ludic/packages/ludic.render3d/FEATURES.md
Orkuncakilkaya f993c4a36a r3d/runtime: allocs, keeps and births at 0 on this side
render3d: shadow_fit, water_reflection_pass, layer_partition_lods and the
GPU cull's scratch are made with the state; v3_dist is scalar; the pushes
into lists sized at start-up, the caps probe, the table growth, the loads
and the constructors declared with their bounds (one statement a line);
the renderer's name made once with the device; the two error messages
given back; the dead lupine models removed.

runtime: a component's text is held interned in its value cell (one copy
per distinct text), so the getter's own text goes with its frame instead
of being kept by ludic.ui's model - 80 of the 83 keeps.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 20:10:59 +03:00

14 KiB
Raw Permalink Blame History

ludic.render3d — what is implemented, where, and how it compares

Every item below names the file (and function or shader) that implements it, so the claim can be checked in the tree. Paths are relative to packages/ludic.render3d unless stated; Gl.* lives in runtime/native/.

The OpenGL surface (Gl.*)

  • Every OpenGL 4.1 core entry point — 478 of 478 GLAPI declarations in the platform gl3.h, generated by ludic-dev glgen (tools/ludic-cli/glgen.ludic) into runtime/native/gl_api.ludic (grep -c '^extern function gl_' = 478) with one ABI thunk each in runtime/native/gl_thunks.ll; 901 GL_* constants. Float and double parameters take fixed; 64-bit sizes take long; GLboolean returns are widened. macOS exposes 4.1 core as its ceiling, so this is the whole API the platform has.
  • Context on the window at Retina resolution (runtime/native/cocoa.ll, win_gl_attach), offscreen CGL context for headless runs (runtime/native/gl.ll), screenshots, shader/program helpers, IEEE-float helpers over Q16.16 (runtime/native/gl.ludic).

Rendering features (numbered so they can be counted)

Lighting and materials

  1. Cook-Torrance GGX specular, Smith height-correlated visibility, Schlick Fresnel — shaders/lighting.glsl shade()
  2. Diffuse image-based lighting from a convolved irradiance map — sky.ludic sky_precompute, shaders/ibl_irradiance.frag
  3. GGX-prefiltered specular environment, 6 roughness levels (importance sampled, mip-filtered) — shaders/ibl_prefilter.frag
  4. Split-sum BRDF lookup table — shaders/ibl_brdf.frag
  5. HDRI sky with the sun extracted from the map and its irradiance integrated from the clipped texels — texture.ludic hdr_decode, sky.ludic
  6. Sky rotation with all convolutions rebuilt (time-of-azimuth control) — sky.ludic sky_set_yaw
  7. Normal mapping with derivative-reconstructed tangent frames (models) and a heightfield tangent basis (terrain) — shaders/model.frag cotangentFrame, shaders/terrain.frag
  8. Distant-grass carpet: the clump cards baked straight down into a tiling tile (alpha = coverage) and draped on the ground beyond the blade rings with stochastic anti-tiling, so the far meadow carries the near cover's clumps and gaps — scatter.ludic carpet_bake, shaders/terrain.frag sampleCarpet (replaced the parallax pass, whose sampler slot it took)
  9. Stochastic (triangle-grid) anti-tiling texture sampling with rotated taps and textureGrad — shaders/terrain.frag sampleMat
  10. Triplanar mapping for steep rock — shaders/terrain.frag sampleTri
  11. Foliage translucency and wrapped diffuse (thin-leaf subsurface approximation) — shaders/model.frag FOLIAGE
  12. Two-sided lighting for thin cards — shaders/model.frag CARD
  13. Ground-bounce fill light (one bounce from the sunlit meadow onto undersides) — shaders/lighting.glsl bounce
  14. Screen-space global illumination: one indirect diffuse bounce gathered from the previous anti-aliased frame, plus ambient occlusion, half resolution, depth-aware blur — shaders/ssgi.frag, shaders/ssao_blur.frag, post.ludic post_ssao_pass
  15. Specular occlusion from ambient occlusion — shaders/lighting.glsl
  16. Cloud shadows projected along the sun from an animated cloud layer — shaders/lighting.glsl cloudShadow
  17. Regional vegetation colouring (aspen groves, dry ridges) and slope-aspect colouring — shaders/lighting.glsl regionTint, shaders/terrain.frag

Shadows 18. Cascaded shadow maps, 5 cascades (16 / 60 / 250 / 1100 / 6000 m) fitted to frustum-slice bounding spheres, texel-snapped, PCF radius widened on the far cascades — shadow.ludic shadow_fit 19. PCF with rotated Poisson taps and interleaved-gradient noise, normal-offset and world-unit slope bias, cascade edge blending — shaders/lighting.glsl sunShadow 20. Per-layer caster culling (grass in near cascades, coarse terrain meshes for far cascades) — scatter.ludic scatter_draw_casters, terrain.ludic 21. Sun-facing impostor cards in the shadow pass with mip-biased coverage — shaders/impostor.vert, shaders/impostor.frag

