55#include < bx/string.h>
66#include < glm/matrix.hpp>
77#include < glm/gtc/type_ptr.hpp>
8+ #include < glm/ext/matrix_relational.hpp>
89
910ClusteredRenderer::ClusteredRenderer (const Scene* scene) :
1011 Renderer(scene),
12+ oldProjMat(glm::zero<glm::mat4>()),
1113 clusterBuildingComputeProgram(BGFX_INVALID_HANDLE),
1214 lightCullingComputeProgram(BGFX_INVALID_HANDLE),
1315 lightingProgram(BGFX_INVALID_HANDLE),
@@ -54,20 +56,18 @@ void ClusteredRenderer::onRender(float dt)
5456 vLightCulling,
5557 vLighting
5658 };
57-
59+
5860 bgfx::setViewName (vClusterBuilding, " Cluster building pass (compute)" );
59- // bgfx::setViewClear(vClusterBuilding, BGFX_CLEAR_NONE);
61+ bgfx::setViewClear (vClusterBuilding, BGFX_CLEAR_NONE);
6062 // set u_viewRect for screen2Eye to work correctly
6163 bgfx::setViewRect (vClusterBuilding, 0 , 0 , width, height);
6264 // this could be set by a different renderer, reset it (D3D12 cares and crashes)
6365 bgfx::setViewFrameBuffer (vClusterBuilding, BGFX_INVALID_HANDLE);
64- // bgfx::touch(vClusterBuilding);
6566
6667 bgfx::setViewName (vLightCulling, " Clustered light culling pass (compute)" );
67- // bgfx::setViewClear(vLightCulling, BGFX_CLEAR_NONE);
68+ bgfx::setViewClear (vLightCulling, BGFX_CLEAR_NONE);
6869 bgfx::setViewRect (vLightCulling, 0 , 0 , width, height);
6970 bgfx::setViewFrameBuffer (vLightCulling, BGFX_INVALID_HANDLE);
70- // bgfx::touch(vLightCulling);
7171
7272 bgfx::setViewName (vLighting, " Clustered lighting pass" );
7373 bgfx::setViewClear (vLighting, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, clearColor, 1 .0f , 0 );
@@ -88,24 +88,37 @@ void ClusteredRenderer::onRender(float dt)
8888
8989 // cluster building
9090
91- clusters.bindBuffers (false ); // write access, all buffers
91+ // only run this step if the camera parameters changed (aspect ratio, fov, near/far plane)
92+ // cluster bounds are saved in camera coordinates so they don't change with camera movement
93+
94+ // ideally we'd compare the relative error here but a correct implementation would involve
95+ // a bunch of costly matrix operations: https://floating-point-gui.de/errors/comparison/
96+ // comparing the absolute error against a rather small epsilon here works as long as the values
97+ // in the projection matrix aren't getting too large
98+ bool buildClusters = glm::any (glm::notEqual (projMat, oldProjMat, 0 .00001f ));
99+ if (buildClusters)
100+ {
101+ oldProjMat = projMat;
102+
103+ clusters.bindBuffers (false ); // write access, all buffers
92104
93- bgfx::dispatch (vClusterBuilding,
94- clusterBuildingComputeProgram,
95- ClusterShader::CLUSTERS_X,
96- ClusterShader::CLUSTERS_Y,
97- ClusterShader::CLUSTERS_Z);
105+ bgfx::dispatch (vClusterBuilding,
106+ clusterBuildingComputeProgram,
107+ ClusterShader::CLUSTERS_X / ClusterShader::CLUSTERS_X_THREADS,
108+ ClusterShader::CLUSTERS_Y / ClusterShader::CLUSTERS_Y_THREADS,
109+ ClusterShader::CLUSTERS_Z / ClusterShader::CLUSTERS_Z_THREADS);
110+ }
98111
99112 // light culling
100113
101114 lights.bindLights (scene);
102115 clusters.bindBuffers (false ); // write access, all buffers
103116
104117 bgfx::dispatch (vLightCulling,
105- lightCullingComputeProgram,
106- ClusterShader::CLUSTERS_X / ClusterShader::CLUSTERS_X_THREADS,
107- ClusterShader::CLUSTERS_Y / ClusterShader::CLUSTERS_Y_THREADS,
108- ClusterShader::CLUSTERS_Z / ClusterShader::CLUSTERS_Z_THREADS);
118+ lightCullingComputeProgram,
119+ ClusterShader::CLUSTERS_X / ClusterShader::CLUSTERS_X_THREADS,
120+ ClusterShader::CLUSTERS_Y / ClusterShader::CLUSTERS_Y_THREADS,
121+ ClusterShader::CLUSTERS_Z / ClusterShader::CLUSTERS_Z_THREADS);
109122 // lighting
110123
111124 bool debugVis = variables[" DEBUG_VIS" ] == " true" ;
0 commit comments