diff --git a/install/gl/shadowmap_vp.glsl b/install/gl/shadowmap_vp.glsl index 8238e2baa4..91bdaaa1e7 100644 --- a/install/gl/shadowmap_vp.glsl +++ b/install/gl/shadowmap_vp.glsl @@ -12,6 +12,7 @@ uniform vec4 u_DiffuseTextureMatrix[2]; // The final diffuse texture coordinate at this vertex varying vec2 var_TexDiffuse; +// The modelview matrices for each of the 6 cube map faces const mat3 cubicTransformations[6] = mat3[6] ( mat3(0, 0, -1, @@ -39,6 +40,17 @@ const mat3 cubicTransformations[6] = mat3[6] 0, 0, 1) ); +// These 4 clip planes are 45 degrees planes passing the origin (opening towards negative z) +// bounding the view frustum of a point light at 0,0,0 +const float clipEps = 0e-2; +const vec4 ClipPlanes[4] = vec4[4] +( + vec4(1, 0, -1, clipEps), + vec4(-1, 0, -1, clipEps), + vec4(0, 1, -1, clipEps), + vec4(0, -1, -1, clipEps) +); + void main() { // Transform the model vertex to world space, then subtract the light origin @@ -46,10 +58,20 @@ void main() vec4 lightSpacePos = u_ObjectTransform * attr_Position; lightSpacePos.xyz -= u_LightOrigin; + // Render the vertex 6 times, once for each cubemap face (gl_InstanceID = [0..5]) + // This is just a rotation, no scaling or projection involved vec4 fragPos = vec4(cubicTransformations[gl_InstanceID] * lightSpacePos.xyz, 1); gl_Position.x = fragPos.x / 6 + fragPos.z * 5/6 - fragPos.z / 3 * gl_InstanceID; gl_Position.y = fragPos.y; gl_Position.z = -fragPos.z - 2; gl_Position.w = -fragPos.z; + + // To clip the vertices outside the view frustum, calculate its clip distance + // every fragment with a distance < 0 will be discarded + // This relies on the GL_CLIP_DISTANCE0-3 flags activated in the renderer code + gl_ClipDistance[0] = dot(fragPos, ClipPlanes[0]); + gl_ClipDistance[1] = dot(fragPos, ClipPlanes[1]); + gl_ClipDistance[2] = dot(fragPos, ClipPlanes[2]); + gl_ClipDistance[3] = dot(fragPos, ClipPlanes[3]); } diff --git a/radiantcore/rendersystem/backend/LightingModeRenderer.cpp b/radiantcore/rendersystem/backend/LightingModeRenderer.cpp index d9ffeffbfd..b2f13c35ad 100644 --- a/radiantcore/rendersystem/backend/LightingModeRenderer.cpp +++ b/radiantcore/rendersystem/backend/LightingModeRenderer.cpp @@ -99,16 +99,18 @@ IRenderResult::Ptr LightingModeRenderer::render(RenderStateFlags globalFlagsMask glDepthFunc(GL_LEQUAL); current.setDepthFunc(GL_LEQUAL); -#if 1 glEnable(GL_DEPTH_TEST); current.setRenderFlag(RENDER_DEPTHTEST); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); current.setRenderFlag(RENDER_FILL); -#endif -#if 0 - glPolygonOffset(0, 0); - glEnable(GL_POLYGON_OFFSET_FILL); -#endif + + // Enable the 4 clip planes, they are used in the vertex shader + glEnable(GL_CLIP_DISTANCE0); + glEnable(GL_CLIP_DISTANCE1); + glEnable(GL_CLIP_DISTANCE2); + glEnable(GL_CLIP_DISTANCE3); + // Render a single light to the shadow map buffer for (auto& interactionList : interactionLists) { @@ -122,16 +124,17 @@ IRenderResult::Ptr LightingModeRenderer::render(RenderStateFlags globalFlagsMask _shadowMapFbo->unbind(); _shadowMapProgram->disable(); + glDisable(GL_CLIP_DISTANCE3); + glDisable(GL_CLIP_DISTANCE2); + glDisable(GL_CLIP_DISTANCE1); + glDisable(GL_CLIP_DISTANCE0); + // Restore view port glViewport(previousViewport[0], previousViewport[1], previousViewport[2], previousViewport[3]); -#if 0 - glDisable(GL_POLYGON_OFFSET_FILL); -#endif -#if 1 glDisable(GL_DEPTH_TEST); current.clearRenderFlag(RENDER_DEPTHTEST); -#endif + // Load the model view & projection matrix for the main scene setupViewMatrices(view);