载入中...
搜索中...
未找到
ClusteredLight.cpp
浏览该文件的文档.
2
3#include <algorithm>
4#include <cmath>
5#include <vector>
6
7namespace eve::graphics {
8
9ClusteredLightingUpload buildClusteredLighting(const std::vector<ClusteredLightGpu> &points,
10 const std::vector<ClusteredLightGpu> &dirs,
11 const glm::mat4 &view, float nearZ, float farZ,
12 int screenW, int screenH, float fovYRad,
13 const glm::vec4 &ambient) {
15 out.ambient = ambient;
16 out.view = view;
17 out.clipInfo = glm::vec4(nearZ, farZ, float(std::max(screenW, 1)), float(std::max(screenH, 1)));
18 out.gridInfo = glm::vec4(float(ClusteredLightConfig::kTilesX), float(ClusteredLightConfig::kTilesY),
20
21 if (!dirs.empty()) {
22 glm::vec3 d(dirs[0].posRadius);
23 if (glm::length(d) < 1e-6f) d = glm::vec3(0.f, 1.f, 0.f);
24 else d = glm::normalize(d);
25 out.primaryDir = glm::vec4(d, 1.f);
26 out.primaryColor = dirs[0].color;
27 } else {
28 out.primaryDir = glm::vec4(0.f, 1.f, 0.f, 0.f);
29 out.primaryColor = glm::vec4(0.f);
30 }
31
32 const int maxPts = std::min(int(points.size()), ClusteredLightConfig::kMaxLights);
33 out.truncatedLightCount = uint32_t(points.size() - size_t(maxPts));
34 out.lights.assign(points.begin(), points.begin() + maxPts);
35 out.gridInfo.w = float(out.lights.size());
36
38 out.clusterTable.assign(size_t(C), ClusterTableEntry{});
39 auto perCluster = std::vector<std::vector<uint32_t>>(size_t(C));
40 for (auto &v : perCluster) v.reserve(4);
41
42 const float nx = nearZ;
43 const float fx = std::max(farZ, nearZ + 1e-3f);
44 const float tanHalfFov = std::tan(std::max(fovYRad, 1e-3f) * 0.5f);
45 const float aspect = out.clipInfo.z / std::max(out.clipInfo.w, 1.f);
46
47 for (uint32_t li = 0; li < uint32_t(out.lights.size()); ++li) {
48 const auto &L = out.lights[li];
49 const glm::vec3 worldPos(L.posRadius);
50 const float radius = std::max(L.posRadius.w, 0.01f);
51 const glm::vec4 vp = view * glm::vec4(worldPos, 1.f);
52 const glm::vec3 viewPos(vp);
53 const float zCenter = -viewPos.z; // positive depth in front of camera (RH)
54 const float z0 = zCenter - radius;
55 const float z1 = zCenter + radius;
56 if (z1 < nx || z0 > fx) continue;
57
58 const float zMin = std::max(z0, nx);
59 const float zMax = std::min(z1, fx);
60 const int slice0 = std::clamp(
61 int(std::floor((zMin - nx) / (fx - nx) * float(ClusteredLightConfig::kSlices))), 0,
63 const int slice1 = std::clamp(
64 int(std::floor((zMax - nx) / (fx - nx) * float(ClusteredLightConfig::kSlices))), 0,
66
67 const float depth = std::max(zCenter, nx);
68 const float halfH = depth * tanHalfFov;
69 const float halfW = halfH * aspect;
70
71 auto toTileX = [&](float x) {
72 float u = (x + halfW) / std::max(2.f * halfW, 1e-3f);
73 return std::clamp(int(std::floor(u * float(ClusteredLightConfig::kTilesX))), 0,
75 };
76 auto toTileY = [&](float y) {
77 float v = 1.f - (y + halfH) / std::max(2.f * halfH, 1e-3f);
78 return std::clamp(int(std::floor(v * float(ClusteredLightConfig::kTilesY))), 0,
80 };
81
82 const int tx0 = toTileX(viewPos.x - radius);
83 const int tx1 = toTileX(viewPos.x + radius);
84 const int tyA = toTileY(viewPos.y - radius);
85 const int tyB = toTileY(viewPos.y + radius);
86 const int ty0 = std::min(tyA, tyB);
87 const int ty1 = std::max(tyA, tyB);
88
89 for (int sz = slice0; sz <= slice1; ++sz) {
90 for (int ty = ty0; ty <= ty1; ++ty) {
91 for (int tx = tx0; tx <= tx1; ++tx) {
92 const int cid =
94 perCluster[size_t(cid)].push_back(li);
95 }
96 }
97 }
98 }
99
100 out.lightIndices.clear();
101 out.lightIndices.reserve(size_t(C) * 4);
102 for (int ci = 0; ci < C; ++ci) {
103 auto &list = perCluster[size_t(ci)];
104 if (list.size() > size_t(ClusteredLightConfig::kMaxLightsPerCluster)) {
105 ++out.overflowClusterCount;
106 out.droppedLightReferenceCount +=
107 uint32_t(list.size() - size_t(ClusteredLightConfig::kMaxLightsPerCluster));
108 std::stable_sort(list.begin(), list.end(), [&](uint32_t a, uint32_t b) {
109 const float ia = glm::length(glm::vec3(out.lights[a].color));
110 const float ib = glm::length(glm::vec3(out.lights[b].color));
111 return ia > ib;
112 });
114 }
115 out.clusterTable[size_t(ci)].offset = uint32_t(out.lightIndices.size());
116 out.clusterTable[size_t(ci)].count = uint32_t(list.size());
117 out.lightIndices.insert(out.lightIndices.end(), list.begin(), list.end());
118 }
119 if (out.lightIndices.empty()) out.lightIndices.push_back(0);
120 out.active = true;
121 return out;
122}
123
124} // namespace eve::graphics
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float halfW
float halfH
float nx
float u
Definition Grass.cpp:233
std::int32_t zMax
std::int32_t zMin
float v
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
float radius
std::shared_ptr< const std::vector< glm::vec2 > > points
float d
glm::mat4 view
std::uint32_t depth
卡牌游戏 UI 工具模块:工厂 + 脚本绑定入口。 功能参考 ycarowr/UiCard:扇形手牌布局、抽牌/洗牌、悬浮放大、拖拽到落牌区、 敌方手牌(背面/偷看)、费用不足置灰,以及可实时调节的布局...
Definition Animation.h:25
ClusteredLightingUpload buildClusteredLighting(const std::vector< ClusteredLightGpu > &points, const std::vector< ClusteredLightGpu > &dirs, const glm::mat4 &view, float nearZ, float farZ, int screenW, int screenH, float fovYRad, const glm::vec4 &ambient)
Build clustered tables for point lights in view space.
ClusterTableEntry public API.
static constexpr int kMaxLightsPerCluster
CPU-built clustered lighting upload for one frame/camera. Point lights are clustered; directional lig...
glm::vec4 ambient