22 : _renderer(renderer), _shadowRenderer(shadowRenderer), _device(device)
34 for (
int i = 0; i < 4; ++i) {
35 distances[i] = farDist;
38 for (
int i = 1; i < numCascades; ++i) {
39 const float fraction =
static_cast<float>(i) /
static_cast<float>(numCascades);
40 const float linearDist = nearDist + (farDist - nearDist) * fraction;
41 const float logDist = nearDist * std::pow(farDist / std::max(nearDist, 0.001f), fraction);
42 distances[i - 1] = linearDist + (logDist - linearDist) * distribution;
44 distances[numCascades - 1] = farDist;
55 const float nearDist = camera->
nearClip();
61 Vector3 lightDir(0.0f, -1.0f, 0.0f);
65 lightDir =
Vector3(lightWorld.getColumn(1)) * -1.0f;
67 lightDir =
Vector3(0.0f, -1.0f, 0.0f);
71 lightRotation = lightNode->
rotation();
77 const Quaternion shadowRotation = lightRotation * pitchDown;
90 for (
int cascade = 0; cascade < numCascades; ++cascade) {
91 LightRenderData* lightRenderData = _shadowRenderer->getLightRenderData(light, camera, cascade);
92 if (!lightRenderData || !lightRenderData->
shadowCamera) {
97 auto& shadowCamNode = shadowCam->
node();
107 const float frustumNear = (cascade == 0) ? nearDist : distances[cascade - 1];
108 const float frustumFar = distances[cascade];
113 for (
int i = 0; i < 8; ++i) {
114 frustumPoints[i] = cameraWorldMat.
transformPoint(frustumPoints[i]);
115 center = center + frustumPoints[i];
117 center = center * (1.0f / 8.0f);
121 for (
int i = 0; i < 8; ++i) {
122 const float dist = (frustumPoints[i] - center).length();
130 if (resolution > 0 && radius > 0.0f) {
136 const float cascadeRes =
static_cast<float>(resolution) * vpSize;
137 const float sizeRatio = 0.25f * cascadeRes / radius;
145 const float x = std::ceil(center.
dot(up) * sizeRatio) / sizeRatio;
146 const float y = std::ceil(center.
dot(right) * sizeRatio) / sizeRatio;
147 const float z = center.
dot(forward);
149 center = up * x + right * y + forward * z;
155 shadowCamNode->setRotation(shadowRotation);
156 shadowCamNode->setPosition(center);
157 shadowCamNode->translateLocal(0.0f, 0.0f, 1000000.0f);
173 const Matrix4 shadowCamView = shadowCamNode->worldTransform().
inverse();
174 float depthMin = 1e30f;
175 float depthMax = -1e30f;
176 for (
int i = 0; i < 8; ++i) {
178 if (z < depthMin) depthMin = z;
179 if (z > depthMax) depthMax = z;
184 shadowCamNode->translateLocal(0.0f, 0.0f, depthMax + 0.1f);
188 shadowCam->
setFarClip(depthMax - depthMin + 0.2f);
194 const Matrix4 shadowView = shadowCamNode->worldTransform().
inverse();
219 const Matrix4 shadowMatrix = viewportMatrix * shadowVP;
226 std::memcpy(&palette[cascade * 16], &shadowMatrix, 64);
231 const int face,
const bool clearRenderTarget,
const bool allCascadesRendering)
239 Camera* shadowCamera =
nullptr;
240 for (
int f = 0; f < faceCount; ++f) {
241 shadowCamera = _shadowRenderer->prepareFace(light, camera, f);
247 auto renderPass = std::make_shared<RenderPassShadowDirectional>(_device, _shadowRenderer, light, camera, shadowCamera, face,
248 allCascadesRendering);
249 _shadowRenderer->setupRenderPass(renderPass.get(), shadowCamera, clearRenderTarget);
254 const std::unordered_map<
Camera*, std::vector<Light*>>& cameraDirShadowLights)
256 if (!frameGraph || !_shadowRenderer || !_device) {
260 for (
const auto& [camera, lights] : cameraDirShadowLights) {
264 for (
auto* light : lights) {
268 if (!_shadowRenderer->needsShadowRendering(light)) {
Perspective or orthographic camera with projection matrix, jitter (TAA), and render target binding.
void setProjection(ProjectionType value)
std::array< Vector3, 8 > getFrustumCorners(const float nearDist, const float farDist) const
void setOrthoHeight(const float value)
void setAspectRatio(float value)
const Matrix4 & projectionMatrix()
const std::unique_ptr< GraphNode > & node() const
void setFarClip(const float value)
void setNearClip(const float value)
void addRenderPass(const std::shared_ptr< RenderPass > &renderPass)
Hierarchical scene graph node with local/world transforms and parent-child relationships.
const Matrix4 & worldTransform()
Directional, point, spot, or area light with shadow mapping and cookie projection.
int shadowResolution() const
float * shadowCascadeDistancesData()
float shadowDistance() const
float * shadowMatrixPaletteData()
const std::array< float, 4 > & shadowCascadeDistances() const
float cascadeDistribution() const
int numShadowFaces() const
const std::array< Vector4, 4 > & cascadeViewports() const
Per-face shadow rendering data: shadow camera, viewport, and scissor.
void cull(Light *light, Camera *camera)
void buildNonClusteredRenderPasses(FrameGraph *frameGraph, const std::unordered_map< Camera *, std::vector< Light * > > &cameraDirShadowLights)
ShadowRendererDirectional(const std::shared_ptr< GraphicsDevice > &device, Renderer *renderer, ShadowRenderer *shadowRenderer)
static void generateSplitDistances(Light *light, float nearDist, float farDist)
std::shared_ptr< RenderPass > getLightRenderPass(Light *light, Camera *camera, int face, bool clearRenderTarget, bool allCascadesRendering)
4x4 column-major transformation matrix with SIMD acceleration.
void setElement(const int col, int row, const float value)
static Matrix4 identity()
Vector3 transformPoint(const Vector3 &v) const
Vector4 getColumn(int col) const
static Matrix4 trs(const Vector3 &t, const Quaternion &r, const Vector3 &s)
Unit quaternion for rotation representation with SIMD-accelerated slerp and multiply.
static Quaternion fromEulerAngles(float ax, float ay, float az)
3D vector for positions, directions, and normals with multi-backend SIMD acceleration.
Vector3 normalized() const
float dot(const Vector3 &other) const
float lengthSquared() const
4D vector for homogeneous coordinates, color values, and SIMD operations.