VisuTwin Canvas
C++ 3D Engine — Metal Backend
Loading...
Searching...
No Matches
worldClusters.h
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2025-2026 Arnis Lektauers
3//
4// Metal-optimized: uses Metal buffers instead of upstream's texture-based approach.
5//
6#pragma once
7
8#include <cstdint>
9#include <vector>
10
11#include "core/math/color.h"
12#include "core/math/vector3.h"
14
15namespace visutwin::canvas
16{
21 {
22 int cellsX = 12;
23 int cellsY = 16;
24 int cellsZ = 12;
26
27 int totalCells() const { return cellsX * cellsY * cellsZ; }
28 };
29
34 struct alignas(16) GpuClusteredLight
35 {
36 float positionRange[4] = {}; // xyz=position, w=range
37 float directionSpot[4] = {}; // xyz=direction, w=outerConeCos
38 float colorIntensity[4] = {}; // xyz=color(linear), w=intensity
39 float params[4] = {}; // x=innerConeCos, y=isSpot(0/1), z=falloffLinear(0/1), w=reserved
40 };
41
47 {
49 Vector3 direction = Vector3(0.0f, -1.0f, 0.0f);
50 Color color = Color(1.0f, 1.0f, 1.0f, 1.0f);
51 float intensity = 0.0f;
52 float range = 10.0f;
53 float innerConeAngle = 0.0f;
54 float outerConeAngle = 45.0f;
55 bool isSpot = false;
56 bool falloffModeLinear = true;
57 };
58
70 {
71 public:
73
79 void update(const std::vector<ClusterLightData>& localLights,
80 const BoundingBox& cameraBounds);
81
82 // CPU data arrays for GPU upload by the renderer/device.
83 const GpuClusteredLight* lightData() const { return _gpuLights.data(); }
84 size_t lightDataSize() const { return _gpuLights.size() * sizeof(GpuClusteredLight); }
85 int lightCount() const { return static_cast<int>(_gpuLights.size()); }
86
87 const uint8_t* cellData() const { return _cellData.data(); }
88 size_t cellDataSize() const { return _cellData.size(); }
89
90 // Grid params for shader uniforms.
91 const Vector3& boundsMin() const { return _boundsMin; }
92 Vector3 boundsRange() const { return _boundsMax - _boundsMin; }
94
95 const ClusterConfig& config() const { return _config; }
96
97 private:
98 void collectLights(const std::vector<ClusterLightData>& localLights);
99 void computeGridBounds(const BoundingBox& cameraBounds);
100 void assignLightsToCells();
101 void packGpuLights();
102
103 ClusterConfig _config;
104
105 // CPU-side light entries with computed AABBs.
106 struct LightEntry
107 {
108 ClusterLightData data;
109 float outerConeCos = 1.0f;
110 float innerConeCos = 1.0f;
111 BoundingBox aabb;
112 };
113
114 std::vector<LightEntry> _lights;
115 std::vector<GpuClusteredLight> _gpuLights;
116
117 // Flat cell data: totalCells * maxLightsPerCell uint8 indices (1-based; 0=empty).
118 std::vector<uint8_t> _cellData;
119
120 Vector3 _boundsMin = Vector3(0.0f);
121 Vector3 _boundsMax = Vector3(0.0f);
122
123 bool _warnedOverflow = false;
124 };
125}
Axis-Aligned Bounding Box defined by center and half-extents.
Definition boundingBox.h:21
void update(const std::vector< ClusterLightData > &localLights, const BoundingBox &cameraBounds)
const uint8_t * cellData() const
const GpuClusteredLight * lightData() const
const Vector3 & boundsMin() const
const ClusterConfig & config() const
WorldClusters(const ClusterConfig &config=ClusterConfig{})
RGBA color with floating-point components in [0, 1].
Definition color.h:18
3D vector for positions, directions, and normals with multi-backend SIMD acceleration.
Definition vector3.h:29