From ddd2e1aad76531d28d4bf634c03b7517288965ab Mon Sep 17 00:00:00 2001 From: Kelsi Date: Mon, 9 Feb 2026 18:51:28 -0800 Subject: [PATCH] Implement LOD shell culling to fix floating cathedral Added distance-based culling for WMO LOD shell groups: - Skip groups with <100 vertices when camera is within 500 units - This hides the simplified 'distant shell' when you're close to buildings Analysis from STORMWIND.WMO logs revealed: - LOD shell: Groups 268/269/271/274 (24-72 verts, flags 0x19xx) - Main cathedral: Group 257 (32,698 verts at 20 units distance) The LOD shell groups are meant for distant viewing only but were rendering at all distances, causing the 'floating cathedral' effect. Fix: Compute distance from camera to each group center and skip rendering low-vertex groups when close. This preserves performance (LOD shells still render from far away) while fixing the visual bug. --- src/rendering/wmo_renderer.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/rendering/wmo_renderer.cpp b/src/rendering/wmo_renderer.cpp index 83562862..5efedde4 100644 --- a/src/rendering/wmo_renderer.cpp +++ b/src/rendering/wmo_renderer.cpp @@ -1008,8 +1008,23 @@ void WMORenderer::render(const Camera& camera, const glm::mat4& view, const glm: loggedStormwindGroups = true; // Only log once to avoid spam } - for (uint32_t gi : dl.visibleGroups) - renderGroup(model.groups[gi], model, instance.modelMatrix, view, projection); + // Render groups with LOD shell culling + glm::vec3 cameraPos = camera.getPosition(); + for (uint32_t gi : dl.visibleGroups) { + const auto& group = model.groups[gi]; + + // LOD shell culling: hide low-detail groups (<100 verts) when camera is close (<500 units) + // This prevents the floating "distant shell" from rendering when you're near the cathedral + glm::vec3 groupCenter = (group.boundingBoxMin + group.boundingBoxMax) * 0.5f; + glm::vec4 worldCenter = instance.modelMatrix * glm::vec4(groupCenter, 1.0f); + float distToGroup = glm::length(cameraPos - glm::vec3(worldCenter)); + + if (group.vertexCount < 100 && distToGroup < 500.0f) { + continue; // Skip LOD shell when close + } + + renderGroup(group, model, instance.modelMatrix, view, projection); + } lastPortalCulledGroups += dl.portalCulled; lastDistanceCulledGroups += dl.distanceCulled;