Geometry, terrain and world 22. GPU-generated terrain height field (ridged multifractal, fbm) — shaders/heightgen.frag 23. Real-world terrain from the Copernicus GLO-30 elevation model with slope-scaled fractal detail; a lake bed carved under the surface the model records — the survey window in the Maroon Lake game (git.workshopsoft.io/workshopsoft/maroon-lake), shaders/heightgen.frag DEM, terrain.ludic terrain_use_dem, terrain_lake 24. Satellite orthophoto drape (Sentinel-2 true colour) sampled bicubically, blended in past the middle ground, keeping the scanned materials' luminance grain plus three-scale procedural grain — the survey window in the Maroon Lake game (git.workshopsoft.io/workshopsoft/maroon-lake), shaders/terrain.frag u_ortho 25. Satellite-classified materials and placement: bare ground (cobble shore near, talus far), snow, meadow, dense conifer stands (tree density and forest-floor duff follow the photograph) — shaders/terrain.frag, terrain.ludic terrain_ortho_green/scree/forest 26. Terrain material splatting by slope, altitude and a track mask; height-map CPU read-back for placement queries — shaders/terrain.frag, terrain.ludic terrain_height 27. Snow by altitude and slope, gully snow, forest-floor material under stands — shaders/terrain.frag 28. glTF 2.0 loading of photogrammetry models by byte-range reads from the .bin — gltf.ludic 29. GPU instancing with divisor attributes and per-instance transforms — scatter.ludic, shaders/model.vert 30. Baked impostors (16-view atlas with coverage and normals, hull-normal blending, LOD switch) — scatter.ludic impostor_bake, shaders/impostor.* 31. Baked branch-card trees: wedge slices of a scanned crown (sectors × height bands) on radial cards over the real trunk mesh — scatter.ludic impostor_bake_wedges, model_branch_cards 32. Card atlases baked from scanned grass clumps and a dense procedural lupine, instanced as crossed cards — scatter.ludic layer_cards 33. Procedural grass blades with wind, dryness and base occlusion; distant blades widen, lie flat to the ground normal and sink into the carpet at the ring's edge — scatter.ludic model_blade, shaders/model.vert, shaders/model.frag BLADE 34. Wind animation (height-weighted sway, per-instance phase) — shaders/model.vert WIND 35. Chunk-streamed ground cover with distance bands (blades in four rings, densest underfoot), deterministic per-chunk generation, nearest-first amortised over frames with an instance budget — stream.ludic 36. Multi-scale noise clustering for natural placement, forest density by elevation/slope/aspect, avalanche chutes, shoreline scrub — the Maroon Lake game (git.workshopsoft.io/workshopsoft/maroon-lake) 37. Level-of-detail by distance: full scan mesh → branch cards → single impostor — scatter.ludic layer_update 38. Texture edge dilation for cut-out atlases; 16-bit PNG decoding to RGB16/R16; RGBE HDR decoding — texture.ludic 39. Anisotropic filtering and mipmapping on all scanned maps — texture.ludic tex_upload 40. Still water: planar reflection pass through a reflection matrix with clip-below discard, depth-tinted body, soft shores, ripple normals, foam streaks, sun glitter; the surface writes depth so occlusion and temporal passes see it — water.ludic, shaders/water.frag

Anti-aliasing, camera and post-processing 41. Temporal anti-aliasing: Halton-jittered projection, depth reprojection, YCoCg neighbourhood clamping, history ping-pong — camera.ludic cam_set_jitter, shaders/taa.frag 42. Optional MSAA with alpha-to-coverage and per-mip alpha sharpening — post.ludic, shaders/impostor.frag 43. HDR pipeline (RGBA16F) with NaN/inf sanitising at every stage — post.ludic, shaders/lighting.glsl sane 44. Bloom: 13-tap downsample pyramid with soft threshold, tent upsample — shaders/bloom_down.frag, shaders/bloom_up.frag 45. Auto-exposure by mean luminance with temporal adaptation — post.ludic post_measure 46. ACES filmic tonemapping with log-space contrast — shaders/tonemap.frag 47. Colour grading: white balance, lift/gain, saturation — shaders/tonemap.frag 48. Vignette, dithering, film grain — shaders/tonemap.frag, shaders/sharpen.frag 49. Luma unsharp sharpening — shaders/sharpen.frag 50. Height-based exponential fog / aerial perspective from the prefiltered sky with sun inscatter — shaders/lighting.glsl applyFog 51. Specular anti-aliasing (highlight cap) and firefly prevention — shaders/lighting.glsl 52. Fly camera with mouse look — the Maroon Lake game (git.workshopsoft.io/workshopsoft/maroon-lake) 53. Profiling switches per stage and a frame benchmark — render.ludic r3d_env_flags

