// ---------------------------- Render Lights ----------------------------
// Query visible lights
std::vector<OctreeOccupant*> result;
m_lightSPT.Query_Frustum(result, pScene->GetFrustum());
glEnable(GL_VERTEX_ARRAY);
glEnable(GL_STENCIL_TEST);
glClearStencil(0);
for(unsigned int i = 0, size = result.size(); i < size;)
{
glClear(GL_STENCIL_BUFFER_BIT);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glColorMask(false, false, false, false);
// Batch 8 lights together
unsigned int firstLightIndex = i;
for(unsigned int j = 0; j < 8 && i < size; j++, i++)
{
glStencilFunc(GL_ALWAYS, 0xff, 0xff);
glStencilMask(m_lightIndices[j]);
Light* pLight = static_cast<Light*>(result[i]);
if(!pLight->m_enabled)
continue;
pLight->SetTransform(pScene);
pLight->RenderBoundingGeom();
}
i = firstLightIndex;
glColorMask(true, true, true, true);
// Now render with reversed depth testing and only to stenciled regions
glCullFace(GL_FRONT);
glDepthFunc(GL_GREATER);
glEnable(GL_BLEND);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
for(unsigned int j = 0; j < 8 && i < size; j++, i++)
{
glStencilFunc(GL_EQUAL, 0xff, m_lightIndices[j]);
Light* pLight = static_cast<Light*>(result[i]);
if(!pLight->m_enabled)
continue;
// If camera is inside light, do not perform depth test (would cull it away improperly)
if(pLight->Intersects(pScene->m_camera.m_position))
{
glDisable(GL_STENCIL_TEST);
pLight->SetTransform(pScene);
pLight->SetShader(pScene);
pLight->RenderBoundingGeom();
glEnable(GL_STENCIL_TEST);
}
else
{
pLight->SetTransform(pScene);
pLight->SetShader(pScene);
pLight->RenderBoundingGeom();
}
}
glCullFace(GL_BACK);
glDepthFunc(GL_LESS);
glDisable(GL_BLEND);
Shader::Unbind();
}
// Re-enable stencil writes to all bits
glStencilMask(0xff);
glDisable(GL_VERTEX_ARRAY);
glDisable(GL_STENCIL_TEST);
GL_ERROR_CHECK();