10 const std::vector<ClusteredLightGpu> &dirs,
11 const glm::mat4 &
view,
float nearZ,
float farZ,
12 int screenW,
int screenH,
float fovYRad,
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.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());
39 auto perCluster = std::vector<std::vector<uint32_t>>(size_t(C));
40 for (
auto &
v : perCluster)
v.reserve(4);
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);
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;
54 const float z0 = zCenter -
radius;
55 const float z1 = zCenter +
radius;
56 if (z1 < nx || z0 > fx)
continue;
58 const float zMin = std::max(z0,
nx);
59 const float zMax = std::min(z1, fx);
60 const int slice0 = std::clamp(
63 const int slice1 = std::clamp(
67 const float depth = std::max(zCenter,
nx);
71 auto toTileX = [&](
float x) {
76 auto toTileY = [&](
float y) {
77 float v = 1.f - (
y +
halfH) / std::max(2.f *
halfH, 1e-3f);
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);
89 for (
int sz = slice0;
sz <= slice1; ++
sz) {
90 for (
int ty = ty0; ty <= ty1; ++ty) {
91 for (
int tx = tx0; tx <= tx1; ++tx) {
94 perCluster[size_t(cid)].push_back(li);
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)];
105 ++out.overflowClusterCount;
106 out.droppedLightReferenceCount +=
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));
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());
119 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.
ClusterTableEntry public API.