ludic/changes/renderer-outside-the-tree.md
Orkuncakilkaya f25289db20
Some checks failed
ci / build-and-test (push) Waiting to run
commit-lint / conventional-commits (push) Waiting to run
bootstrap / cfree-fixpoint (push) Has been cancelled
docs / build-and-deploy (push) Successful in 34s
feat(gl): OpenGL 4.1 and the ludic.render3d renderer
`Gl.*` binds the whole OpenGL 4.1 core API — every entry point of the
platform gl3.h with every GL_* constant, generated by `ludic-dev glgen`
with per-call ABI thunks. Windowed builds get an NSOpenGLContext on the
existing window at Retina resolution; headless builds render into an
offscreen CGL context, so a program that uses Gl.* renders and
screenshots identically under the test harness. It links gl.ll, the
thunks and OpenGL.framework only when used; every other build stays
byte-identical.

packages/ludic.render3d is a physically based renderer written on that
surface: HDRI image-based lighting, GPU-generated terrain with scanned
PBR materials, CDLOD, cascaded shadows, glTF with skinning, instanced
vegetation with impostors, procedural grass, water, SSAO, and an HDR
pipeline with bloom, auto-exposure and ACES.

It also carries this session's work on it: the terrain at half its cost
(10.3 -> 5.4 ms of frame), the streaming hitch that got worse the longer
you played, a resize that emptied the world, and the packaging that lets
a game use the renderer from its own repository — `ludic assets`, the
material manifest shipping with the package, and shader lookup falling
back to the install root. See changes/ for each, with its numbers.

The camping game that drove all of it has moved out to its own
repository, Maroon Lake; examples/rendering/smooth.ludic stays as the
renderer's example here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 03:31:12 +03:00

39 lines
2.5 KiB
Markdown

bump: minor
type: feat
**A game can use the renderer from outside this repository.** `ludic.render3d` reads two
things from disk at run time — its GLSL, and the scanned CC0 materials — and both were
found only by a path relative to the working directory, so the renderer worked in a
Ludic checkout and nowhere else. A game living in its own repository now needs to copy
neither.
**The shaders come from the package**, wherever the package is. They belong to
`ludic.render3d` and ship with it, so the renderer looks for them beside the project
first (a Ludic checkout, where they are under `packages/`) and then under the install
root, `$LUDIC_HOME/packages/ludic.render3d` — the same place the compiler already
resolves `import "ludic.render3d/r3d.ludic"` from. Nothing to vendor, and no version of
the shaders that can drift from the version of the code that compiles them.
**`ludic assets [--force]`** fetches the scanned materials and the HDRI sky into
`assets/polyhaven/` of whatever project you run it in. The list of what to fetch is the
renderer's own — the renderer decides which materials it wants — so it moved out of the
repository's `assets/` and into the package as
`packages/ludic.render3d/assets.manifest`, where it ships with the toolchain. A game
does not keep its own copy of that list and so cannot fall out of step with the
renderer's material set. `ludic dev fetch-assets` is the same command from a checkout.
**A URL-shaped module built its binary into directories.** `project_name` took
everything after the last dot of the manifest's module path, which for a package
identified the way the package manager identifies them —
`git.host.io/user/name` — is inside the *host*: the build wrote
`build/io/user/name` instead of `build/name`. The last path segment comes first now, and
a dot inside that segment still separates namespace from package, so `ludic.render3d`
still builds as `render3d`.
**The camping game has moved out** to its own repository —
[Maroon Lake](https://git.workshopsoft.io/workshopsoft/maroon-lake) — taking
`examples/rendering/valley.ludic`, `hiker.ludic`, `camp/`, and 175 MB of survey data and
scanned kit with it. It was here as a demo of the renderer and became a game, and an
engine repository should not be carrying a game's assets. It is now the first consumer
of everything above, which is the point: what the renderer needs a game to be able to do,
it can now do from outside. `examples/rendering/smooth.ludic` stays as the renderer's
example in this tree.