Skip to content

Commit

Permalink
#219: Run the shadow map pass before the regular depth fill pass
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Mar 25, 2022
1 parent 943846a commit c00fd79
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 20 deletions.
7 changes: 0 additions & 7 deletions radiantcore/rendersystem/backend/LightInteractions.cpp
Expand Up @@ -158,13 +158,6 @@ void LightInteractions::fillDepthBuffer(OpenGLState& state, GLSLDepthFillAlphaPr

void LightInteractions::drawShadowMap(OpenGLState& state, const Rectangle& rectangle, ShadowMapProgram& program)
{
// Enable GL state and save to state
glDepthMask(true);
state.setRenderFlag(RENDER_DEPTHWRITE);

glDepthFunc(GL_LEQUAL);
state.setDepthFunc(GL_LEQUAL);

// Set up the viewport to write to a specific area within the shadow map texture
glViewport(rectangle.x, rectangle.y, 6 * rectangle.width, rectangle.width);
glClear(GL_DEPTH_BUFFER_BIT);
Expand Down
60 changes: 47 additions & 13 deletions radiantcore/rendersystem/backend/LightingModeRenderer.cpp
Expand Up @@ -13,11 +13,8 @@
namespace render
{

IRenderResult::Ptr LightingModeRenderer::render(RenderStateFlags globalFlagsMask,
const IRenderView& view, std::size_t time)
void LightingModeRenderer::ensureShadowMapSetup()
{
auto result = std::make_shared<LightingModeRenderResult>();

if (!_shadowMapFbo)
{
_shadowMapFbo = FrameBuffer::CreateShadowMapBuffer();
Expand All @@ -38,11 +35,14 @@ IRenderResult::Ptr LightingModeRenderer::render(RenderStateFlags globalFlagsMask
_shadowMapProgram = dynamic_cast<ShadowMapProgram*>(_programFactory.getBuiltInProgram(ShaderProgram::ShadowMap));
assert(_shadowMapProgram);
}
}

// Construct default OpenGL state
OpenGLState current;
setupState(current);
setupViewMatrices(view);
IRenderResult::Ptr LightingModeRenderer::render(RenderStateFlags globalFlagsMask,
const IRenderView& view, std::size_t time)
{
auto result = std::make_shared<LightingModeRenderResult>();

ensureShadowMapSetup();

std::vector<LightInteractions> interactionLists;
interactionLists.reserve(_lights.size());
Expand All @@ -69,6 +69,10 @@ IRenderResult::Ptr LightingModeRenderer::render(RenderStateFlags globalFlagsMask
interactionLists.emplace_back(std::move(interaction));
}

// Construct default OpenGL state
OpenGLState current;
setupState(current);

// Past this point, everything in the geometry store is up to date
_geometryStore.syncToBufferObjects();

Expand All @@ -80,21 +84,37 @@ IRenderResult::Ptr LightingModeRenderer::render(RenderStateFlags globalFlagsMask
// Set the vertex attribute pointers
ObjectRenderer::InitAttributePointers();

result->depthDrawCalls += drawDepthFillPass(current, globalFlagsMask, interactionLists, view, time);

// save viewport
// Draw the shadow maps of each light
// Save the viewport set up in the camera code
GLint previousViewport[4];
glGetIntegerv(GL_VIEWPORT, previousViewport);

_shadowMapProgram->enable();
_shadowMapFbo->bind();

// Enable GL state and save to state
glDepthMask(GL_TRUE);
current.setRenderFlag(RENDER_DEPTHWRITE);

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
// Render a single light to the shadow map buffer
for (auto& interactionList : interactionLists)
{
if (!interactionList.castsShadows()) continue;

interactionList.drawShadowMap(current, _shadowMapAtlas[0], *_shadowMapProgram);
interactionList.drawShadowMap(current, _shadowMapAtlas[3], *_shadowMapProgram);
result->shadowDrawCalls += interactionList.getShadowMapDrawCalls();
break;
}
Expand All @@ -105,6 +125,19 @@ IRenderResult::Ptr LightingModeRenderer::render(RenderStateFlags globalFlagsMask
// 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);

// Run the depth fill pass
result->depthDrawCalls += drawDepthFillPass(current, globalFlagsMask, interactionLists, view, time);

// Draw the surfaces per light and material
auto interactionState = InteractionPass::GenerateInteractionState(_programFactory);

Expand All @@ -125,7 +158,7 @@ IRenderResult::Ptr LightingModeRenderer::render(RenderStateFlags globalFlagsMask
{
// Define which part of the shadow map atlas should be sampled
interactionProgram->enableShadowMapping(true);
interactionProgram->setShadowMapRectangle(_shadowMapAtlas[0]);
interactionProgram->setShadowMapRectangle(_shadowMapAtlas[3]);
}
else
{
Expand All @@ -139,6 +172,7 @@ IRenderResult::Ptr LightingModeRenderer::render(RenderStateFlags globalFlagsMask
// Unbind the shadow map texture
OpenGLState::SetTextureState(current.texture5, 0, GL_TEXTURE5, GL_TEXTURE_2D);

// Draw any surfaces without any light interactions
result->nonInteractionDrawCalls += drawNonInteractionPasses(current, globalFlagsMask, view, time);

cleanupState();
Expand Down
2 changes: 2 additions & 0 deletions radiantcore/rendersystem/backend/LightingModeRenderer.h
Expand Up @@ -56,6 +56,8 @@ class LightingModeRenderer final :

std::size_t drawNonInteractionPasses(OpenGLState& current, RenderStateFlags globalFlagsMask,
const IRenderView& view, std::size_t time);

void ensureShadowMapSetup();
};

}
6 changes: 6 additions & 0 deletions radiantcore/rendersystem/backend/SceneRenderer.cpp
Expand Up @@ -43,6 +43,12 @@ void SceneRenderer::setupState(OpenGLState& state)
{
glPushAttrib(GL_ALL_ATTRIB_BITS);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// global settings that are not set in renderstates
glFrontFace(GL_CW);
glCullFace(GL_BACK);
Expand Down

0 comments on commit c00fd79

Please sign in to comment.