Characters and moving objects 54. glTF skins: node hierarchy, joints and inverse bind matrices loaded per model, four-influence GPU skinning, poses set per node in the model's frame — skin.ludic, shaders/skin.vert, quat.ludic 55. Actors: models placed and moved per frame (skinned or rigid), lit and cast into every cascade — actor.ludic 56. The drawn terrain height on the CPU (cubic B-spline of the texels) for things that stand on it — terrain.ludic terrain_height_smooth 57. A third-person character controller with a distance-driven procedural gait (walk / run / idle), slope and water limits, and a settling orbit camera — the Maroon Lake game (git.workshopsoft.io/workshopsoft/maroon-lake) 58. A 2D overlay over the finished frame: batched rectangles, images and proportional text from a baked font atlas (tools/blender/font_build.py) — overlay.ludic, shaders/overlay.* 59. Time of day over the HDRI: a solar arc drives the sun's direction and colour, the sky's light scales toward a deep-blue starry night, a moon lights the night, the visible sky turns with the sun and its convolutions rebake when far off, the height-field shadow rebakes as the sun moves, auto-exposure is capped at night — daylight.ludic, shaders/sky.frag, shaders/lighting.glsl 60. One point light (the campfire) in the shading — shaders/lighting.glsl fireLight 61. Static collision: ground circles in a cell grid - removed; still things are bodies in ludic.physics (Jolt) 62. Cut-out and emissive actors (a flame's cards) — actor.ludic, shaders/model.frag u_emissive 63. Per-instance skin clones (a herd posed individually), per-part tints and hidden parts on actors, uniform-location caching with frustum and distance culling — skin.ludic skin_clone, actor.ludic 64. A second point / cone light (a torch or flashlight in the hand) with a reach in metres and a gentle falloff to it — daylight.ludic daylight_hand, shaders/lighting.glsl handLight 64a. Tree foliage dithered out inside arm's length of the camera, in the depth prepass — shaders/model.vert v_near, shaders/depth.frag, #define NEAR_FADE 65. Auto-exposure adapted on the GPU: a 1x1 pass eases last frame's value toward key / mean and the tonemapper samples it, so nothing is read back (a pixel-buffer read still synchronised on Apple's GL) — post.ludic post_measure, shaders/adapt.frag 66. A PPM reader with box-filtered downscale (photo thumbnails) and word-wrapped overlay text — texture.ludic tex_load_ppm, overlay.ludic ov_text_wrap 67. The overlay batches a whole frame into one upload and draws per texture range with optional scissor clips (per-change uploads stalled the driver: 40 ms -> 25 ms), plus nine-slice, rotated, line, disc and arc primitives — overlay.ludic ov_flush, ov_clip, ov_nine, ov_sub_rot, ov_line, ov_disc, ov_arc 68. Weather on the daylight: an overcast factor greys and dims the sun and the sky's light, a fog multiplier thickens the air, a lightning flash — daylight.ludic daylight_weather 69. An outline pass: an actor carries a rim width and colour, drawn as an inverted hull depth-tested against the scene, and anything that is not an actor can queue one at a transform (a scatter instance, a tile) — actor.ludic actor_draw_outlines, outline_model, shaders/outline.frag 70. Two ways to make an island out of a survey: a radius from a centre, or the sea put around the survey's own edge with a noise-wobbled coast, both scaling the existing relief into the water and compressing the last few metres of height either side of the line into beach and shallows — terrain.ludic terrain_island, terrain_coast, shaders/heightgen.frag

Against Unreal Engine 5 and RAGE (RDR2), honestly

Technique UE5 / RAGE Here
Physically based shading, IBL, split-sum both implemented (1–4)
Cascaded shadow maps with PCF both (UE5 also virtual shadow maps) implemented (18–21); no virtual shadow maps
Temporal AA / upsampling TSR / TAA TAA implemented (41), no upscaling
Screen-space AO / GI SSAO, SSGI, Lumen SSGI + AO implemented (14); no Lumen-class GI, no ray tracing (not available on OpenGL 4.1)
Volumetric clouds and fog both HDRI sky with cloud shadows and analytic fog; no ray-marched clouds
Foliage: impostors, wind, translucency both implemented (30–34)
Nanite / virtualised geometry UE5 not applicable; LOD chain (37) instead
Terrain: height fields, layered materials, real-world data both implemented (22–27)
Water with planar reflection RAGE planar, UE SSR planar reflection implemented (40); no screen-space reflection
Post: bloom, exposure, tonemap, grading, DoF, motion blur both bloom/exposure/tonemap/grading implemented (44–49); no depth of field, no motion blur
Streaming world both chunk streaming of cover (35); terrain is one 8 km tile
Compute shaders, indirect draw, bindless both not available in OpenGL 4.1 core on macOS

Where the remaining visual gap sits: photogrammetry cards for several meadow species, ray-traced or probe-based global illumination, virtual shadow maps, and volumetric clouds. Those are the techniques that separate this from the reference.