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

TypeNameDefault
HammeriteLightProbe[]probes[]
floatcell_size64.0
AABBbounds
boolnative_grid<unknown>

Methods

ReturnsMethod
voidrebuild()
Dictionaryquery(pos: Vector3, max_probes: int, max_radius: float = 512.0)
boolhas_nearby_probe(pos: Vector3, min_distance: float)
voidadd_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.

Hammerite 1.0 · built from a6dd634, 2026-10-10