Skip to content
← Lab

cl_godot: A Custom Godot Fork

A personal fork of Godot 4.8-dev. It adds hardware ray queries to the Metal backend and builds on them: MegaLights-style stochastic lighting, ray-traced GI with a surface cache, OpenColorIO colour management, and the editor tools to go with it. Apple silicon only, not upstream, and every feature below is in the public repo.

C++ GLSL Metal Godot OpenColorIO Python SCons Ray Tracing

What the fork adds

Ray tracing on Metal

Upstream Godot has the ray-tracing API stubbed out on Metal. The fork implements it.

  • Hardware ray queries in the Metal driver

    Acceleration structures, ray query bindings and SPIR-V Cross plumbing on Apple silicon. Inline queries only, as Metal offers them.

  • Whole-scene TLAS

    Built from every instance, not the frustum cull, so off-screen geometry casts shadows and bounce. Skinned, blend-shaped and multimesh instances included.

  • GPU timestamps on macOS

    --gpu-profile prints per-pass GPU time from MTLCounterSampleBuffer. Upstream reports nothing on Metal.

Direct lighting

Shadow maps replaced by rays, and a light count that no longer sets the frame cost.

  • Ray-traced sun shadows

    Replace the directional shadow map. Soft penumbras from the sun's angular size, temporal accumulation, alpha-tested casters.

  • Stochastic direct lighting

    MegaLights-style: every omni, spot and area light in one compute pass with reservoir sampling and one shadow ray per sample. Hundreds of shadowed lights at a flat cost.

  • Area lights, end to end

    Shadows, stochastic sampling, fog and GI all sample the rectangle. Sampling is uniform over the rect; the biased quadrant warp was measured and dropped.

  • SVGF-style denoiser

    Variance-driven a-trous spatial filter with temporal accumulation over demodulated diffuse and specular.

  • Ray-traced volumetric fog shadows

    Fog froxels trace their own shadow rays against the TLAS instead of reading shadow maps.

  • Screen-space contact traces

    Short screen traces close contact shadows the rays miss at the bias distance.

  • Light size everywhere

    A light's size drives the sun lobe, the stochastic pass and the fog, so soft shadows come from the light, not a blur radius.

Global illumination

Traced bounce with a surface cache behind it, in the spirit of Lumen.

  • Ray-traced GI final gather

    Replaces the SDFGI resolve and SSIL with a traced cosine gather, depth-validated history, VoxelGI as fallback.

  • SDFGI probes traced by hardware

    The probe rays go through the ray query path instead of the SDF march. Interior leak measurably lower.

  • Surface cache

    Six orthographic captures per instance into albedo, normal, emission and depth atlases, relit on the GPU. Cards read each other for multi-bounce.

  • Deferred hit shading

    Where a hit has no card, the material's own fragment code runs in compute at the hit, one indirect dispatch per material.

  • Traced reflections

    Mirror through rough, resolved over a neighbourhood before the temporal pass. Stock SSR is skipped where the traced result covers the roughness.

  • Directional irradiance and specular occlusion

    An irradiance moment adds surface detail; a traced occlusion term replaces the bent-normal approximation.

  • Reflection probe re-fit

    Captured probe radiance is re-fitted to the frame's irradiance so probes agree with the traced diffuse.

  • Translucency lighting volume

    A froxel volume of shadowed direct light and bounce for transparent surfaces, replacing per-fragment light loops.

  • Dynamic lights estimated apart

    A light that moves gets its own bounce history, so it neither smears the static cache nor counts twice at the hand-over.

Colour management

OpenColorIO in the renderer, the way a compositing pipeline expects it.

  • OpenColorIO module

    OCIO 2.4.2 vendored as modules/ocio with an OCIOServer singleton and a config chosen in project settings.

  • ACEScg working space

    Colour textures are converted into the working space at import; data textures are left alone. Authored colours are converted, not just linearised.

  • OCIO tonemapper

    TONE_MAPPER_OCIO renders through a real display, view and look set on the Environment, chosen separately, HDR output included.

  • Luminance in the working space

    The ray-traced passes measure and clamp luminance in the working colour space rather than assuming sRGB primaries.

Editor and workflow

Small things that make lights easier to place and the passes easier to see.

  • Visible area lights

    area_visible_to_camera shows an AreaLight3D's emitting rectangle to the camera and follows size changes. Clicking the rect selects the light.

  • Light range gizmos

    Omni, spot and area lights show a spherical range shape instead of the selection cube, with an eye toggle per light to hide it.

  • Gizmos out of the screen traces

    Editor gizmos no longer appear in SSR or screen-space shadow traces.

  • Ray Tracing settings category

    Every setting under Rendering > Ray Tracing is read each frame, so tuning updates the running viewport with no restart. Per-light shadow settings drive the traced passes.

  • Debug draws

    Viewport modes for the stochastic light, visibility and analytic terms, the cluster's area lights, and the area-light atlas. A GI tier counter reports where each ray's radiance came from.

  • Editor convergence

    The editor keeps repainting until the surface cache reports settled, instead of freezing a half-converged frame.

What is still open

  • Diffuse GI restarts about 8% too bright after a mouse flick; the structural fix is unbuilt.
  • Particles are not in the TLAS; multimesh sub-instances carry no cards.
  • 500-light target missed: 40.0 ms against 24 at 1080p.
  • The translucency volume serves one view, holds no area lights, and leaks a froxel of shadow.
  • Metal and Apple silicon only. No Vulkan path, nothing proposed upstream, runs not bit-deterministic.

Where the record lives

github.com/cpt-cabbage/godot, branch main. The commit log and MEGALIGHTS_PLAN.md are the full record; this page condenses them.

Written with Claude Code driving the code; I set the architecture, ran the measurements, and chose what to keep. Every commit carries the co-author trailer.

← LabPortfolio →About →

Open to EU and UK supervision roles from October 2026.

Contact Me →