Add shadow frustum culling to terrain and M2 depth passes

Both passes were rendering the entire loaded scene (17×17 tile radius)
into a shadow map that only covers 360×360 world units — submitting
10-50× more geometry than the shadow frustum can actually use.

- TerrainRenderer::renderShadow: skip chunks whose bounding sphere
  doesn't overlap the shadow frustum AABB in XY. Reduces terrain draw
  calls from O(all loaded chunks) to O(chunks within ~180 units).
- M2Renderer::renderShadow: skip instances whose world AABB doesn't
  overlap the shadow frustum in XY. Reduces M2 draw calls similarly.
- Both functions now take shadowCenter + halfExtent parameters.
This commit is contained in:
Kelsi 2026-02-18 21:15:24 -08:00
parent c4d0a21713
commit 514b914068
5 changed files with 23 additions and 8 deletions

View file

@ -369,7 +369,7 @@ GLuint TerrainRenderer::createAlphaTexture(const std::vector<uint8_t>& alphaData
return textureID;
}
void TerrainRenderer::renderShadow(GLuint shaderProgram) {
void TerrainRenderer::renderShadow(GLuint shaderProgram, const glm::vec3& shadowCenter, float halfExtent) {
if (chunks.empty()) return;
GLint modelLoc = glGetUniformLocation(shaderProgram, "uModel");
@ -378,6 +378,13 @@ void TerrainRenderer::renderShadow(GLuint shaderProgram) {
for (const auto& chunk : chunks) {
if (!chunk.isValid()) continue;
// Cull chunks whose bounding sphere doesn't overlap the shadow frustum (XY plane)
float maxDist = halfExtent + chunk.boundingSphereRadius;
float dx = chunk.boundingSphereCenter.x - shadowCenter.x;
float dy = chunk.boundingSphereCenter.y - shadowCenter.y;
if (dx * dx + dy * dy > maxDist * maxDist) continue;
glBindVertexArray(chunk.vao);
glDrawElements(GL_TRIANGLES, chunk.indexCount, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);