What the model sees. The engine writes 7 pixel-aligned input channels; the skinner paints the target. Tap any tile to view it full size.
One geometry pass, painted into every cell
Every frame is a pure function of five numbers: map seed, camera step, theme, material, lighting. The engine renders the structure once per camera step; the skinner paints it under all 16 theme × lighting combinations. Held-out cells get rendered too: that is the answer key.
skin(channels, theme, lighting)× 16theme × lightingFull plan from deck 6: 64 cells × 40 maps × 50 camera steps. Split by map seed too, so no test frame is a neighbour of a training frame.
| example_id | map_seed | cam_step | theme | material | lighting | split |
|---|
Same seed, same skinner, two engines
Both engines write the same channel stack and hand it to one skinner. So the choice between them is about how much geometry and lighting the skinner gets to see. The dataset, the splits and the model don't change.
| Raycaster (Doom-style) | Full 3D (Three.js) | |
|---|---|---|
| Channels | 17: depth, surface ×5, material ×4, UV ×2, light, normal ×3, shadow | The same 17, with richer normals and true shadows |
| Normals | Walls face only 4 directions; floor and ceiling are flat | Any direction: round pillars, curved enemies |
| Sun and shadows | Per-cell "is this courtyard open to the sky" (Doom-style sectors) | Real shadow map: walls and enemies cast shadows |
| Camera | Turn left and right only; fixed eye height | Look up and down; eye height and ceiling height are knobs |
| Enemies | Billboard sprites that always face you | Meshes with real depth and normals |
| Variability | Low, so fewer nuisance knobs can leak a factor | High: more realism, more to randomize and audit |
| At 64×64 | Loses almost nothing | Loses much of its advantage; may push us to 128² (4× compute) |
| Determinism | Byte-identical on CPU, everywhere | Same GPU and driver gives the same bytes; across GPUs, store the shards |
| Engineering | About 300 lines, no dependencies | Three.js, shaders, a shadow pass |
| Fit to Chatforce | A clean lab instrument | Close to their real product: live re-theming |
Knobs: what we grid, what we randomize
| Knob | Role | Engines |
|---|---|---|
| Theme | Factor (gridded, held out) | Both |
| Wall material | Factor | Both |
| Lighting preset | Factor | Both |
| Map seed, enemies | Nuisance (randomized) | Both |
| Sun direction | Nuisance, per map | Both (3D casts shadows) |
| Field of view | Nuisance | Both |
| Eye and ceiling height | Nuisance | 3D only |
| Pattern scale, irregularity, finish, glow | Part of the theme record | Both (in the skinner) |
| Exposure, fog | Part of lighting | Both (in the skinner) |
Texturing: procedural, from UV
There are no texture files. Each engine computes where along a surface every pixel sits (UV). The skinner turns UV + material into bricks, tiles, panels or rock using maths, inside the shader. That's why a new theme is a new row of numbers, and why patterns stay glued to walls as you move.