HammeriteLightProbeSet
Core: lighting. Inherits Resource
A map's baked light probes, with a uniform spatial grid for finding the nearest ones.
HammeriteMap.generate_light_probes() fills it and a bake lights it; most code reads it only through HammeriteMap.light_level_at(). Positions are in map space, the coordinates brushes are authored in.
Properties
| Type | Name | Default |
|---|---|---|
HammeriteLightProbe[] | probes | [] |
float | cell_size | 64.0 |
AABB | bounds | |
bool | native_grid | <unknown> |
Methods
| Returns | Method |
|---|---|
void | rebuild() |
Dictionary | query(pos: Vector3, max_probes: int, max_radius: float = 512.0) |
bool | has_nearby_probe(pos: Vector3, min_distance: float) |
void | add_probe(probe: HammeriteLightProbe) |
Constants
NATIVE_PROBE_GRID
const NATIVE_PROBE_GRID = &"HammeriteNativeProbeGrid"
The class name the native probe grid kernel registers in ClassDB when it is installed.
Property descriptions
probes
var probes: HammeriteLightProbe[] = []
The probes the bake lights. add_probe() adds one; assigning the array, or growing it in place, has the grid built again before it is next asked.
cell_size
var cell_size: float = 64.0
Edge of one grid cell, in map units. Changing it has the grid built again before it is next asked.
bounds
var bounds: AABB
The smallest box holding every probe position, or an empty box at the origin when there are none. Kept by rebuild() and add_probe().
native_grid
var native_grid: bool = <unknown>
Whether query() is answered by the native kernel (#116), which walks the grid as it does. Settable, so a suite can ask both ways.
Method descriptions
rebuild()
func rebuild() -> void
Builds the grid and bounds again from probes and cell_size. The map calls it on load, and a query calls it after the probes change; a probe edited in place - moved - is the one change it cannot see, and wants this called.
query()
func query(pos: Vector3, max_probes: int, max_radius: float = 512.0) -> Dictionary
The max_probes probes nearest pos, and how far off each one is. Returns { "indices": PackedInt32Array, "distances": PackedFloat32Array }, nearest first, and they really are the nearest: the fade that weights them - here, and in probe_sampling.gdshaderinc - leans on it. It silences whichever probe is farthest on the grounds that it is the one leaving the set, so a set that is only approximately the nearest drops probes while they still carry weight, which is the light popping that the fade exists to prevent. Probes sit half a cell apart, so the cells around pos hold far more than any caller asks for and the walk stops within a ring or two of it. max_radius only binds where the bake is sparse - the edge of a map, a room the generator could not reach into. Written as one function on purpose: the ring walk, the cull and the insert were three, and a call per cell of every ring cost more than any of the work inside them.
has_nearby_probe()
func has_nearby_probe(pos: Vector3, min_distance: float) -> bool
Whether any probe stands within min_distance of pos. What probe generation asks to keep probes from clustering; as many rings of cells are searched as min_distance reaches.
add_probe()
func add_probe(probe: HammeriteLightProbe) -> void
Add probe to the set, and to the grid as it stands rather than building it again.