VisuTwin Canvas
C++ 3D Engine — Metal Backend
Loading...
Searching...
No Matches
renderPassShadowLocalNonClustered.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2025-2026 Arnis Lektauers
3//
4// Created by Arnis Lektauers on 06.12.2025.
5//
7
13#include <scene/graphNode.h>
16
17namespace visutwin::canvas
18{
20 ShadowRenderer* shadowRenderer, Light* light, int face, bool applyVsm): RenderPass(device),
21 _shadowRenderer(shadowRenderer),
22 _light(light),
23 _graphicsDevice(device),
24 _face(face),
25 _applyVsm(applyVsm) {
26
27 _requiresCubemaps = false;
28
29 // Prepare the shadow camera for this face
30 _shadowCamera = shadowRenderer->prepareFace(light, nullptr, face);
31
32 // Set up the render pass
33 // Clear the render target as well, as it contains a single shadow map
34 shadowRenderer->setupRenderPass(this, _shadowCamera, true);
35
36 // Set debug name
37 if (light->node()) {
38 _name = _name + "-" + light->node()->name();
39 }
40 }
41
43 {
44 if (!_graphicsDevice || !_shadowCamera || !_shadowCamera->node()) {
45 return;
46 }
47
48 auto programLibrary = getProgramLibrary(_graphicsDevice);
49 if (!programLibrary) {
50 return;
51 }
52
53 auto shadowShader = programLibrary->getShadowShader(false);
54 auto shadowShaderDynBatch = programLibrary->getShadowShader(true);
55 if (!shadowShader) {
56 return;
57 }
58
59 _graphicsDevice->setShader(shadowShader);
60
61 // Shadow pass needs blend/depth state set on the device — the forward pass
62 // sets these per-material, but the shadow pass bypasses materials entirely.
63 // Matches renderPassShadowDirectional.cpp execute().
64 static auto shadowBlendState = std::make_shared<BlendState>(); // default: no blend, color writes on
65 static auto shadowDepthState = std::make_shared<DepthState>(); // default: depth test+write enabled
66 _graphicsDevice->setBlendState(shadowBlendState);
67 _graphicsDevice->setDepthState(shadowDepthState);
68
69 // hardware polygon-offset depth bias during shadow rendering.
70 // Applied via setDepthState().
71 {
72 const float bias = _light->shadowBias() * -1000.0f;
73 _graphicsDevice->setDepthBias(bias, bias, 0.0f);
74 }
75
76 const Matrix4 viewProjection = _shadowCamera->projectionMatrix() * _shadowCamera->node()->worldTransform().inverse();
77 for (auto* renderComponent : RenderComponent::instances()) {
78 if (!shouldRenderShadowRenderComponent(renderComponent, nullptr)) {
79 continue;
80 }
81
82 for (auto* meshInstance : renderComponent->meshInstances()) {
83 if (!meshInstance->visible()) {
84 continue;
85 }
86 if (!shouldRenderShadowMeshInstance(meshInstance, _shadowCamera)) {
87 continue;
88 }
89
90 auto vertexBuffer = meshInstance->mesh()->getVertexBuffer();
91 meshInstance->setVisibleThisFrame(true);
92 _graphicsDevice->setVertexBuffer(vertexBuffer, 0);
93
94 if (meshInstance->isDynamicBatch()) {
95 if (shadowShaderDynBatch) {
96 _graphicsDevice->setShader(shadowShaderDynBatch);
97 }
98 auto* sbi = meshInstance->skinBatchInstance();
99 if (sbi) {
100 _graphicsDevice->setDynamicBatchPalette(sbi->paletteData(), sbi->paletteSizeBytes());
101 }
102 _graphicsDevice->setTransformUniforms(viewProjection, Matrix4::identity());
103 _graphicsDevice->draw(meshInstance->mesh()->getPrimitive(), meshInstance->mesh()->getIndexBuffer(), 1, -1, true, true);
104 _graphicsDevice->setShader(shadowShader);
105 } else {
106 const auto modelMatrix = (meshInstance->node() ? meshInstance->node()->worldTransform() : Matrix4::identity());
107 _graphicsDevice->setTransformUniforms(viewProjection, modelMatrix);
108 _graphicsDevice->draw(meshInstance->mesh()->getPrimitive(), meshInstance->mesh()->getIndexBuffer(), 1, -1, true, true);
109 }
110 }
111 }
112
113 (void)_shadowRenderer;
114 (void)_light;
115 (void)_face;
116 (void)_applyVsm;
117 }
118}
Directional, point, spot, or area light with shadow mapping and cookie projection.
Definition light.h:54
GraphNode * node() const
Definition light.h:107
static const std::vector< RenderComponent * > & instances()
std::shared_ptr< GraphicsDevice > device() const
Definition renderPass.h:124
RenderPass(const std::shared_ptr< GraphicsDevice > &device)
Definition renderPass.h:66
RenderPassShadowLocalNonClustered(const std::shared_ptr< GraphicsDevice > &device, ShadowRenderer *shadowRenderer, Light *light, int face, bool applyVsm)
void setupRenderPass(RenderPass *renderPass, Camera *shadowCamera, bool clearRenderTarget)
Camera * prepareFace(Light *light, Camera *camera, int face)
bool shouldRenderShadowMeshInstance(MeshInstance *meshInstance, Camera *shadowCamera)
std::shared_ptr< ProgramLibrary > getProgramLibrary(const std::shared_ptr< GraphicsDevice > &device)
bool shouldRenderShadowRenderComponent(const RenderComponent *renderComponent, const Camera *camera)
4x4 column-major transformation matrix with SIMD acceleration.
Definition matrix4.h:31
static Matrix4 identity()
Definition matrix4.h:108
Matrix4 inverse() const