Skip to content

gdgs 3.3.0

Latest

Choose a tag to compare

@github-actions github-actions released this 30 Jul 03:56
  • Added relighting: Gaussian splats can now be lit by the scene's Light3D nodes. A splat stores radiance, not material — no normal, no albedo, no occlusion — so an editor bake derives the missing geometry from a lighting proxy (the same voxel field the collision module contours into a smooth mesh) and gives every splat an outward surface normal, an ambient-occlusion term and a confidence value. At runtime the colour is scaled by unlit_level + gain × irradiance, so enabling relighting darkens everything to a floor and lets only lit regions climb back up. Directional, omni and spot lights are supported with Godot's own range and cone falloff, up to eight at a time, and they may move freely. See docs/relighting.md.
  • Added the GaussianLightingResource bake artifact: 4 bytes per splat plus the proxy mesh, saved as a .res and assigned to the node's new lighting property. The imported GaussianResource is untouched, so relighting is entirely additive and costs nothing when unused.
  • Added a GDGS Lighting inspector panel that bakes on a background thread behind a cancellable progress dialog, saves the result and assigns it in one undo/redo action. Like collision, the module is optional and fault-isolated; unlike collision it is bake-time only, so a shipped game can relight from a baked resource with addons/gdgs/collision deleted.
  • Added relight_cast_shadows: the baked proxy mounts as a SHADOWS_ONLY MeshInstance3D, so a Gaussian scene casts real shadows onto ordinary Godot geometry under both rendering backends. This is independent of whether the splats themselves are relit.
  • Relighting is evaluated once per splat in the vertex/projection stage rather than per fragment, because splat clouds have 10–50× overdraw. At 271123 splats and 1280×720 with a close-in camera it costs +4.7% of frame time with one light and +16.0% with eight.
  • Both rendering backends implement relighting with identical maths, verified: with the multiplier pinned to 1.0 the two agree to 1.4786/255, against a 1.4781/255 unlit baseline, and the Raster backend is bit-identical to relighting-off.
  • Letting Godot light the Raster splats natively — which would give splats cast shadows for free — was implemented and measured rather than assumed. It works, but costs 2.5–3.9× the frame time (rising with overdraw, since light() is fragment-stage) and could never apply to the Compute backend, so it is not shipped. Splats therefore cast shadows but do not receive them.
  • Fixed the node never telling the rendering backend that its lighting resource changed. The Raster backend polls its nodes and did not notice, but the Compute backend caches the bake at registration time and kept rendering the state the node had when it entered the tree — null for the usual order of adding a node and assigning the resource afterwards, including from the inspector.
  • Added a keep_grid option to the collision pipeline so a caller can ask for the occupancy field the mesh was contoured from, not just the contour. Existing behaviour is unchanged.
  • Replaced the bundled demo scene with an interactive relighting sandbox: an orbiting light over the sample asset with live toggles for relighting, proxy shadow casting, DC-only, light type, unlit level and gain, plus a ground plane and an ordinary Godot box so the same light can be compared on both. It bakes its own proxy on first run and caches it under user://, so no multi-megabyte artifact enters the repository, and it is built in code so the scene file cannot be churned by an editor version. The previous minimal demo scene lives on as tests/ab_reference.tscn, the fixture the visual A/B harness renders.
  • Added headless tests for the lighting bake (octahedral round-trip, surface field, per-splat transfer, concave-corner ambient occlusion, proxy vertex normals), the light rig (per-type packing, change detection, hidden/dark light rejection) and the Raster lighting texture packing.