载入中...
搜索中...
未找到
Shadow.cpp
浏览该文件的文档.
1#include "graphics/Shadow.h"
2
4
5#include <algorithm>
6#include <cmath>
7#include <glm/gtc/matrix_transform.hpp>
8
9namespace eve::graphics {
10
11namespace {
12
13glm::mat4 cascadeVP(const glm::vec3 &lightDir, const glm::vec3 &eye, const glm::vec3 &target,
14 const glm::vec3 &up, float fovYRad, float aspect, float nearZ, float farZ,
15 float *texelWorldOut, float *zRangeOut) {
16 const glm::mat4 view = glm::lookAtRH(eye, target, up);
17 // Match the camera projection used by RenderSystem3D so frustum corners align.
18 const glm::mat4 proj = perspectiveVulkanRH_ZO(fovYRad, aspect, nearZ, farZ);
19 const glm::mat4 inv = glm::inverse(proj * view);
20
21 // NDC cube corners → world
22 glm::vec3 corners[8];
23 int idx = 0;
24 for (int z = 0; z < 2; ++z)
25 for (int y = 0; y < 2; ++y)
26 for (int x = 0; x < 2; ++x) {
27 const glm::vec4 ndc(x ? 1.f : -1.f, y ? 1.f : -1.f, z ? 1.f : 0.f, 1.f);
28 glm::vec4 w = inv * ndc;
29 w /= w.w;
30 corners[idx++] = glm::vec3(w);
31 }
32
33 glm::vec3 worldCenter(0.f);
34 for (int i = 0; i < 8; ++i) worldCenter += corners[i];
35 worldCenter *= 0.125f;
36 float radius = 0.5f;
37 for (int i = 0; i < 8; ++i)
38 radius = std::max(radius, glm::length(corners[i] - worldCenter));
39
40 glm::vec3 L = glm::normalize(lightDir);
41 if (glm::length(L) < 1e-6f) L = glm::vec3(0.f, 1.f, 0.f);
42 glm::vec3 lightUp(0.f, 1.f, 0.f);
43 if (std::abs(glm::dot(L, lightUp)) > 0.95f) lightUp = glm::vec3(0.f, 0.f, 1.f);
44 // Camera-independent view: rotation from L only. If lookAt follows the
45 // frustum center, static receivers crawl in shadow UV as the camera moves
46 // (Cornell floor: large jagged umbrae swimming/flickering).
47 const glm::mat4 lightView = glm::lookAtRH(L * 50.f, glm::vec3(0.f), lightUp);
48
49 glm::vec3 minB(1e9f), maxB(-1e9f);
50 for (int i = 0; i < 8; ++i) {
51 const glm::vec3 lp = glm::vec3(lightView * glm::vec4(corners[i], 1.f));
52 minB = glm::min(minB, lp);
53 maxB = glm::max(maxB, lp);
54 }
55 glm::vec3 centerLS = glm::vec3(lightView * glm::vec4(worldCenter, 1.f));
56
57 const float zPad = (maxB.z - minB.z) * 0.1f + 0.5f;
58 minB.z -= zPad;
59 // Pad toward the light so casters just outside the view frustum still
60 // write depth. Cornell: camera looks slightly down, the ceiling sits
61 // above the cascade near plane and never occludes the left/top creases.
62 maxB.z += zPad + 2.f;
63 if (zRangeOut) *zRangeOut = std::max(-minB.z - (-maxB.z), 1e-3f);
64
65 const float mapSize = float(ShadowConfig::kMapSize);
66 // World-space frustum sphere radius is pose-invariant for a given split, so
67 // the texel grid does not rescale as the camera rotates.
68 const float texelWorld = (2.f * radius) / mapSize;
69 if (texelWorldOut) *texelWorldOut = texelWorld;
70
71 auto snap = [&](float v) { return std::floor(v / texelWorld) * texelWorld; };
72 centerLS.x = snap(centerLS.x);
73 centerLS.y = snap(centerLS.y);
74
75 const glm::mat4 lightProj =
76 orthoVulkanRH_ZO(centerLS.x - radius, centerLS.x + radius, centerLS.y - radius,
77 centerLS.y + radius, -maxB.z, -minB.z);
78 return lightProj * lightView;
79}
80
81} // namespace
82
83ShadowUpload buildDirectionalCSM(const glm::vec3 &lightDirTowardSurface, const glm::vec3 &eye,
84 const glm::vec3 &target, const glm::vec3 &up, float fovYRad,
85 float aspect, float nearZ, float farZ, float bias, float strength) {
86 ShadowUpload out{};
87 out.active = true;
88 const float n = std::max(nearZ, 1e-3f);
89 const float fCam = std::max(farZ, n + 1e-2f);
90 const float f = std::min(fCam, std::max(n + 1e-2f, ShadowConfig::kMaxDistance));
91 const float ratio = f / n;
92 float splits[ShadowConfig::kCascades + 1];
93 splits[0] = n;
94 for (int i = 1; i <= ShadowConfig::kCascades; ++i) {
95 const float p = float(i) / float(ShadowConfig::kCascades);
96 const float logS = n * std::pow(ratio, p);
97 const float uniS = n + (f - n) * p;
98 splits[i] = ShadowConfig::kSplitLambda * logS + (1.f - ShadowConfig::kSplitLambda) * uniS;
99 }
100
101 float cascadeNdc[ShadowConfig::kCascades]{};
102 float cascadeTexel[ShadowConfig::kCascades]{};
103 for (int i = 0; i < ShadowConfig::kCascades; ++i) {
104 float texelWorld = 0.f;
105 float zRange = 1.f;
106 out.ubo.lightVP[i] =
107 cascadeVP(lightDirTowardSurface, eye, target, up, fovYRad, aspect, splits[i],
108 splits[i + 1], &texelWorld, &zRange);
109 // ~0.6 texels of world bias. More than that, projected onto a grazing
110 // Cornell wall, becomes a multi-pixel bright rim on the left/top of
111 // the umbra (peter-panning at the box/wall crease).
112 const float autoNdc = std::clamp((0.6f * texelWorld) / zRange, 1e-5f, 0.01f);
113 cascadeNdc[i] = std::max(std::max(0.f, bias), autoNdc);
114 cascadeTexel[i] = texelWorld;
115 }
116 out.ubo.splits = glm::vec4(splits[1], splits[2], splits[3], std::max(0.f, strength));
117 out.ubo.cascadeBias = glm::vec4(cascadeNdc[0], cascadeNdc[1], cascadeNdc[2], 0.f);
118 out.ubo.cascadeTexel = glm::vec4(cascadeTexel[0], cascadeTexel[1], cascadeTexel[2], 0.f);
119 out.ubo.bias = glm::vec4(cascadeNdc[0], 1.f, 1.f, 0.f);
120 return out;
121}
122
123} // namespace eve::graphics
int y
Definition Grass.cpp:135
int z
Definition Grass.cpp:135
int x
Definition Grass.cpp:135
glm::vec3 n
Definition Grass.cpp:64
int w
int idx
float f
glm::vec3 eye
glm::vec4 p[6]
glm::mat4 view
glm::mat4 proj
int v
卡牌游戏 UI 工具模块:工厂 + 脚本绑定入口。 功能参考 ycarowr/UiCard:扇形手牌布局、抽牌/洗牌、悬浮放大、拖拽到落牌区、 敌方手牌(背面/偷看)、费用不足置灰,以及可实时调节的布局...
Definition AnimTrail.h:6
glm::mat4 perspectiveVulkanRH_ZO(float fovyRad, float aspect, float zNear, float zFar)
Right-handed, zero-to-one depth perspective for Vulkan swapchains.
Definition ClipSpace.h:20
ShadowUpload buildDirectionalCSM(const glm::vec3 &lightDirTowardSurface, const glm::vec3 &eye, const glm::vec3 &target, const glm::vec3 &up, float fovYRad, float aspect, float nearZ, float farZ, float bias, float strength)
Build 3 cascade light view-proj matrices for a directional light.
Definition Shadow.cpp:83
glm::mat4 orthoVulkanRH_ZO(float left, float right, float bottom, float top, float zNear, float zFar)
Definition ClipSpace.h:28
static constexpr float kSplitLambda
Definition Shadow.h:10
static constexpr int kMapSize
Definition Shadow.h:9
static constexpr float kMaxDistance
Definition Shadow.h:13
static constexpr int kCascades
Definition Shadow.h:8