impostor system revived

This commit is contained in:
turanszkij
2018-09-26 21:54:49 +01:00
parent e1aaab09a3
commit 3f88eae324
9 changed files with 704 additions and 563 deletions
+11 -5
View File
@@ -105,7 +105,8 @@ MeshWindow::MeshWindow(wiGUI* gui) : GUI(gui)
MeshComponent* mesh = wiRenderer::GetScene().meshes.GetComponent(entity);
if (mesh != nullptr)
{
wiRenderer::CreateImpostor(entity, GRAPHICSTHREAD_IMMEDIATE);
Scene& scene = wiRenderer::GetScene();
scene.impostors.Create(entity).swapInDistance = impostorDistanceSlider->GetValue();
}
});
meshWindow->AddWidget(impostorCreateButton);
@@ -115,10 +116,10 @@ MeshWindow::MeshWindow(wiGUI* gui) : GUI(gui)
impostorDistanceSlider->SetSize(XMFLOAT2(100, 30));
impostorDistanceSlider->SetPos(XMFLOAT2(x, y += step));
impostorDistanceSlider->OnSlide([&](wiEventArgs args) {
MeshComponent* mesh = wiRenderer::GetScene().meshes.GetComponent(entity);
if (mesh != nullptr)
ImpostorComponent* impostor = wiRenderer::GetScene().impostors.GetComponent(entity);
if (impostor != nullptr)
{
mesh->impostorDistance = args.fValue;
impostor->swapInDistance = args.fValue;
}
});
meshWindow->AddWidget(impostorDistanceSlider);
@@ -229,7 +230,12 @@ void MeshWindow::SetEntity(Entity entity)
meshInfoLabel->SetText(ss.str());
doubleSidedCheckBox->SetCheck(mesh->IsDoubleSided());
impostorDistanceSlider->SetValue(mesh->impostorDistance);
const ImpostorComponent* impostor = scene.impostors.GetComponent(entity);
if (impostor != nullptr)
{
impostorDistanceSlider->SetValue(impostor->swapInDistance);
}
tessellationFactorSlider->SetValue(mesh->GetTessellationFactor());
SoftBodyPhysicsComponent* physicscomponent = wiRenderer::GetScene().softbodies.GetComponent(entity);
+2
View File
@@ -226,6 +226,8 @@ void wiEmittedParticle::Restart()
//#define DEBUG_SORTING // slow but great for debug!!
void wiEmittedParticle::UpdateRenderData(const TransformComponent& transform, const MaterialComponent& material, const MeshComponent* mesh, GRAPHICSTHREAD threadID)
{
center = transform.GetPosition();
CreateSelfBuffers();
GraphicsDevice* device = wiRenderer::GetDevice();
+3
View File
@@ -115,6 +115,9 @@ public:
uint32_t GetMaxParticleCount() const { return MAX_PARTICLES; }
uint32_t GetMemorySizeInBytes() const;
// Non-serialized attributes:
XMFLOAT3 center;
inline bool IsDebug() const { return _flags & DEBUG; }
inline bool IsPaused() const { return _flags & PAUSED; }
inline bool IsSorted() const { return _flags & SORTING; }
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -99,6 +99,7 @@ namespace wiRenderer
void DrawLensFlares(GRAPHICSTHREAD threadID);
void DrawDecals(const wiSceneSystem::CameraComponent& camera, GRAPHICSTHREAD threadID);
void RefreshEnvProbes(GRAPHICSTHREAD threadID);
void RefreshImpostors(GRAPHICSTHREAD threadID);
void VoxelRadiance(GRAPHICSTHREAD threadID);
void ComputeTiledLightCulling(bool deferred, GRAPHICSTHREAD threadID);
void ResolveMSAADepthBuffer(wiGraphicsTypes::Texture2D* dst, wiGraphicsTypes::Texture2D* src, GRAPHICSTHREAD threadID);
@@ -138,7 +139,6 @@ namespace wiRenderer
void GenerateClouds(wiGraphicsTypes::Texture2D* dst, UINT refinementCount, float randomness, GRAPHICSTHREAD threadID);
void ManageDecalAtlas(GRAPHICSTHREAD threadID);
void CreateImpostor(wiECS::Entity, GRAPHICSTHREAD threadID);
void PutWaterRipple(const std::string& image, const XMFLOAT3& pos);
void ManageWaterRipples();
+36 -2
View File
@@ -824,7 +824,9 @@ namespace wiSceneSystem
RunMaterialUpdateSystem(materials, dt);
RunObjectUpdateSystem(transforms, meshes, materials, objects, aabb_objects, bounds, waterPlane);
RunImpostorUpdateSystem(impostors);
RunObjectUpdateSystem(transforms, meshes, materials, objects, aabb_objects, impostors, bounds, waterPlane);
RunCameraUpdateSystem(transforms, cameras);
@@ -847,6 +849,7 @@ namespace wiSceneSystem
hierarchy.Clear();
materials.Clear();
meshes.Clear();
impostors.Clear();
objects.Clear();
aabb_objects.Clear();
rigidbodies.Clear();
@@ -874,6 +877,7 @@ namespace wiSceneSystem
hierarchy.Merge(other.hierarchy);
materials.Merge(other.materials);
meshes.Merge(other.meshes);
impostors.Merge(other.impostors);
objects.Merge(other.objects);
aabb_objects.Merge(other.aabb_objects);
rigidbodies.Merge(other.rigidbodies);
@@ -906,6 +910,7 @@ namespace wiSceneSystem
entityCount = max(entityCount, hierarchy.GetCount());
entityCount = max(entityCount, materials.GetCount());
entityCount = max(entityCount, meshes.GetCount());
entityCount = max(entityCount, impostors.GetCount());
entityCount = max(entityCount, objects.GetCount());
entityCount = max(entityCount, aabb_objects.GetCount());
entityCount = max(entityCount, rigidbodies.GetCount());
@@ -934,6 +939,7 @@ namespace wiSceneSystem
hierarchy.Remove_KeepSorted(entity);
materials.Remove(entity);
meshes.Remove(entity);
impostors.Remove(entity);
objects.Remove(entity);
aabb_objects.Remove(entity);
rigidbodies.Remove(entity);
@@ -1500,12 +1506,22 @@ namespace wiSceneSystem
}
}
void RunImpostorUpdateSystem(ComponentManager<ImpostorComponent>& impostors)
{
for (size_t i = 0; i < impostors.GetCount(); ++i)
{
ImpostorComponent& impostor = impostors[i];
impostor.aabb = AABB();
impostor.instanceMatrices.clear();
}
}
void RunObjectUpdateSystem(
const ComponentManager<TransformComponent>& transforms,
const ComponentManager<MeshComponent>& meshes,
const ComponentManager<MaterialComponent>& materials,
ComponentManager<ObjectComponent>& objects,
ComponentManager<AABB>& aabb_objects,
ComponentManager<ImpostorComponent>& impostors,
AABB& sceneBounds,
XMFLOAT4& waterPlane
)
@@ -1523,6 +1539,7 @@ namespace wiSceneSystem
object.rendertypeMask = 0;
object.SetDynamic(false);
object.SetCastShadow(false);
object.SetImpostorPlacement(false);
if (object.meshID != INVALID_ENTITY)
{
@@ -1535,7 +1552,12 @@ namespace wiSceneSystem
aabb = mesh->aabb.get(transform->world);
sceneBounds = AABB::Merge(sceneBounds, aabb);
object.position = transform->GetPosition();
// This is instance bounding box matrix:
XMFLOAT4X4 meshMatrix;
XMStoreFloat4x4(&meshMatrix, mesh->aabb.getAsBoxMatrix() * XMLoadFloat4x4(&transform->world));
// We need sometimes the center of the instance bounding box, not the transform position (which can be outside the bounding box)
object.center = *((XMFLOAT3*)&meshMatrix._41);
if (mesh->IsSkinned() || mesh->IsDynamic())
{
@@ -1568,6 +1590,18 @@ namespace wiSceneSystem
object.SetCastShadow(material->IsCastingShadow());
}
}
ImpostorComponent* impostor = impostors.GetComponent(object.meshID);
if (impostor != nullptr)
{
object.SetImpostorPlacement(true);
object.impostorSwapDistance = impostor->swapInDistance;
object.impostorFadeThresholdRadius = aabb.getRadius();
impostor->aabb = AABB::Merge(impostor->aabb, aabb);
impostor->fadeThresholdRadius = object.impostorFadeThresholdRadius;
impostor->instanceMatrices.push_back(meshMatrix);
}
}
}
}
+33 -7
View File
@@ -160,9 +160,7 @@ namespace wiSceneSystem
inline float GetOpacity() const { return baseColor.w; }
inline void SetDirty() { _flags |= DIRTY; }
inline void SetClean() { _flags &= ~DIRTY; }
inline void SetDirty(bool value = true) { if (value) { _flags |= DIRTY; } else { _flags &= ~DIRTY; } }
inline bool IsDirty() const { return _flags & DIRTY; }
inline void SetCastShadow(bool value) { if (value) { _flags |= CAST_SHADOW; } else { _flags &= ~CAST_SHADOW; } }
@@ -219,7 +217,6 @@ namespace wiSceneSystem
std::vector<MeshSubset> subsets;
float tessellationFactor = 0.0f;
float impostorDistance = 100.0f;
wiECS::Entity armatureID = wiECS::INVALID_ENTITY;
// Non-serialized attributes:
@@ -232,7 +229,6 @@ namespace wiSceneSystem
std::unique_ptr<wiGraphicsTypes::GPUBuffer> vertexBuffer_ATL;
std::unique_ptr<wiGraphicsTypes::GPUBuffer> streamoutBuffer_POS;
std::unique_ptr<wiGraphicsTypes::GPUBuffer> streamoutBuffer_PRE;
wiRenderTarget impostorTarget;
inline void SetRenderable(bool value) { if (value) { _flags |= RENDERABLE; } else { _flags &= ~RENDERABLE; } }
@@ -243,7 +239,6 @@ namespace wiSceneSystem
inline bool IsDoubleSided() const { return _flags & DOUBLE_SIDED; }
inline bool IsDynamic() const { return _flags & DYNAMIC; }
bool HasImpostor() const { return impostorTarget.IsInitialized(); }
inline float GetTessellationFactor() const { return tessellationFactor; }
inline wiGraphicsTypes::INDEXBUFFER_FORMAT GetIndexFormat() const { return vertex_positions.size() > 65535 ? wiGraphicsTypes::INDEXFORMAT_32BIT : wiGraphicsTypes::INDEXFORMAT_16BIT; }
inline bool IsSkinned() const { return armatureID != wiECS::INVALID_ENTITY; }
@@ -369,6 +364,29 @@ namespace wiSceneSystem
};
struct ImpostorComponent
{
enum FLAGS
{
EMPTY = 0,
DIRTY = 1 << 0,
};
uint32_t _flags = DIRTY;
float swapInDistance = 100.0f;
// Non-serialized attributes:
AABB aabb;
wiRenderTarget rendertarget; // todo: combine all impostors into atlas/texture2darray
float fadeThresholdRadius;
std::vector<XMFLOAT4X4> instanceMatrices;
inline void SetDirty(bool value = true) { if (value) { _flags |= DIRTY; } else { _flags &= ~DIRTY; } }
inline bool IsDirty() const { return _flags & DIRTY; }
void Serialize(wiArchive& archive, uint32_t seed = 0);
};
struct ObjectComponent
{
enum FLAGS
@@ -377,6 +395,7 @@ namespace wiSceneSystem
RENDERABLE = 1 << 0,
CAST_SHADOW = 1 << 1,
DYNAMIC = 1 << 2,
IMPOSTOR_PLACEMENT = 1 << 3,
};
uint32_t _flags = RENDERABLE | CAST_SHADOW;
@@ -387,7 +406,9 @@ namespace wiSceneSystem
// Non-serialized attributes:
XMFLOAT3 position = XMFLOAT3(0, 0, 0);
XMFLOAT3 center = XMFLOAT3(0, 0, 0);
float impostorFadeThresholdRadius;
float impostorSwapDistance;
// occlusion result history bitfield (32 bit->32 frame history)
uint32_t occlusionHistory = ~0;
@@ -406,10 +427,12 @@ namespace wiSceneSystem
inline void SetRenderable(bool value) { if (value) { _flags |= RENDERABLE; } else { _flags &= ~RENDERABLE; } }
inline void SetCastShadow(bool value) { if (value) { _flags |= CAST_SHADOW; } else { _flags &= ~CAST_SHADOW; } }
inline void SetDynamic(bool value) { if (value) { _flags |= DYNAMIC; } else { _flags &= ~DYNAMIC; } }
inline void SetImpostorPlacement(bool value) { if (value) { _flags |= IMPOSTOR_PLACEMENT; } else { _flags &= ~IMPOSTOR_PLACEMENT; } }
inline bool IsRenderable() const { return _flags & RENDERABLE; }
inline bool IsCastingShadow() const { return _flags & CAST_SHADOW; }
inline bool IsDynamic() const { return _flags & DYNAMIC; }
inline bool IsImpostorPlacement() const { return _flags & IMPOSTOR_PLACEMENT; }
inline float GetTransparency() const { return 1 - color.w; }
inline uint32_t GetRenderTypes() const { return rendertypeMask; }
@@ -884,6 +907,7 @@ namespace wiSceneSystem
wiECS::ComponentManager<HierarchyComponent> hierarchy;
wiECS::ComponentManager<MaterialComponent> materials;
wiECS::ComponentManager<MeshComponent> meshes;
wiECS::ComponentManager<ImpostorComponent> impostors;
wiECS::ComponentManager<ObjectComponent> objects;
wiECS::ComponentManager<AABB> aabb_objects;
wiECS::ComponentManager<RigidBodyPhysicsComponent> rigidbodies;
@@ -1001,12 +1025,14 @@ namespace wiSceneSystem
wiECS::ComponentManager<ArmatureComponent>& armatures
);
void RunMaterialUpdateSystem(wiECS::ComponentManager<MaterialComponent>& materials, float dt);
void RunImpostorUpdateSystem(wiECS::ComponentManager<ImpostorComponent>& impostors);
void RunObjectUpdateSystem(
const wiECS::ComponentManager<TransformComponent>& transforms,
const wiECS::ComponentManager<MeshComponent>& meshes,
const wiECS::ComponentManager<MaterialComponent>& materials,
wiECS::ComponentManager<ObjectComponent>& objects,
wiECS::ComponentManager<AABB>& aabb_objects,
wiECS::ComponentManager<ImpostorComponent>& impostors,
AABB& sceneBounds,
XMFLOAT4& waterPlane
);
+1
View File
@@ -10,6 +10,7 @@ namespace wiSceneSystem
struct HierarchyComponent;
struct MaterialComponent;
struct MeshComponent;
struct ImpostorComponent;
struct ObjectComponent;
struct RigidBodyPhysicsComponent;
struct SoftBodyPhysicsComponent;
+37 -2
View File
@@ -173,7 +173,6 @@ namespace wiSceneSystem
}
archive >> tessellationFactor;
archive >> impostorDistance;
SerializeEntity(archive, armatureID, seed);
CreateRenderData();
@@ -199,11 +198,25 @@ namespace wiSceneSystem
}
archive << tessellationFactor;
archive << impostorDistance;
SerializeEntity(archive, armatureID, seed);
}
}
void ImpostorComponent::Serialize(wiArchive& archive, uint32_t seed)
{
if (archive.IsReadMode())
{
archive >> _flags;
archive >> swapInDistance;
SetDirty();
}
else
{
archive << _flags;
archive << swapInDistance;
}
}
void ObjectComponent::Serialize(wiArchive& archive, uint32_t seed)
{
if (archive.IsReadMode())
@@ -512,6 +525,7 @@ namespace wiSceneSystem
hierarchy.Serialize(archive, seed);
materials.Serialize(archive, seed);
meshes.Serialize(archive, seed);
impostors.Serialize(archive, seed);
objects.Serialize(archive, seed);
aabb_objects.Serialize(archive, seed);
rigidbodies.Serialize(archive, seed);
@@ -602,6 +616,15 @@ namespace wiSceneSystem
component.Serialize(archive, propagateSeedDeep ? seed : 0);
}
}
{
bool component_exists;
archive >> component_exists;
if (component_exists)
{
auto& component = impostors.Create(entity);
component.Serialize(archive, propagateSeedDeep ? seed : 0);
}
}
{
bool component_exists;
archive >> component_exists;
@@ -843,6 +866,18 @@ namespace wiSceneSystem
archive << false;
}
}
{
auto component = impostors.GetComponent(entity);
if (component != nullptr)
{
archive << true;
component->Serialize(archive, seed);
}
else
{
archive << false;
}
}
{
auto component = objects.GetComponent(entity);
if (component != nullptr)