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

@ -2151,7 +2151,7 @@ void M2Renderer::render(const Camera& camera, const glm::mat4& view, const glm::
}
}
void M2Renderer::renderShadow(GLuint shadowShaderProgram) {
void M2Renderer::renderShadow(GLuint shadowShaderProgram, const glm::vec3& shadowCenter, float halfExtent) {
if (instances.empty() || shadowShaderProgram == 0) {
return;
}
@ -2172,6 +2172,12 @@ void M2Renderer::renderShadow(GLuint shadowShaderProgram) {
glActiveTexture(GL_TEXTURE0);
for (const auto& instance : instances) {
// Cull instances whose AABB doesn't overlap the shadow frustum (XY plane)
glm::vec3 instCenter = (instance.worldBoundsMin + instance.worldBoundsMax) * 0.5f;
glm::vec3 instHalf = (instance.worldBoundsMax - instance.worldBoundsMin) * 0.5f;
if (std::abs(instCenter.x - shadowCenter.x) > halfExtent + instHalf.x) continue;
if (std::abs(instCenter.y - shadowCenter.y) > halfExtent + instHalf.y) continue;
auto it = models.find(instance.modelId);
if (it == models.end()) continue;