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) {
17 out.clipInfo = glm::vec4(nearZ, farZ,
float(std::max(screenW, 1)),
float(std::max(screenH, 1)));
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;
28 out.primaryDir = glm::vec4(0.f, 1.f, 0.f, 0.f);
29 out.primaryColor = glm::vec4(0.f);
33 out.lights.assign(
points.begin(),
points.begin() + maxPts);
34 out.gridInfo.w = float(out.lights.size());
38 auto perCluster = std::vector<std::vector<uint32_t>>(size_t(C));
39 for (
auto &
v : perCluster)
v.reserve(4);
41 const float nx = nearZ;
42 const float fx = std::max(farZ, nearZ + 1e-3f);
43 const float tanHalfFov = std::tan(std::max(fovYRad, 1e-3f) * 0.5f);
44 const float aspect = out.clipInfo.z / std::max(out.clipInfo.w, 1.f);
46 for (uint32_t li = 0; li < uint32_t(out.lights.size()); ++li) {
47 const auto &L = out.lights[li];
48 const glm::vec3 worldPos(L.posRadius);
49 const float radius = std::max(L.posRadius.w, 0.01f);
50 const glm::vec4 vp =
view * glm::vec4(worldPos, 1.f);
51 const glm::vec3 viewPos(vp);
52 const float zCenter = -viewPos.z;
53 const float z0 = zCenter - radius;
54 const float z1 = zCenter + radius;
55 if (z1 < nx || z0 > fx)
continue;
57 const float zMin = std::max(z0, nx);
58 const float zMax = std::min(z1, fx);
59 const int slice0 = std::clamp(
62 const int slice1 = std::clamp(
66 const float depth = std::max(zCenter, nx);
67 const float halfH =
depth * tanHalfFov;
68 const float halfW = halfH * aspect;
70 auto toTileX = [&](
float x) {
71 float u = (
x + halfW) / std::max(2.f * halfW, 1e-3f);
75 auto toTileY = [&](
float y) {
76 float v = 1.f - (
y + halfH) / std::max(2.f * halfH, 1e-3f);
81 const int tx0 = toTileX(viewPos.x - radius);
82 const int tx1 = toTileX(viewPos.x + radius);
83 const int tyA = toTileY(viewPos.y - radius);
84 const int tyB = toTileY(viewPos.y + radius);
85 const int ty0 = std::min(tyA, tyB);
86 const int ty1 = std::max(tyA, tyB);
88 for (
int sz = slice0; sz <= slice1; ++sz) {
89 for (
int ty = ty0; ty <= ty1; ++ty) {
90 for (
int tx = tx0; tx <= tx1; ++tx) {
93 perCluster[size_t(cid)].push_back(li);
99 out.lightIndices.clear();
100 out.lightIndices.reserve(
size_t(C) * 4);
101 for (
int ci = 0; ci < C; ++ci) {
102 auto &list = perCluster[size_t(ci)];
104 std::stable_sort(list.begin(), list.end(), [&](uint32_t
a, uint32_t
b) {
105 const float ia = glm::length(glm::vec3(out.lights[a].color));
106 const float ib = glm::length(glm::vec3(out.lights[b].color));
111 out.clusterTable[size_t(ci)].offset = uint32_t(out.lightIndices.size());
112 out.clusterTable[size_t(ci)].count = uint32_t(list.size());
113 out.lightIndices.insert(out.lightIndices.end(), list.begin(), list.end());
115 if (out.lightIndices.empty()) out.lightIndices.push_back(0);
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.