MCPcopy Create free account
hub / github.com/BohemiaInteractive/CWR / RenderCascadeArray

Function RenderCascadeArray

engine/PoseidonGL33/EngineGL33_ShadowDepth.cpp:315–400  ·  view source on GitHub ↗

Render the casters into each cascade layer of the depth array, once per cascade with that cascade's light-VP: solid triangles with the depth-only program, then the alpha-cutout batches with the texture-alpha-discard program (one bind per caster texture). Depth/clear go through the Core bundles so the GL-state audits stay green; ApplyPipeline re-owns depth/cull/texture on the next draw.

Source from the content-addressed store, hash-verified

313// caster texture). Depth/clear go through the Core bundles so the GL-state audits
314// stay green; ApplyPipeline re-owns depth/cull/texture on the next draw.
315bool RenderCascadeArray(void* glContext, const float* lightVPs, int numCascades, int res, const float* solidXYZ,
316 int solidVertCount, const float* alphaXYZUV, int alphaVertCount,
317 const ResolvedAlphaBatch* batches, int batchCount)
318{
319 const bool haveSolid = solidXYZ && solidVertCount >= 3;
320 const bool haveAlpha = alphaXYZUV && alphaVertCount >= 3 && batches && batchCount > 0;
321 if (!glContext || !lightVPs || res <= 0 || numCascades < 1 || (!haveSolid && !haveAlpha))
322 return false;
323 if (!EnsureProgram() || !EnsureArrayTarget(res, numCascades) || !EnsureMesh())
324 return false;
325 if (haveAlpha && (!EnsureAlphaProgram() || !EnsureAlphaMesh()))
326 return false;
327
328 GLint prevFBO = 0, prevProg = 0, prevVAO = 0, prevArrayBuf = 0;
329 GLint prevVP[4] = {0, 0, 0, 0};
330 glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prevFBO);
331 glGetIntegerv(GL_CURRENT_PROGRAM, &prevProg);
332 glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &prevVAO);
333 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &prevArrayBuf);
334 glGetIntegerv(GL_VIEWPORT, prevVP);
335
336 glBindFramebuffer(GL_FRAMEBUFFER, s_arrFbo);
337 glViewport(0, 0, res, res);
338 Poseidon::render::depthstencil::Normal(/*hasStencil*/ false);
339 Poseidon::render::cull::None();
340
341 // Upload the (cascade-invariant) geometry once; only the light-VP changes per layer.
342 if (haveSolid)
343 {
344 GL33Bind::Vao(s_vao);
345 glBindBuffer(GL_ARRAY_BUFFER, s_vbo);
346 glBufferData(GL_ARRAY_BUFFER, static_cast<GLsizeiptr>(solidVertCount) * 3 * sizeof(float), solidXYZ,
347 GL_DYNAMIC_DRAW);
348 }
349 if (haveAlpha)
350 {
351 GL33Bind::Vao(s_alphaVao);
352 glBindBuffer(GL_ARRAY_BUFFER, s_alphaVbo);
353 glBufferData(GL_ARRAY_BUFFER, static_cast<GLsizeiptr>(alphaVertCount) * 5 * sizeof(float), alphaXYZUV,
354 GL_DYNAMIC_DRAW);
355 }
356
357 glClearDepth(1.0);
358 for (int i = 0; i < numCascades; i++)
359 {
360 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, s_arrTex, 0, i);
361 Poseidon::render::clear::WithMask(GL_DEPTH_BUFFER_BIT);
362
363 if (haveSolid)
364 {
365 // Store the BACK faces (cull front): a lit front-facing surface is then
366 // strictly nearer the light than the stored depth, so it cannot
367 // self-shadow — kills the soldier's self-shadow acne/animation flicker
368 // and lets the bias stay tiny (no peter-panning / shadows vanishing up
369 // close). ApplyPipeline re-owns cull on the next draw.
370 Poseidon::render::cull::Front();
371 glUseProgram(s_prog);
372 glUniformMatrix4fv(s_locVP, 1, GL_FALSE, lightVPs + i * 16);

Callers 1

Calls 12

EnsureProgramFunction · 0.85
EnsureArrayTargetFunction · 0.85
EnsureMeshFunction · 0.85
EnsureAlphaProgramFunction · 0.85
EnsureAlphaMeshFunction · 0.85
NormalFunction · 0.85
NoneFunction · 0.85
VaoFunction · 0.85
WithMaskFunction · 0.85
FrontFunction · 0.85
ActiveUnitFunction · 0.85
Tex2DFunction · 0.85

Tested by

no test coverage detected