From ffbd40a236c8d0ed5d1137e34245bbb01849b59e Mon Sep 17 00:00:00 2001 From: Turanszki Janos Date: Sun, 30 Aug 2020 00:12:58 +0200 Subject: [PATCH] frustum culling optimization --- WickedEngine/wiIntersect.cpp | 16 ++++++++++++++++ WickedEngine/wiIntersect.h | 1 + WickedEngine/wiRenderer.cpp | 22 +++++++++++----------- WickedEngine/wiVersion.cpp | 2 +- 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/WickedEngine/wiIntersect.cpp b/WickedEngine/wiIntersect.cpp index 17e9d4ae0..fecd0a117 100644 --- a/WickedEngine/wiIntersect.cpp +++ b/WickedEngine/wiIntersect.cpp @@ -358,6 +358,22 @@ Frustum::BoxFrustumIntersect Frustum::CheckBox(const AABB& box) const return(BOX_FRUSTUM_INSIDE); return(BOX_FRUSTUM_INTERSECTS); } +bool Frustum::CheckBoxFast(const AABB& box) const +{ + XMVECTOR max = XMLoadFloat3(&box._max); + XMVECTOR min = XMLoadFloat3(&box._min); + XMVECTOR zero = XMVectorZero(); + for (size_t p = 0; p < 6; ++p) + { + auto lt = XMVectorLess(XMLoadFloat4(&planes[p]), zero); + auto furthestFromPlane = XMVectorSelect(max, min, lt); + if (XMVectorGetX(XMPlaneDotCoord(XMLoadFloat4(&planes[p]), furthestFromPlane)) < 0.0f) + { + return false; + } + } + return true; +} const XMFLOAT4& Frustum::getNearPlane() const { return planes[0]; } const XMFLOAT4& Frustum::getFarPlane() const { return planes[1]; } diff --git a/WickedEngine/wiIntersect.h b/WickedEngine/wiIntersect.h index 1e4173273..ae6b4fda7 100644 --- a/WickedEngine/wiIntersect.h +++ b/WickedEngine/wiIntersect.h @@ -123,6 +123,7 @@ public: BOX_FRUSTUM_INSIDE, }; BoxFrustumIntersect CheckBox(const AABB& box) const; + bool CheckBoxFast(const AABB& box) const; const XMFLOAT4& getNearPlane() const; const XMFLOAT4& getFarPlane() const; diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index f568d8804..1351aaa23 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -3230,7 +3230,7 @@ void RenderMeshes( for (uint32_t frustum_index = 0; frustum_index < frustum_count; ++frustum_index) { - if (frusta != nullptr && !frusta[frustum_index].CheckBox(instanceAABB)) + if (frusta != nullptr && !frusta[frustum_index].CheckBoxFast(instanceAABB)) { // In case shadow cameras were provided and no intersection detected with frustum, we don't add the instance for the face: continue; @@ -3607,7 +3607,7 @@ void RenderImpostors( for (size_t impostorID = 0; impostorID < scene.impostors.GetCount(); ++impostorID) { const ImpostorComponent& impostor = scene.impostors[impostorID]; - if (camera.frustum.CheckBox(impostor.aabb)) + if (camera.frustum.CheckBoxFast(impostor.aabb)) { instanceCount += (uint32_t)impostor.instanceMatrices.size(); } @@ -3629,7 +3629,7 @@ void RenderImpostors( for (size_t impostorID = 0; impostorID < scene.impostors.GetCount(); ++impostorID) { const ImpostorComponent& impostor = scene.impostors[impostorID]; - if (!camera.frustum.CheckBox(impostor.aabb)) + if (!camera.frustum.CheckBoxFast(impostor.aabb)) { continue; } @@ -3898,7 +3898,7 @@ void UpdatePerFrameData(float dt, uint32_t layerMask) group_count = 0; // first thread initializes local counter } - if (culling.frustum.CheckBox(aabb)) + if (culling.frustum.CheckBoxFast(aabb)) { // Local stream compaction: group_list[group_count++] = args.jobIndex; @@ -3963,7 +3963,7 @@ void UpdatePerFrameData(float dt, uint32_t layerMask) group_count = 0; // first thread initializes local counter } - if (culling.frustum.CheckBox(aabb)) + if (culling.frustum.CheckBoxFast(aabb)) { // Local stream compaction: group_list[group_count++] = args.jobIndex; @@ -3994,7 +3994,7 @@ void UpdatePerFrameData(float dt, uint32_t layerMask) const AABB& aabb = scene.aabb_probes[i]; - if (culling.frustum.CheckBox(aabb)) + if (culling.frustum.CheckBoxFast(aabb)) { culling.culledEnvProbes.push_back((uint32_t)i); } @@ -4022,7 +4022,7 @@ void UpdatePerFrameData(float dt, uint32_t layerMask) group_count = 0; // first thread initializes local counter } - if (culling.frustum.CheckBox(aabb)) + if (culling.frustum.CheckBoxFast(aabb)) { // Local stream compaction: group_list[group_count++] = args.jobIndex; @@ -4066,7 +4066,7 @@ void UpdatePerFrameData(float dt, uint32_t layerMask) } const wiHairParticle& hair = scene.hairs[i]; - if (hair.meshID == INVALID_ENTITY || !culling.frustum.CheckBox(hair.aabb)) + if (hair.meshID == INVALID_ENTITY || !culling.frustum.CheckBoxFast(hair.aabb)) { continue; } @@ -5532,7 +5532,7 @@ void DrawShadowmaps(const CameraComponent& camera, CommandList cmd, uint32_t lay for (size_t i = 0; i < scene.aabb_objects.GetCount(); ++i) { const AABB& aabb = scene.aabb_objects[i]; - if (shcams[cascade].frustum.CheckBox(aabb)) + if (shcams[cascade].frustum.CheckBoxFast(aabb)) { const ObjectComponent& object = scene.objects[i]; if (object.IsRenderable() && cascade >= object.cascadeMask && object.IsCastingShadow()) @@ -5601,7 +5601,7 @@ void DrawShadowmaps(const CameraComponent& camera, CommandList cmd, uint32_t lay for (size_t i = 0; i < scene.aabb_objects.GetCount(); ++i) { const AABB& aabb = scene.aabb_objects[i]; - if (shcam.frustum.CheckBox(aabb)) + if (shcam.frustum.CheckBoxFast(aabb)) { const ObjectComponent& object = scene.objects[i]; if (object.IsRenderable() && object.IsCastingShadow()) @@ -7008,7 +7008,7 @@ void DrawDeferredDecals( const DecalComponent& decal = scene.decals[decalIndex]; const AABB& aabb = scene.aabb_decals[decalIndex]; - if ((decal.texture != nullptr || decal.normal != nullptr) && camera.frustum.CheckBox(aabb)) + if ((decal.texture != nullptr || decal.normal != nullptr) && camera.frustum.CheckBoxFast(aabb)) { device->BindResource(PS, decal.texture != nullptr ? decal.texture->texture : nullptr, TEXSLOT_ONDEMAND0, cmd); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index c7a434693..2b66764d4 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates, breaking API changes const int minor = 47; // minor bug fixes, alterations, refactors, updates - const int revision = 24; + const int revision = 25; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);