A comprehensive catalog of techniques for achieving the smallest possible 3D video game assets, inspired by demoscene practices. Each technique includes compatibility notes for building effective combinations.
This section describes the fundamental axis of how static your data is - from fully retained (load once, GPU owns it forever) to fully immediate (CPU rebuilds everything every frame). This spectrum affects which techniques are compatible, where bottlenecks appear, and how debuggable your system is.
RETAINED IMMEDIATE
(Static) (Dynamic)
| |
| D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 |
| | | | | | | | | | |
GPU GPU GPU GPU Mixed Mixed CPU CPU CPU CPU
owns owns owns drives leans drives builds builds software
world scene meshes render CPU GPU GPU all renders
graph graph only cmds cmds data data allDescription: Entire world representation lives in GPU memory. GPU-driven rendering with minimal CPU involvement. Scene graph, transforms, visibility - all GPU-side.
Characteristics:
Examples:
Works well with:
Does not work well with:
Compression relevance:
Debugging characteristics:
Description: Scene graph and meshes retained on GPU, but CPU updates transforms each frame and manages object lifetime.
Characteristics:
Examples:
Works well with:
Does not work well with:
Compression relevance:
Debugging characteristics:
Description: Geometry stable, but materials, textures, or shader parameters change frequently.
Characteristics:
Examples:
Works well with:
Does not work well with:
Compression relevance:
Debugging characteristics:
Description: GPU does heavy lifting but CPU reads back results for game logic (occlusion queries, physics readback).
Characteristics:
Examples:
Works well with:
Does not work well with:
Compression relevance:
Debugging characteristics:
Description: Static world retained, dynamic objects handled more immediately. Common practical compromise.
Characteristics:
Examples:
Works well with:
Does not work well with:
Compression relevance:
Debugging characteristics:
Description: CPU decides everything each frame but reuses uploaded buffer data. Traditional immediate-mode thinking with some retention.
Characteristics:
Examples:
Works well with:
Does not work well with:
Compression relevance:
Debugging characteristics:
Description: Continuously stream geometry based on camera/player position. Hybrid retention with constant churn.
Characteristics:
Examples:
Works well with:
Does not work well with:
Compression relevance:
Debugging characteristics:
Description: GPU generates geometry each frame via compute shaders. Data flow: parameters → compute → render.
Characteristics:
Examples:
Works well with:
Does not work well with:
Compression relevance:
Debugging characteristics:
Description: CPU builds all render data every frame, uploads to GPU. True immediate mode.
Characteristics:
Examples:
Works well with:
Does not work well with:
Compression relevance:
Debugging characteristics:
Description: CPU does all rendering, writes directly to framebuffer. Ultimate immediate mode.
Characteristics:
Examples:
Works well with:
Does not work well with:
Compression relevance:
Debugging characteristics:
You noted preference for immediate mode for several reasons that are worth expanding:
1. Performance Transparency In retained mode, costs are amortized and hidden:
In immediate mode:
2. State Machine Clarity
// Retained mode question: "What is the GPU rendering right now?"
// Answer: Whatever combination of:
// - Scene graph state (when was it last modified?)
// - Pending uploads (are they done?)
// - Cached command buffers (from when?)
// - Material overrides (which are active?)
// Immediate mode answer: "Whatever I told it to render this frame."3. Debugging Workflow
// Immediate mode debugging:
if (frame == 1234) {
printf("About to draw object X at position %f,%f,%f\n", ...);
// Set breakpoint here, inspect everything
}
// Retained mode debugging:
// "The object was uploaded at frame 100,
// its transform was last set at frame 1200,
// the GPU is using command buffer from frame 1232,
// the actual draw happens... somewhere in the driver"4. Effect Implementation When implementing a new effect in immediate mode:
When implementing in retained mode:
5. Reproducibility Immediate mode: Same inputs → Same outputs (per frame) Retained mode: Same inputs → Different outputs (depending on history)
Since you want to expand on immediate mode, here are techniques that work well in that paradigm:
Each pixel independently computed from scratch. No retained geometry. Perfect immediate mode.
Implementation pattern:
// Every frame, every pixel:
for each pixel:
ray = computeRay(pixel, camera)
for steps in range(MAX_STEPS):
p = ray.origin + ray.dir * t
d = sceneSDF(p) // Evaluate ENTIRE scene
if d < EPSILON: shade and return
t += dWhy it's immediate-friendly:
Generate geometry in compute, render same frame, discard.
Pattern:
Frame N:
1. Dispatch compute (params → vertices)
2. Barrier
3. Draw generated vertices
4. Discard vertex buffer (or ring-buffer reuse)No retention, full regeneration each frame.
Vertex shader generates positions from uniforms + vertex ID.
// No vertex buffer needed
vec3 position = proceduralPosition(gl_VertexID, u_time, u_params);Upload: just uniforms (bytes). Geometry: computed.
If it can be computed in screen space, it's inherently immediate:
Instead of uploading mesh + transforms, upload:
Let shaders compute everything.
The most extreme immediate mode: render one quad, do everything in fragment shader.
// Entire 3D scene in fragment shader
void main() {
vec3 ro = cameraPos;
vec3 rd = normalize(rayDir(uv, cameraMatrix));
float t = raymarch(ro, rd);
vec3 p = ro + rd * t;
vec3 n = calcNormal(p);
vec3 col = shade(p, n, rd);
fragColor = vec4(col, 1.0);
}Data uploaded: Camera matrix, time, maybe a few floats. That's it.
Draw N instances of nothing, generate everything from instance ID:
// "Mesh" is just instance count
// glDrawArraysInstanced(GL_TRIANGLES, 0, 36, 10000); // 10000 cubes
void main() {
int cubeID = gl_InstanceID;
int vertexInCube = gl_VertexID;
vec3 cubeCenter = proceduralPosition(cubeID, u_time);
vec3 localPos = cubeVertex(vertexInCube); // One of 36 vertices
gl_Position = mvp * vec4(cubeCenter + localPos * scale, 1.0);
}Uploaded data: Zero vertex buffers. Just uniforms and draw call.
Design rendering so frame N depends only on:
Not on:
This enables:
Because immediate mode recomputes everything, you can:
This is why ShaderToy is so effective for exploration.
In immediate mode, you can inject debug visualization anywhere:
vec3 color = shade(p, n);
#ifdef DEBUG_NORMALS
color = n * 0.5 + 0.5;
#endif
#ifdef DEBUG_DEPTH
color = vec3(t / maxDist);
#endif
#ifdef DEBUG_ITERATIONS
color = vec3(float(iterations) / float(MAX_STEPS));
#endifNo retained state to corrupt. Recompile shader, see debug view.
Since immediate mode pays costs every frame, specific optimization patterns emerge:
Instead of retaining a BVH, compute hierarchical bounds analytically:
float sceneSDF(vec3 p) {
// Coarse bounds check (almost free)
if (length(p - sceneCenter) > sceneRadius) return length(p - sceneCenter) - sceneRadius;
// Check sub-regions
float d = MAX_DIST;
for (int region = 0; region < 8; region++) {
vec3 regionCenter = ...;
if (length(p - regionCenter) < regionRadius + d) {
d = min(d, regionSDF(p, region));
}
}
return d;
}In ray marching, distance = natural LOD:
// Far objects: fewer iterations automatically (larger steps)
// Near objects: more iterations (smaller steps near surface)
// LOD is emergent, not storedRender at lower resolution, upscale. Immediate mode makes this trivial:
// Half res: every frame
// Full res: every frame
// No retained buffers to manage between modesFixed time budget per frame. In immediate mode, you control this directly:
if (technique_too_slow) {
reduce MAX_STEPS;
// or simplify SDF
// or reduce resolution
// Immediate feedback on cost
}1. Write/modify shader code
2. Save file
3. Hot-reload shader (< 100ms)
4. See result
5. Repeat
Total iteration time: secondsCompare to retained mode:
1. Modify scene graph code
2. Recompile application
3. Restart application
4. Wait for assets to load
5. Navigate to test location
6. See result
7. Repeat
Total iteration time: minutesDespite the benefits of immediate mode, retained is necessary when:
The key insight: Start immediate, retain when proven necessary.
The current state of shader debugging is abysmal. You write code, compile, run, see wrong output, and then... stare at the code? Add return vec4(debugValue, 0, 0, 1) and recompile? This section explores better approaches.
Current workflow:
1. Write shader
2. Compile (hope for no errors)
3. Run application
4. See wrong output
5. Guess what's wrong
6. Add debug output (return color = normal, etc.)
7. Recompile entire application
8. Navigate back to test case
9. Squint at colors trying to interpret values
10. Repeat 5-9 approximately 47 times
11. Finally find the bug
12. Remove debug code
13. Discover you introduced a new bug while debugging
Total time: hoursImagine a development environment where:
┌─────────────────────────────────────────────────────────────────┐
│ SHADER NOTEBOOK [Run] │
├─────────────────────────────────────────────────────────────────┤
│ Cell 1: Define SDF primitives │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ (define (sphere p r) │ │
│ │ (- (length p) r)) │ │
│ │ │ │
│ │ (define (box p b) │ │
│ │ (let ((q (- (abs p) b))) │ │
│ │ (+ (length (max q 0)) (min (max q.x (max q.y q.z)) 0))))│ │
│ └─────────────────────────────────────────────────────────────┘ │
│ [✓ Compiled] [Visualize] [Trace] │
│ │
│ Cell 2: Compose scene │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ (define (scene p) │ │
│ │ (smooth-union │ │
│ │ (sphere (- p (vec3 0 1 0)) 0.5) │ │
│ │ (box p (vec3 1 0.2 1)) │ │
│ │ 0.3)) │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ [✓ Compiled] [Visualize] [Trace] │
│ │
│ ┌──────────────────────┐ ┌─────────────────────────────────┐ │
│ │ [Live Preview] │ │ Trace at cursor (123, 456): │ │
│ │ │ │ p = (0.23, 1.02, -0.5) │ │
│ │ ████████ │ │ sphere_d = 0.021 │ │
│ │ ██████████████ │ │ box_d = 0.83 │ │
│ │ ██████████████ │ │ smooth_union_d = 0.019 │ │
│ │ ████████ │ │ iterations = 34 │ │
│ │ │ │ total_distance = 4.23 │ │
│ └──────────────────────┘ └─────────────────────────────────┘ │
│ │
│ REPL> (scene (vec3 0 1 0)) │
│ => 0.0 │
│ REPL> (gradient scene (vec3 0 1 0)) │
│ => (0.0, 1.0, 0.0) ; normal points up, correct │
│ REPL> _ │
└─────────────────────────────────────────────────────────────────┘Concept: Click on any pixel, get full execution trace for that pixel.
Implementation approaches:
#ifdef TRACE_ENABLED
traceBuffer[traceIndex++] = vec4(TRACE_ID_SPHERE_DIST, d, 0, 0);
#endif // Vulkan debugPrintfEXT, requires validation layers
debugPrintfEXT("p=%v3f d=%f", p, d);Works well with:
Does not work well with:
Concept: Edit shader, see result instantly, without losing camera position or scene state.
Implementation:
File watcher detects change
→ Compile new shader (background thread)
→ If success: swap shader, keep all uniforms
→ If fail: show error inline, keep old shader running
→ Never restart applicationExisting tools with this:
What's missing: Integration with actual game engine scenes.
Concept: Overlay debug info directly on the rendered frame, togglable via hotkeys or REPL.
┌────────────────────────────────────────────────────────┐
│ [F1] Normals [F2] Depth [F3] Iterations [F4] UVs │
│ [F5] Overdraw [F6] Mip Level [F7] Shader Cost │
├────────────────────────────────────────────────────────┤
│ │
│ Scene renders here with selected overlay │
│ │
│ ┌─────────────────────┐ │
│ │ Stats: │ │
│ │ Avg iterations: 42 │ │
│ │ Max iterations: 128 │ │
│ │ Pixels at max: 2.3% │ │
│ │ Frame time: 4.2ms │ │
│ └─────────────────────┘ │
│ │
│ > _ [REPL input here] │
└────────────────────────────────────────────────────────┘REPL commands:
> set maxIterations 64 ; tweak uniform
> reload ; hot reload shaders
> capture ; save trace for this frame
> show normals ; enable normal vis
> query 320 240 ; trace specific pixel
> time scene ; profile scene SDF
> bisect scene p0 p1 0.001 ; find exact surface pointSince GPUs output colors, encode values as colors systematically:
// Standard debug palette
vec3 debugValue(float v, float minV, float maxV) {
float t = (v - minV) / (maxV - minV);
// Turbo colormap or similar
return turboColormap(t);
}
// Directional encoding
vec3 debugDirection(vec3 d) {
return d * 0.5 + 0.5; // [-1,1] -> [0,1]
}
// Signed distance encoding
vec3 debugSDF(float d) {
if (d < 0.0) return vec3(-d, 0, 0); // Inside: red
else return vec3(0, 0, d); // Outside: blue
}Enhancement: Configurable color mapping with legend overlay.
For immediate mode rendering, we can replay any frame:
Record: [Camera, Time, Uniforms] for each frame
Playback: Jump to any recorded frame, re-render, trace
Timeline:
[====|====|====|====|====|====|====|====]
^ Frame 847
Bug appears here
[Step Back] [Step Forward] [Slow Motion] [Trace This Frame]Works extremely well with: Immediate mode (stateless) Difficult with: Retained mode (need to record all state changes)
Compare two shader versions side-by-side or as diff:
┌──────────────────────────────────────────────────────────────┐
│ [Before] [After] [Diff] │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐│
│ │ │ │ │ │ ││
│ │ Old shader │ │ New shader │ │ Difference ││
│ │ output │ │ output │ │ (amplified) ││
│ │ │ │ │ │ ││
│ └────────────────┘ └────────────────┘ └────────────────┘│
│ │
│ Max diff: 0.023 at (234, 567) │
│ Mean diff: 0.0001 │
│ Pixels > threshold: 0.3% │
└──────────────────────────────────────────────────────────────┘Useful for:
Per-pixel cost visualization:
// Instrument shader to count operations
#ifdef PROFILE_MODE
int opCount = 0;
#define SIN(x) (opCount++, sin(x))
#define SQRT(x) (opCount++, sqrt(x))
// etc.
#endif
// Or use hardware counters where available
// AMD: shader_clock, shader_cycles
// NVIDIA: similar with NSightOverlay: Heatmap of shader cost per pixel.
The verbosity and inflexibility of GLSL/HLSL actively impedes the immediate-mode, exploratory workflow. A Lisp-like language would enable:
; Define an SDF primitive
(define (sphere p r)
(- (length p) r))
; Define a combinator (this is where macros shine)
(defmacro smooth-union (a b k)
`(let ((h (clamp (+ 0.5 (/ (- ,b ,a) ,k)) 0.0 1.0)))
(- (mix ,b ,a h) (* ,k h (- 1.0 h)))))
; Use it
(define (scene p)
(smooth-union
(sphere p 1.0)
(sphere (- p (vec3 1.5 0 0)) 0.8)
0.3))
; Domain repetition as a macro
(defmacro repeat-domain (p spacing body)
`(let ((,p (- (mod (+ ,p (* ,spacing 0.5)) ,spacing) (* ,spacing 0.5))))
,body))
; Infinite spheres!
(define (infinite-spheres p)
(repeat-domain p (vec3 3.0)
(sphere p 0.5)))Source (.scm/.lisp)
│
▼
┌───────────┐
│ Parser │
└───────────┘
│
▼
┌───────────┐
│ Macro │ ◄── User-defined macros expand here
│ Expansion │
└───────────┘
│
▼
┌───────────┐
│ IR │ ◄── S-expression intermediate representation
└───────────┘
│
├──────────────┬──────────────┬──────────────┐
▼ ▼ ▼ ▼
┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐
│ GLSL │ │ HLSL │ │ SPIR-V│ │ Metal │
│ Gen │ │ Gen │ │ Gen │ │ Gen │
└───────┘ └───────┘ └───────┘ └───────┘
│ │ │ │
▼ ▼ ▼ ▼
OpenGL DirectX Vulkan macOS/iOSProblem: GLSL has no generics, no templates, lots of repetition.
GLSL approach:
float smoothUnionFloat(float a, float b, float k) { ... }
vec2 smoothUnionVec2(vec2 a, vec2 b, float k) { ... }
vec3 smoothUnionVec3(vec3 a, vec3 b, float k) { ... }
vec4 smoothUnionVec4(vec4 a, vec4 b, float k) { ... }S-expr approach:
(defmacro define-smooth-union (type)
`(define (,(symbol-append 'smooth-union- type) a b k)
(let ((h (clamp (+ 0.5 (/ (- b a) k)) 0.0 1.0)))
(- (mix b a h) (* k h (- 1.0 h))))))
(define-smooth-union float)
(define-smooth-union vec2)
(define-smooth-union vec3)
(define-smooth-union vec4)
; Or even better, let type inference handle it:
(define-generic smooth-union (a b k)
(let ((h (clamp (+ 0.5 (/ (- b a) k)) 0.0 1.0)))
(- (mix b a h) (* k h (- 1.0 h))))); SDF-specific syntax
(sdf-define scene
(union
(intersect
(sphere origin 1.0)
(plane (vec3 0 1 0) 0.0))
(transform (translate 0 2 0)
(rotate-y time
(box origin (vec3 0.5))))))
; Expands to efficient GLSL with proper transforms; Trace macro for debugging
(defmacro trace (label expr)
(if *debug-mode*
`(let ((result ,expr))
(emit-trace ,label result)
result)
expr))
; Usage
(define (scene p)
(trace 'final-distance
(smooth-union
(trace 'sphere-distance (sphere p 1.0))
(trace 'box-distance (box p (vec3 1)))
0.3)))
; In release mode, traces compile away completelyExisting Lisp-to-shader compilers:
Related approaches:
What's missing: Deep integration with game engines, not just standalone tools.
Alternative: Define a tiny core, sugar on top:
Core primitives (the "kernel"):
- lambda, let, if, define
- Arithmetic: + - * / mod
- Comparisons: < > =
- Vector ops: vec2, vec3, vec4, swizzle
- Math: sin, cos, sqrt, abs, min, max, clamp, mix, length, dot, cross, normalize
Everything else: macros in user space
This kernel compiles directly to GLSL/HLSL/SPIR-V intrinsics.shader-repl> (define (sphere p r) (- (length p) r))
; sphere defined
shader-repl> (sphere (vec3 0 0 0) 1.0)
; => -1.0 (inside the sphere)
shader-repl> (sphere (vec3 2 0 0) 1.0)
; => 1.0 (outside the sphere)
shader-repl> (gradient sphere (vec3 1 0 0) 0.001)
; => (1.0, 0.0, 0.0) (normal points +X)
shader-repl> (render scene #:width 800 #:height 600)
; [Opens preview window]
shader-repl> (set! *camera-pos* (vec3 0 2 5))
; [Preview updates immediately]
shader-repl> (export-glsl scene "scene.glsl")
; Wrote scene.glsl
shader-repl> (time (scene (vec3 0 0 0)))
; 0.000023ms per evaluation (CPU reference)
; Estimated GPU: ~0.0001ms per pixelThe unfortunate reality: most techniques must eventually work with Godot, Unreal, or Unity. Here's a realistic assessment of integration difficulty.
★★★★★ - Native support, just use it
★★★★☆ - Plugin/extension exists, works well
★★★☆☆ - Possible with effort, some limitations
★★☆☆☆ - Hacky, fights the engine, fragile
★☆☆☆☆ - Theoretically possible, practically painful
☆☆☆☆☆ - Fundamentally incompatible, don't try| Aspect | Godot 4 | Unreal 5 | Unity 2022+ |
|---|---|---|---|
| Renderer | Vulkan/OpenGL (custom) | RHI abstraction | SRP (URP/HDRP) |
| Shader lang | Godot Shading Language | HLSL + Material Editor | HLSL/ShaderLab |
| Custom shaders | ★★★★☆ Easy | ★★★☆☆ Complex | ★★★★☆ Moderate |
| Compute shaders | ★★★☆☆ Recent addition | ★★★★☆ Good support | ★★★★☆ Good support |
| Custom render passes | ★★★☆☆ Possible | ★★☆☆☆ Very complex | ★★★★☆ SRP makes this easier |
| Hot reload shaders | ★★★★★ Built-in | ★★★☆☆ Editor only | ★★★★☆ Works |
| Source access | ★★★★★ Open source | ★★★★☆ Source available | ☆☆☆☆☆ Closed |
| Technique | Godot 4 | Unreal 5 | Unity | Notes |
|---|---|---|---|---|
| G1: Billboards | ★★★★★ | ★★★★★ | ★★★★★ | Universal support |
| G2: SDFs (ray marched) | ★★★☆☆ | ★★☆☆☆ | ★★★☆☆ | Custom shader, fights lighting |
| G3: Standard meshes | ★★★★★ | ★★★★★ | ★★★★★ | This is what engines do |
| G4: Voxels | ★★★☆☆ | ★★★☆☆ | ★★★☆☆ | Plugins exist, not native |
| G5: Gaussian Splats | ★★☆☆☆ | ★★★☆☆ | ★★★☆☆ | Emerging plugin support |
| G6: Nanite-style | ☆☆☆☆☆ | ★★★★★ | ☆☆☆☆☆ | UE5 exclusive |
| G9: Subdivision | ★★☆☆☆ | ★★★☆☆ | ★★☆☆☆ | Limited runtime support |
| Technique | Godot 4 | Unreal 5 | Unity | Notes |
|---|---|---|---|---|
| P1: Proc buildings | ★★★☆☆ | ★★★★☆ | ★★★☆☆ | Houdini→UE pipeline good |
| P2: Proc terrain | ★★★★☆ | ★★★★★ | ★★★★☆ | Good support across |
| P4: Proc textures | ★★★★☆ | ★★★★☆ | ★★★★☆ | Shader-based, universal |
| P6: Compute gen | ★★★☆☆ | ★★★★☆ | ★★★★☆ | Godot compute newer |
| Technique | Godot 4 | Unreal 5 | Unity | Notes |
|---|---|---|---|---|
| T1: BC/DXT/ASTC | ★★★★★ | ★★★★★ | ★★★★★ | Universal |
| T4: Virtual texturing | ☆☆☆☆☆ | ★★★★★ | ★★☆☆☆ | UE has best support |
| T6: Procedural tex | ★★★★☆ | ★★★☆☆ | ★★★★☆ | UE material editor verbose |
| T7: Triplanar | ★★★★★ | ★★★★★ | ★★★★★ | Easy shader technique |
| Technique | Godot 4 | Unreal 5 | Unity | Notes |
|---|---|---|---|---|
| R1: Rasterization | ★★★★★ | ★★★★★ | ★★★★★ | Default |
| R2: Ray marching | ★★★☆☆ | ★★☆☆☆ | ★★★☆☆ | Custom pass needed |
| R5: Deferred | ★★★★☆ | ★★★★★ | ★★★★☆ | HDRP is deferred |
| R7: RT/Path tracing | ★★☆☆☆ | ★★★★★ | ★★★★☆ | UE5 Lumen excellent |
| Technique | Godot 4 | Unreal 5 | Unity | Notes |
|---|---|---|---|---|
| A2: Skeletal | ★★★★★ | ★★★★★ | ★★★★★ | Core feature |
| A4: Procedural | ★★★☆☆ | ★★★★☆ | ★★★★☆ | UE Control Rig good |
| A5: VAT | ★★★☆☆ | ★★★★☆ | ★★★★☆ | Plugins/workflows exist |
| Technique | Godot 4 | Unreal 5 | Unity | Notes |
|---|---|---|---|---|
| Shader hot reload | ★★★★★ | ★★★☆☆ | ★★★★☆ | Godot best here |
| Custom render pass | ★★★☆☆ | ★★☆☆☆ | ★★★★☆ | Unity SRP helps |
| Debug visualization | ★★★☆☆ | ★★★★☆ | ★★★★☆ | UE has good tools |
| REPL-style workflow | ★★☆☆☆ | ★☆☆☆☆ | ★★☆☆☆ | None support well |
| Custom shader lang | ★★☆☆☆ | ★☆☆☆☆ | ★★★☆☆ | Unity allows preprocessing |
Advantages:
Challenges:
Recommended approach for immediate-mode/SDF:
1. Create GDExtension in C++/Rust
2. Write custom VisualServer rendering commands
3. Use ComputeShader for generation
4. Hook into Godot's shader preprocessor for custom syntax
Difficulty: ★★★☆☆ (Medium, source helps)S-expr shader integration:
Option A: Transpile to Godot Shading Language
- Godot's shader lang is simple, good target
- Loses some GLSL features but gains simplicity
Option B: GDExtension that compiles to SPIR-V directly
- Bypass Godot's shader compiler
- More complex but more powerful
Difficulty: ★★★☆☆ (Medium)Advantages:
Challenges:
Recommended approach for immediate-mode/SDF:
1. Use Custom Stencil Buffer approach (hacky)
2. Or: Create custom SceneViewExtension
3. Or: Modify Deferred Shading pass (requires engine mod)
4. For simple cases: Ray march in post-process material
Difficulty: ★★☆☆☆ (Hard, fights the engine)S-expr shader integration:
Option A: Generate HLSL, inject via Custom node in Materials
- Limited to material graph context
- Can't easily do full custom passes
Option B: Generate USF files, register as global shaders
- More powerful, much more complex
- Need to understand RDG (Render Dependency Graph)
Option C: Plugin that preprocesses .usf files
- Intercept shader compilation
- Very fragile, version-dependent
Difficulty: ★☆☆☆☆ (Very Hard)What UE5 is good at (use these instead):
Advantages:
Challenges:
Recommended approach for immediate-mode/SDF:
1. Create custom RenderFeature in URP/HDRP
2. Add custom render pass
3. Full control over what's rendered
4. Can inject compute shaders
Difficulty: ★★★☆☆ (Medium, SRP helps)S-expr shader integration:
Option A: Transpile to HLSL, use as .shader files
- Most straightforward
- Can use ShaderLab wrapper for multi-platform
Option B: Custom ScriptedImporter for .scm files
- Editor recognizes your file type
- Compiles on import
- Good workflow integration
Option C: Shader preprocessing via IPreprocessShaders
- Intercept compilation
- Transform AST before Unity compiles
Difficulty: ★★★☆☆ (Medium, good extensibility)If your priority is...
| Priority | Recommended | Reasoning |
|---|---|---|
| Immediate mode workflow | Godot | Best hot reload, simplest to modify |
| Custom shader language | Unity | Best preprocessing hooks |
| Maximum visual quality | Unreal | Nanite, Lumen, etc. |
| SDF-based rendering | Godot | Easiest to add custom render pass |
| Procedural generation | Unreal | Houdini integration, PCG framework |
| Open source control | Godot | Only option |
| VR/AR | Unity | Best XR support historically |
| Tiny executable size | Godot | Smallest runtime |
| AAA production | Unreal | Industry standard |
When engines fight you too much:
Strategy: Render to texture in custom code, composite in engine
┌─────────────────────────────────────────────────────────────┐
│ Your Custom Renderer │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ S-expr Shader │ ──► │ GLSL/HLSL/MSL │ │
│ │ Compiler │ │ │ │
│ └─────────────────┘ └─────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ Custom Rendering Context │ │
│ │ (Separate window or shared context) │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Render to Texture │
│ │ │
└─────────────────────────┼───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Game Engine │
│ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ Apply texture to quad / full-screen pass │ │
│ │ Engine handles: UI, physics, audio, input, etc. │ │
│ └───────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘Benefits:
Drawbacks:
WebGPU is emerging as a potential universal shader target:
S-expr source
│
▼
WGSL output
│
├──► Browser (native WebGPU)
├──► Desktop (Dawn/wgpu)
└──► Engines (via plugins)
├──► Godot (wgpu backend in development)
├──► Unity (WebGPU export)
└──► Unreal (less likely)Advantages:
Current status: Promising but not production-ready for games.
| Position | Compression Strategy | Rationale |
|---|---|---|
| D1-D2 (Retained) | Heavy offline compression (Draco, BC7, Basis) | Amortize decode cost over long retention |
| D3-D5 (Mixed) | Balanced compression, fast decode | Some retained, some dynamic |
| D6-D7 (Streaming) | Progressive, fast decode | Bandwidth limited, can't wait |
| D8-D9 (Immediate) | Minimal/no compression | Decode cost paid every frame |
| D10 (Software) | Whatever CPU handles | Different constraints entirely |
Key insight: In immediate mode, your "compression" is your procedural algorithm. The SDF function IS the compressed representation of your geometry.
| Technique | Best Spectrum Position | Notes |
|---|---|---|
| G2 (SDFs) | D8-D10 | Inherently immediate, computed not stored |
| G6 (Nanite) | D1 | Extremely retained, GPU-driven |
| G4 (Voxels) | D5-D8 | Can be either, often dynamic |
| P6 (Compute generation) | D8 | Generated each frame |
| T6 (Procedural textures) | D8-D9 | No texture data, computed |
| R2 (Ray marching) | D8-D10 | Stateless per-pixel |
| G1 (Billboards) | D2-D5 | Usually retained, updated |
| A5 (Vertex Animation Textures) | D2 | Retained, sampled |
After cataloging these techniques, several meta-patterns emerge:
RETAINED ◄─────────────────────────────────── IMMEDIATE
D1 D2 D3 D4 D5 D6 D7 D8 D9 D10
────────────────────────────────────────────────────────►
Easy to depend on things to the RIGHT (more immediate)
◄────────────────────────────────────────────────────────
Hard to depend on things to the LEFT (more retained)Why this happens:
Examples:
Implication: Design your most constrained/retained systems first, then fill in with more immediate techniques.
High Compression Value ◄─────────────────► Low Compression Value
D1 D2 D3 D4 D5 D6 D7 D8 D9 D10
The more retained, the more compression matters.
The more immediate, the less traditional compression applies.At D1-D3: Heavy compression (Draco, BC7, Basis) - amortized over long retention At D4-D6: Moderate compression - balance decode speed vs. size At D7-D8: Light/fast compression - streaming, decode cost matters At D9-D10: Algorithm IS compression - procedural = maximally compressed
Implication: If you're targeting extreme compression, you're implicitly pushed toward immediate/procedural.
Hard to Debug ◄───────────────────────────► Easy to Debug
D1 D2 D3 D4 D5 D6 D7 D8 D9 D10Why:
Implication: Develop in immediate mode (D8-D10), then migrate leftward for performance.
Good Engine Support ◄────────────────────► Poor Engine Support
D1 D2 D3 D4 D5 D6 D7 D8 D9 D10
(With exception of D1 in UE5 specifically due to Nanite)Why: Game engines are built around retained scene graphs (D2-D3). They have pipelines for:
They don't have pipelines for:
Exception: UE5's Nanite is D1, but required rewriting Unreal's entire renderer.
Implication: The more immediate your technique, the more you fight the engine.
For most practical game development:
D5-D6 characteristics:
Almost all procedural techniques (P1-P8) naturally live at D8:
The procedural bargain: Trade compute for storage.
The ART* techniques (single primitive, single palette, low resolution) enable:
Implication: Artistic constraints are technical enablers.
Animation is the hardest category for immediate mode because:
Solutions:
There are essentially two graphics programming cultures:
Culture A: Retained/Engine (D1-D4)
Culture B: Immediate/Procedural (D7-D10)
Most techniques belong clearly to one culture. Mixing them is possible but requires bridging.
Demoscene 4KB/64KB intros occupy D8-D10 exclusively:
This represents the theoretical minimum for 3D graphics: pure algorithm, zero assets.
This table shows which techniques work at which spectrum positions.
Legend:
| Technique | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 |
|---|---|---|---|---|---|---|---|---|---|---|
| G1: Billboards | ◐ | ● | ● | ● | ● | ● | ● | ◐ | ◐ | ◐ |
| G2: SDFs | ✗ | ✗ | ✗ | ○ | ◐ | ◐ | ● | ● | ● | ● |
| G3: Polygon Meshes | ● | ● | ● | ● | ● | ● | ◐ | ○ | ○ | ◐ |
| G4: Voxels | ◐ | ◐ | ◐ | ◐ | ● | ● | ● | ● | ◐ | ◐ |
| G5: Gaussian Splats | ● | ● | ◐ | ◐ | ◐ | ○ | ○ | ✗ | ✗ | ✗ |
| G6: Nanite-style | ● | ○ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| G7: Mesh Compression | ● | ● | ● | ● | ● | ● | ● | ✗ | ✗ | ✗ |
| G8: Implicit Noise | ✗ | ✗ | ○ | ◐ | ◐ | ● | ● | ● | ● | ● |
| G9: Subdivision | ◐ | ● | ● | ● | ● | ◐ | ○ | ○ | ○ | ○ |
| G10: Displacement | ◐ | ● | ● | ● | ● | ● | ◐ | ○ | ○ | ○ |
| G11: CSG | ✗ | ○ | ○ | ◐ | ● | ● | ● | ● | ● | ● |
| G12: NURBS/Curves | ○ | ● | ● | ● | ● | ◐ | ◐ | ○ | ○ | ○ |
| G13: Height Maps | ◐ | ● | ● | ● | ● | ● | ● | ● | ◐ | ◐ |
| G14: Sprite Stacking | ✗ | ● | ● | ● | ● | ● | ◐ | ○ | ● | ● |
| G15: Style Transfer | ✗ | ○ | ◐ | ◐ | ● | ● | ● | ● | ○ | ✗ |
| G16: Geometry Images | ● | ● | ● | ◐ | ◐ | ○ | ○ | ✗ | ✗ | ✗ |
(Additional technique × spectrum tables for Procedural, Texture, Rendering, etc. continue in the full document)
These matrices show how different techniques work together.
Legend:
| G1 Bill | G2 SDF | G3 Mesh | G4 Voxel | G5 Splat | G6 Nanite | G8 Noise | G9 Subdiv | G11 CSG | G13 Height | |
|---|---|---|---|---|---|---|---|---|---|---|
| G1 Billboard | ➖ | ❌ | ✅ | ⚠️ | ⚠️ | ✅ | ❌ | ⚠️ | ❌ | ✅ |
| G2 SDF | ❌ | ➖ | ❌ | ⚠️ | ❌ | ❌ | ✅ | ❌ | ✅ | ⚠️ |
| G3 Mesh | ✅ | ❌ | ➖ | ⚠️ | ⚠️ | ✅ | ⚠️ | ✅ | ⚠️ | ✅ |
| G4 Voxel | ⚠️ | ⚠️ | ⚠️ | ➖ | ❌ | ❌ | ✅ | ❌ | ✅ | ✅ |
| G5 Splat | ⚠️ | ❌ | ⚠️ | ❌ | ➖ | ❌ | ❌ | ❌ | ❌ | ⚠️ |
| G6 Nanite | ✅ | ❌ | ✅ | ❌ | ❌ | ➖ | ❌ | ⚠️ | ❌ | ⚠️ |
| G8 Noise | ❌ | ✅ | ⚠️ | ✅ | ❌ | ❌ | ➖ | ⚠️ | ✅ | ✅ |
| G9 Subdiv | ⚠️ | ❌ | ✅ | ❌ | ❌ | ⚠️ | ⚠️ | ➖ | ⚠️ | ⚠️ |
| G11 CSG | ❌ | ✅ | ⚠️ | ✅ | ❌ | ❌ | ✅ | ⚠️ | ➖ | ⚠️ |
| G13 Height | ✅ | ⚠️ | ✅ | ✅ | ⚠️ | ⚠️ | ✅ | ⚠️ | ⚠️ | ➖ |
Key Observations:
| R1 Forward | R2 RayMarch | R3 VoxCast | R4 Particle | R5 Deferred | R6 Forward+ | R7 RT | |
|---|---|---|---|---|---|---|---|
| G1 Billboard | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ⚠️ |
| G2 SDF | ❌ | ✅ | ⚠️ | ❌ | ❌ | ❌ | ⚠️ |
| G3 Mesh | ✅ | ❌ | ❌ | ⚠️ | ✅ | ✅ | ✅ |
| G4 Voxel | ⚠️ | ⚠️ | ✅ | ⚠️ | ⚠️ | ⚠️ | ⚠️ |
| G5 Splat | ⚠️ | ❌ | ❌ | ✅ | ⚠️ | ⚠️ | ❌ |
| G6 Nanite | ⚠️ | ❌ | ❌ | ⚠️ | ✅ | ⚠️ | ✅ |
| G8 Noise | ⚠️ | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ | ⚠️ |
| G9 Subdiv | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
| G11 CSG | ⚠️ | ✅ | ⚠️ | ❌ | ⚠️ | ⚠️ | ⚠️ |
| G13 Height | ✅ | ⚠️ | ⚠️ | ⚠️ | ✅ | ✅ | ✅ |
Key Observations:
| T1 Compress | T3 Atlas | T4 Virtual | T6 ProcTex | T7 Triplanar | T8 Palette | |
|---|---|---|---|---|---|---|
| G1 Billboard | ✅ | ✅ | ✅ | ⚠️ | ❌ | ✅ |
| G2 SDF | ❌ | ❌ | ❌ | ✅ | ✅ | ⚠️ |
| G3 Mesh | ✅ | ✅ | ✅ | ✅ | ⚠️ | ✅ |
| G4 Voxel | ⚠️ | ⚠️ | ⚠️ | ✅ | ✅ | ✅ |
| G5 Splat | ⚠️ | ⚠️ | ⚠️ | ❌ | ❌ | ❌ |
| G6 Nanite | ✅ | ✅ | ✅ | ✅ | ⚠️ | ⚠️ |
| G8 Noise | ❌ | ❌ | ❌ | ✅ | ✅ | ⚠️ |
| G11 CSG | ⚠️ | ⚠️ | ⚠️ | ✅ | ✅ | ✅ |
| G13 Height | ✅ | ⚠️ | ✅ | ✅ | ✅ | ✅ |
Key Observations:
| A1 Keyframe | A2 Skeletal | A4 Procedural | A5 VAT | A6 Morph | |
|---|---|---|---|---|---|
| G1 Billboard | ✅ | ❌ | ⚠️ | ⚠️ | ❌ |
| G2 SDF | ⚠️ | ❌ | ✅ | ❌ | ⚠️ |
| G3 Mesh | ✅ | ✅ | ✅ | ✅ | ✅ |
| G4 Voxel | ⚠️ | ❌ | ✅ | ⚠️ | ❌ |
| G6 Nanite | ✅ | ⚠️ | ⚠️ | ⚠️ | ⚠️ |
| G8 Noise | ⚠️ | ❌ | ✅ | ❌ | ⚠️ |
| G9 Subdiv | ✅ | ✅ | ✅ | ⚠️ | ✅ |
| G11 CSG | ⚠️ | ❌ | ✅ | ❌ | ⚠️ |
| G13 Height | ✅ | ❌ | ✅ | ⚠️ | ⚠️ |
Key Observations:
| M1 Flat | M2 Phong | M3 PBR | M4 Lightmap | M7 Toon | M8 Matcap | |
|---|---|---|---|---|---|---|
| G1 Billboard | ✅ | ⚠️ | ⚠️ | ⚠️ | ✅ | ✅ |
| G2 SDF | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
| G3 Mesh | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| G4 Voxel | ✅ | ✅ | ⚠️ | ⚠️ | ✅ | ⚠️ |
| G5 Splat | ✅ | ⚠️ | ⚠️ | ❌ | ⚠️ | ❌ |
| G6 Nanite | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| G8 Noise | ✅ | ✅ | ⚠️ | ❌ | ✅ | ✅ |
| G11 CSG | ✅ | ✅ | ⚠️ | ❌ | ✅ | ✅ |
| G13 Height | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
Key Observations:
A condensed view of the most important technique interactions across all categories:
| G2 SDF | G3 Mesh | G4 Vox | G6 Nan | P6 Comp | T6 Proc | R2 March | R5 Def | M3 PBR | M4 Light | A2 Skel | A4 Proc | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| G2 SDF | ➖ | ❌ | ⚠️ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ |
| G3 Mesh | ❌ | ➖ | ⚠️ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| G4 Voxel | ⚠️ | ⚠️ | ➖ | ❌ | ✅ | ✅ | ⚠️ | ⚠️ | ⚠️ | ⚠️ | ❌ | ✅ |
| G6 Nanite | ❌ | ✅ | ❌ | ➖ | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ⚠️ | ⚠️ |
| P6 Compute | ✅ | ✅ | ✅ | ❌ | ➖ | ✅ | ⚠️ | ⚠️ | ⚠️ | ❌ | ⚠️ | ✅ |
| T6 ProcTex | ✅ | ✅ | ✅ | ✅ | ✅ | ➖ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
| R2 RayMarch | ✅ | ❌ | ⚠️ | ❌ | ⚠️ | ✅ | ➖ | ⚠️ | ✅ | ❌ | ❌ | ✅ |
| R5 Deferred | ❌ | ✅ | ⚠️ | ✅ | ⚠️ | ✅ | ⚠️ | ➖ | ✅ | ✅ | ✅ | ✅ |
| M3 PBR | ✅ | ✅ | ⚠️ | ✅ | ⚠️ | ✅ | ✅ | ✅ | ➖ | ✅ | ✅ | ✅ |
| M4 Lightmap | ❌ | ✅ | ⚠️ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ➖ | ⚠️ | ❌ |
| A2 Skeletal | ❌ | ✅ | ❌ | ⚠️ | ⚠️ | ✅ | ❌ | ✅ | ✅ | ⚠️ | ➖ | ✅ |
| A4 ProcAnim | ✅ | ✅ | ✅ | ⚠️ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ➖ |
Paradigm Clusters Visible:
The matrix reveals four fundamental splits:
| Split | Left Side | Right Side | Root Cause |
|---|---|---|---|
| Representation | G2 SDF, G8 Noise, G11 CSG | G3 Mesh, G6 Nanite, G9 Subdiv | Mathematical function vs stored triangles |
| Rendering | R2 Ray March, R3 Voxel Cast | R1 Forward, R5 Deferred, R7 RT | Per-pixel evaluation vs rasterization |
| Data Source | P6 Compute, T6 Procedural, A4 Procedural | M4 Lightmap, A2 Skeletal, A5 VAT | Runtime computation vs precomputed data |
| Parameterization | G2, G4, G8, G11 (no UVs) | G3, G6, G9 (UVs) | Implicit surface vs explicit mapping |
Pre-validated technique combinations for common use cases:
G2 (SDF) + P8 (Fractal) + T6 (Procedural) + R2 (RayMarch) + M2 (Phong) + A4 (Procedural)✅ All compatible - pure procedural, no stored data
G3 (Mesh) + G1 (Billboard) + T1 (Compress) + T3 (Atlas) + R1 (Forward) + M4 (Lightmap) + A2 (Skeletal) + L1 (Discrete LOD)✅ All compatible - traditional retained, baked lighting
G6 (Nanite) + G3 (Mesh) + P2 (Terrain) + T4 (Virtual) + R5 (Deferred) + R7 (RT) + M3 (PBR) + M4 (Lightmap) + A2 (Skeletal) + L5 (Streaming)✅ All compatible - Nanite + traditional with streaming
G4 (Voxel) + P6 (Compute) + T8 (Palette) + R3 (VoxelCast) + M2 (Phong) + A4 (Procedural) + C7 (DAG)✅ All compatible - voxel-focused stack
G3 (Mesh) + G9 (Subdiv) + T6 (Procedural) + T8 (Palette) + R1 (Forward) + M7 (Toon) + M8 (Matcap) + A2 (Skeletal) + A4 (Procedural)✅ All compatible - stylized with procedural touches
| Technique | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 |
|---|---|---|---|---|---|---|---|---|---|---|
| P1: Proc Buildings | ○ | ◐ | ◐ | ◐ | ● | ● | ● | ● | ◐ | ◐ |
| P2: Proc Terrain | ○ | ◐ | ◐ | ● | ● | ● | ● | ● | ◐ | ◐ |
| P3: Proc Vegetation | ○ | ◐ | ◐ | ● | ● | ● | ● | ● | ◐ | ○ |
| P4: Proc Textures | ✗ | ○ | ◐ | ● | ● | ● | ● | ● | ● | ● |
| P5: Wang Tiles | ◐ | ● | ● | ● | ● | ● | ◐ | ○ | ○ | ○ |
| P6: Compute Gen | ○ | ○ | ○ | ◐ | ● | ● | ● | ● | ✗ | ✗ |
| P7: Grammar-Based | ○ | ◐ | ◐ | ◐ | ● | ● | ● | ● | ● | ● |
| P8: Fractals | ✗ | ○ | ○ | ◐ | ● | ● | ● | ● | ● | ● |
| Technique | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 |
|---|---|---|---|---|---|---|---|---|---|---|
| T1: GPU Compression | ● | ● | ● | ● | ● | ● | ● | ○ | ○ | ✗ |
| T2: Supercompression | ● | ● | ● | ● | ● | ● | ● | ○ | ○ | ○ |
| T3: Atlasing | ● | ● | ● | ● | ● | ● | ◐ | ○ | ○ | ○ |
| T4: Virtual Texturing | ● | ● | ● | ● | ◐ | ◐ | ● | ○ | ✗ | ✗ |
| T5: Tex Synthesis | ○ | ◐ | ◐ | ● | ● | ● | ● | ● | ◐ | ◐ |
| T6: Procedural Tex | ✗ | ○ | ◐ | ● | ● | ● | ● | ● | ● | ● |
| T7: Triplanar | ◐ | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| T8: Palette-Based | ◐ | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| T9: Polynomial Approx | ✗ | ○ | ○ | ◐ | ● | ● | ● | ● | ● | ● |
| T10: Fourier/DCT | ○ | ◐ | ◐ | ● | ● | ● | ● | ● | ◐ | ◐ |
| T11: Neural Compress | ● | ● | ◐ | ◐ | ◐ | ○ | ○ | ○ | ✗ | ✗ |
| T12: Detail Textures | ● | ● | ● | ● | ● | ● | ● | ◐ | ◐ | ◐ |
| T14: Material ID | ◐ | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| Technique | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 |
|---|---|---|---|---|---|---|---|---|---|---|
| R1: Rasterization | ● | ● | ● | ● | ● | ● | ● | ◐ | ◐ | ◐ |
| R2: Ray Marching | ✗ | ✗ | ○ | ◐ | ● | ● | ● | ● | ● | ● |
| R3: Voxel Raycasting | ○ | ◐ | ◐ | ● | ● | ● | ● | ● | ● | ● |
| R4: Particles | ● | ● | ● | ● | ● | ● | ● | ● | ◐ | ◐ |
| R5: Deferred | ● | ● | ● | ● | ● | ◐ | ○ | ○ | ✗ | ✗ |
| R6: Forward+ | ● | ● | ● | ● | ● | ● | ◐ | ○ | ○ | ✗ |
| R7: Hybrid RT | ● | ● | ● | ● | ◐ | ◐ | ○ | ○ | ✗ | ✗ |
| R8: Software Raster | ● | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| Technique | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 |
|---|---|---|---|---|---|---|---|---|---|---|
| C1: Delta Encoding | ● | ● | ● | ● | ● | ● | ● | ○ | ○ | ○ |
| C2: Quantization | ● | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| C3: Octree | ● | ● | ● | ● | ● | ● | ● | ● | ◐ | ◐ |
| C4: Run-Length | ● | ● | ● | ● | ● | ● | ● | ○ | ○ | ○ |
| C5: LZ-family | ● | ● | ● | ● | ● | ● | ● | ○ | ○ | ○ |
| C6: Entropy Coding | ● | ● | ● | ● | ● | ● | ◐ | ○ | ○ | ○ |
| C7: Sparse Voxel DAG | ● | ● | ◐ | ◐ | ● | ● | ● | ○ | ✗ | ✗ |
| C8: PCA/SVD | ● | ● | ● | ● | ● | ◐ | ◐ | ○ | ○ | ○ |
| Technique | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 |
|---|---|---|---|---|---|---|---|---|---|---|
| L1: Discrete LOD | ● | ● | ● | ● | ● | ● | ◐ | ○ | ○ | ○ |
| L2: Continuous LOD | ● | ● | ● | ● | ● | ● | ● | ◐ | ○ | ○ |
| L3: HLOD | ● | ● | ◐ | ◐ | ● | ◐ | ○ | ✗ | ✗ | ✗ |
| L4: Impostor LOD | ● | ● | ● | ● | ● | ● | ● | ◐ | ◐ | ◐ |
| L5: Streaming | ● | ● | ● | ● | ● | ● | ● | ○ | ✗ | ✗ |
| Technique | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 |
|---|---|---|---|---|---|---|---|---|---|---|
| A1: Keyframe | ● | ● | ● | ● | ● | ● | ◐ | ○ | ○ | ○ |
| A2: Skeletal | ● | ● | ● | ● | ● | ◐ | ○ | ○ | ○ | ○ |
| A3: Anim Compression | ● | ● | ● | ● | ● | ● | ◐ | ✗ | ✗ | ✗ |
| A4: Procedural Anim | ○ | ◐ | ◐ | ● | ● | ● | ● | ● | ● | ● |
| A5: VAT | ● | ● | ● | ● | ● | ◐ | ◐ | ○ | ✗ | ✗ |
| A6: Morph Targets | ● | ● | ● | ● | ● | ● | ◐ | ○ | ○ | ○ |
| A7: Bone Baking | ● | ● | ● | ● | ● | ◐ | ○ | ✗ | ✗ | ✗ |
| A8: Flipbook | ◐ | ● | ● | ● | ● | ● | ● | ◐ | ● | ● |
| Technique | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 |
|---|---|---|---|---|---|---|---|---|---|---|
| M1: Flat/Unlit | ● | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| M2: Lambert/Phong | ● | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| M3: PBR | ● | ● | ● | ● | ● | ● | ◐ | ◐ | ○ | ○ |
| M4: Lightmaps | ● | ● | ● | ◐ | ◐ | ○ | ○ | ✗ | ✗ | ✗ |
| M5: Spherical Harm | ● | ● | ● | ● | ● | ● | ◐ | ○ | ○ | ○ |
| M6: Light Probes | ● | ● | ● | ● | ● | ◐ | ○ | ○ | ✗ | ✗ |
| M7: Toon Shading | ● | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| M8: Matcaps | ● | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| Technique | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 |
|---|---|---|---|---|---|---|---|---|---|---|
| ART1: Single Primitive | ○ | ◐ | ● | ● | ● | ● | ● | ● | ● | ● |
| ART2: Single Palette | ● | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| ART3: Low Resolution | ● | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| ART4: Outline Only | ◐ | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| ART5: Silhouette Design | ● | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| Technique | D1 | D2 | D3 | D4 | D5 | D6 | D7 | D8 | D9 | D10 |
|---|---|---|---|---|---|---|---|---|---|---|
| IM1: Ray March SDF | ✗ | ✗ | ✗ | ○ | ◐ | ● | ● | ● | ● | ● |
| IM2: Compute→Render | ✗ | ✗ | ○ | ◐ | ● | ● | ● | ● | ✗ | ✗ |
| IM3: Uniform-Driven | ✗ | ○ | ◐ | ● | ● | ● | ● | ● | ● | ✗ |
| IM4: Screen-Space | ◐ | ● | ● | ● | ● | ● | ● | ● | ● | ● |
| IM6: Fullscreen+Math | ✗ | ✗ | ✗ | ○ | ◐ | ● | ● | ● | ● | ● |
| IM7: Instanced Proc | ✗ | ○ | ◐ | ● | ● | ● | ● | ● | ○ | ✗ |
To find techniques for a specific spectrum position: Read down the column. ● and ◐ are viable choices.
To see how universal a technique is: Read across the row. More ● = more universal.
Most universal techniques (work everywhere):
Most position-specific techniques:
This appendix provides search-based links to documentation, examples, papers, and tools. Using search links rather than direct URLs helps prevent link rot.
All links use DuckDuckGo searches. Format: https://duckduckgo.com/?q=<search+terms>
This section catalogs the minimum hardware and API requirements for each technique, enabling filtering by target platform.
| Tier | Name | GPU Examples | Era | Typical Use |
|---|---|---|---|---|
| HW0 | Ancient | Intel GMA, GeForce 6/7 | 2004-2006 | Retro, embedded |
| HW1 | Old | GeForce 8/9, Radeon HD 2000-4000 | 2006-2009 | Legacy support |
| HW2 | Moderate | GeForce 400-600, Radeon HD 5000-7000 | 2010-2013 | Wide compatibility |
| HW3 | Modern | GeForce 900+, Radeon RX 400+, Intel UHD | 2015-2019 | Current mainstream |
| HW4 | Current | GeForce RTX 20+, Radeon RX 6000+, Intel Arc | 2020+ | High-end features |
| HW5 | Cutting Edge | RTX 40+, RX 7000+, with mesh shaders/RT | 2022+ | Newest features |
| Tier | Name | GPU Examples | Era | Typical Use |
|---|---|---|---|---|
| MW0 | Ancient Mobile | Adreno 200, Mali-400 | 2010-2013 | Legacy devices |
| MW1 | Old Mobile | Adreno 300, Mali-T600, PowerVR 6 | 2013-2015 | Budget devices |
| MW2 | Moderate Mobile | Adreno 500, Mali-G71, Apple A9 | 2016-2018 | Mid-range |
| MW3 | Modern Mobile | Adreno 600+, Mali-G77+, Apple A12+ | 2019+ | Current phones |
| MW4 | Current Mobile | Adreno 700+, Mali-G710+, Apple A15+ | 2021+ | Flagship phones |
| Tier | Name | APIs | Features |
|---|---|---|---|
| SW0 | Legacy | OpenGL 2.1, ES 2.0, DX9 | Fixed function fallbacks, basic shaders |
| SW1 | Established | OpenGL 3.3, ES 3.0, DX10 | Full programmable pipeline, instancing |
| SW2 | Modern | OpenGL 4.3, ES 3.1, DX11 | Compute shaders, tessellation |
| SW3 | Explicit | Vulkan 1.0, DX12, Metal | Explicit memory, async compute |
| SW4 | Cutting Edge | Vulkan 1.3, DX12 Ultimate, Metal 3 | Mesh shaders, RT, variable rate shading |
| Position | Min HW | Min Mobile | Min SW | Notes |
|---|---|---|---|---|
| D1 (Full GPU Scene) | HW4 | MW4 | SW3 | Requires advanced GPU-driven features |
| D2 (Retained + CPU Transform) | HW1 | MW1 | SW0 | Standard retained mode, universal |
| D3 (Retained + Dynamic Mat) | HW1 | MW1 | SW0 | Same as D2, just more uniform updates |
| D4 (GPU + CPU Feedback) | HW2 | MW2 | SW2 | Needs query/readback support |
| D5 (Mixed Static/Dynamic) | HW1 | MW1 | SW1 | Flexible, works broadly |
| D6 (CPU-Driven, Retained Buf) | HW1 | MW1 | SW0 | Traditional approach, universal |
| D7 (Streaming) | HW1 | MW1 | SW1 | Needs async loading capability |
| D8 (Per-Frame GPU Gen) | HW2 | MW2 | SW2 | Needs compute shaders |
| D9 (Per-Frame CPU Rebuild) | HW0 | MW0 | SW0 | Just needs basic drawing |
| D10 (CPU Software) | HW0 | MW0 | N/A | No GPU required |
| Technique | Min HW | Min Mobile | Min SW | Compute | Mesh Shaders | RT | Notes |
|---|---|---|---|---|---|---|---|
| G1: Billboards | HW0 | MW0 | SW0 | No | No | No | Universal, textured quads |
| G2: SDFs (analytical) | HW1 | MW1 | SW0 | No | No | No | Just needs fragment shaders |
| G2: SDFs (baked 3D tex) | HW1 | MW1 | SW1 | No | No | No | Needs 3D texture support |
| G3: Polygon Meshes | HW0 | MW0 | SW0 | No | No | No | Universal baseline |
| G4: Voxels (CPU mesh) | HW0 | MW0 | SW0 | No | No | No | Generate mesh on CPU |
| G4: Voxels (GPU raycst) | HW1 | MW1 | SW0 | No | No | No | Fragment shader raycast |
| G4: Voxels (compute) | HW2 | MW2 | SW2 | Yes | No | No | GPU mesh generation |
| G5: Gaussian Splats | HW3 | MW3 | SW2 | Yes | No | No | Sorting, compute required |
| G6: Nanite-style | HW4 | N/A | SW3 | Yes | Opt | No | Software raster, clusters |
| G7: Mesh Compression | HW0 | MW0 | SW0 | No | No | No | CPU decode, standard draw |
| G8: Implicit Noise | HW1 | MW1 | SW0 | No | No | No | Fragment shader evaluation |
| G9: Subdivision | HW2 | MW2 | SW2 | No | No | No | Needs tessellation shaders |
| G9: Subdivision (CPU) | HW0 | MW0 | SW0 | No | No | No | Pre-subdivide on CPU |
| G10: Displacement | HW2 | MW2 | SW2 | No | No | No | Needs tessellation |
| G10: Displacement (vtx) | HW1 | MW1 | SW1 | No | No | No | Vertex texture fetch |
| G11: CSG (mesh) | HW0 | MW0 | SW0 | No | No | No | CPU boolean operations |
| G11: CSG (SDF) | HW1 | MW1 | SW0 | No | No | No | min/max in shader |
| G12: NURBS/Curves | HW0 | MW0 | SW0 | No | No | No | CPU tessellation |
| G12: NURBS (GPU) | HW2 | MW2 | SW2 | No | No | No | GPU tessellation |
| G13: Height Maps | HW0 | MW0 | SW0 | No | No | No | Standard vertex displacement |
| G14: Sprite Stacking | HW0 | MW0 | SW0 | No | No | No | Just 2D sprites |
| G15: Style Transfer | HW3 | MW3 | SW2 | Yes | No | No | Neural network inference |
| G16: Geometry Images | HW1 | MW1 | SW1 | No | No | No | Texture as geometry |
| Technique | Min HW | Min Mobile | Min SW | Compute | Notes |
|---|---|---|---|---|---|
| P1: Proc Buildings (CPU) | HW0 | MW0 | SW0 | No | Generate mesh on CPU |
| P1: Proc Buildings (GPU) | HW2 | MW2 | SW2 | Yes | Compute shader generation |
| P2: Proc Terrain (CPU) | HW0 | MW0 | SW0 | No | Classic approach |
| P2: Proc Terrain (GPU) | HW2 | MW2 | SW2 | Yes | Erosion simulation etc |
| P3: Proc Vegetation | HW0 | MW0 | SW0 | No | L-system on CPU |
| P4: Proc Textures | HW1 | MW1 | SW0 | No | Fragment shader noise |
| P5: Wang Tiles | HW0 | MW0 | SW0 | No | Just texture sampling |
| P6: Compute Gen | HW2 | MW2 | SW2 | Yes | Core requirement |
| P7: Grammar-Based | HW0 | MW0 | SW0 | No | CPU-side parsing |
| P8: Fractals (2D) | HW0 | MW0 | SW0 | No | Fragment shader |
| P8: Fractals (3D SDF) | HW1 | MW1 | SW0 | No | Ray marching |
| Technique | Min HW | Min Mobile | Min SW | Compute | Notes |
|---|---|---|---|---|---|
| T1: BC1-BC5/DXT | HW0 | N/A | SW0 | No | Desktop standard |
| T1: ETC1 | N/A | MW0 | SW0 | No | Android baseline |
| T1: ETC2 | N/A | MW1 | SW1 | No | ES 3.0 required |
| T1: ASTC | HW3 | MW2 | SW2 | No | Modern mobile standard |
| T1: BC6H/BC7 | HW2 | N/A | SW1 | No | DX11+ HDR/quality |
| T2: Basis Universal | HW0 | MW0 | SW0 | No | Transcodes to platform format |
| T3: Atlasing | HW0 | MW0 | SW0 | No | Universal |
| T4: Virtual Texturing | HW2 | MW2 | SW2 | Opt | Page table management |
| T5: Tex Synthesis | HW1 | MW1 | SW1 | No | Fragment shader |
| T6: Procedural Tex | HW1 | MW1 | SW0 | No | Pure shader |
| T7: Triplanar | HW0 | MW0 | SW0 | No | 3x texture sample |
| T8: Palette-Based | HW0 | MW0 | SW0 | No | Texture indirection |
| T9: Polynomial | HW1 | MW1 | SW0 | No | Shader math |
| T10: Fourier/DCT | HW1 | MW1 | SW0 | No | Shader reconstruction |
| T11: Neural Compress | HW3 | MW3 | SW2 | Yes | Network inference |
| T12: Detail Textures | HW0 | MW0 | SW0 | No | Multi-texture blend |
| T14: Material ID | HW0 | MW0 | SW0 | No | Texture lookup |
| Technique | Min HW | Min Mobile | Min SW | Compute | RT | Notes |
|---|---|---|---|---|---|---|
| R1: Forward | HW0 | MW0 | SW0 | No | No | Universal baseline |
| R2: Ray Marching | HW1 | MW1 | SW0 | No | No | Fragment shader loops |
| R3: Voxel Raycast | HW1 | MW1 | SW0 | No | No | Fragment shader |
| R4: Particles (CPU) | HW0 | MW0 | SW0 | No | No | Upload each frame |
| R4: Particles (GPU) | HW2 | MW2 | SW2 | Yes | No | Compute update |
| R5: Deferred | HW1 | MW1 | SW1 | No | No | MRT support needed |
| R5: Deferred (mobile) | HW2 | MW2 | SW1 | No | No | Bandwidth concerns |
| R6: Forward+ | HW2 | MW2 | SW2 | Yes | No | Compute light culling |
| R7: Hybrid RT | HW4 | N/A | SW4 | Yes | Yes | RT cores/software |
| R8: Software Raster | HW2 | MW2 | SW2 | Yes | No | Compute shader |
| R9: PRT/Lightmaps | HW0 | MW0 | SW0 | No | No | Just textures |
| Technique | Min HW | Min Mobile | Min SW | Notes |
|---|---|---|---|---|
| C1: Delta Encoding | HW0 | MW0 | SW0 | CPU decode |
| C2: Quantization | HW0 | MW0 | SW0 | Universal |
| C3: Octree | HW0 | MW0 | SW0 | CPU traversal |
| C3: Octree (GPU) | HW2 | MW2 | SW2 | Compute traversal |
| C4: Run-Length | HW0 | MW0 | SW0 | CPU decode |
| C5: LZ-family | HW0 | MW0 | SW0 | CPU decode |
| C6: Entropy Coding | HW0 | MW0 | SW0 | CPU decode |
| C7: Sparse Voxel DAG | HW2 | MW2 | SW2 | GPU traversal preferred |
| C8: PCA/SVD | HW0 | MW0 | SW0 | CPU or shader reconstruct |
| Technique | Min HW | Min Mobile | Min SW | Compute | Notes |
|---|---|---|---|---|---|
| L1: Discrete LOD | HW0 | MW0 | SW0 | No | Universal |
| L2: Continuous LOD | HW1 | MW1 | SW1 | No | Vertex shader |
| L2: CDLOD/Geoclipmaps | HW1 | MW1 | SW1 | No | Terrain specific |
| L3: HLOD | HW0 | MW0 | SW0 | No | Pre-merged meshes |
| L4: Impostor LOD | HW0 | MW0 | SW0 | No | Billboard fallback |
| L5: Streaming | HW0 | MW0 | SW0 | No | Async loading |
| Technique | Min HW | Min Mobile | Min SW | Compute | Notes |
|---|---|---|---|---|---|
| A1: Keyframe | HW0 | MW0 | SW0 | No | Universal |
| A2: Skeletal (CPU) | HW0 | MW0 | SW0 | No | CPU skinning |
| A2: Skeletal (GPU) | HW1 | MW1 | SW1 | No | Vertex shader skinning |
| A3: Anim Compression | HW0 | MW0 | SW0 | No | CPU decode |
| A4: Procedural Anim | HW0 | MW0 | SW0 | No | CPU or shader |
| A5: VAT | HW1 | MW1 | SW1 | No | Vertex texture fetch |
| A6: Morph Targets | HW0 | MW0 | SW0 | No | Blend on CPU or GPU |
| A7: Bone Baking | HW0 | MW0 | SW0 | No | Pre-process |
| A8: Flipbook | HW0 | MW0 | SW0 | No | UV animation |
| Technique | Min HW | Min Mobile | Min SW | Compute | Notes |
|---|---|---|---|---|---|
| M1: Flat/Unlit | HW0 | MW0 | SW0 | No | Universal |
| M2: Lambert/Phong | HW0 | MW0 | SW0 | No | Universal |
| M3: PBR | HW1 | MW1 | SW1 | No | IBL needs cubemaps |
| M4: Lightmaps | HW0 | MW0 | SW0 | No | Just textures |
| M5: Spherical Harm | HW0 | MW0 | SW0 | No | Shader eval |
| M6: Light Probes | HW0 | MW0 | SW0 | No | Sample and apply |
| M7: Toon Shading | HW0 | MW0 | SW0 | No | Simple shader |
| M8: Matcaps | HW0 | MW0 | SW0 | No | View-space UV |
| Technique | Min HW | Min Mobile | Min SW | Compute | Notes |
|---|---|---|---|---|---|
| S1: Domain Repetition | HW1 | MW1 | SW0 | No | Shader fract/mod |
| S2: Shader Deform | HW0 | MW0 | SW0 | No | Vertex shader |
| S3: Parallax Mapping | HW1 | MW1 | SW0 | No | Fragment shader loops |
| S4: Screen-Space FX | HW1 | MW1 | SW1 | No | Post-process |
| S5: SDF Blending | HW1 | MW1 | SW0 | No | Shader math |
| S6: Raymarching Opt | HW1 | MW1 | SW0 | No | Better algorithms |
| IM1: Raymarch SDF | HW1 | MW1 | SW0 | No | Full-screen quad |
| IM2: Compute→Render | HW2 | MW2 | SW2 | Yes | Compute required |
| IM3: Uniform-Driven | HW1 | MW1 | SW1 | No | Instancing helps |
| IM6: Fullscreen+Math | HW1 | MW1 | SW0 | No | Pure fragment |
| IM7: Instanced Proc | HW1 | MW1 | SW1 | No | Instancing required |
| Technique | Min HW | Min Mobile | Min SW | Notes |
|---|---|---|---|---|
| DEB1: Pixel Trace | HW2 | MW2 | SW2 | Compute or debug shader |
| DEB2: Hot Reload | HW0 | MW0 | SW0 | Runtime shader compile |
| DEB3: Debug HUDs | HW0 | MW0 | SW0 | UI overlay |
| DEB4: Value→Color | HW0 | MW0 | SW0 | Shader modification |
| DEB5: Time Travel | HW0 | MW0 | SW0 | State recording |
| DEB6: Diff Rendering | HW1 | MW1 | SW1 | Dual render targets |
| DEB7: Shader Profiling | HW2 | MW2 | SW2 | Vendor-specific tools |
| Feature | GL | GL ES | DX | Vulkan | Metal | Notes |
|---|---|---|---|---|---|---|
| Basic shaders | 2.0 | 2.0 | 9 | 1.0 | 1.0 | GLSL 1.10+ |
| Instancing | 3.1 | 3.0 | 10 | 1.0 | 1.0 | Draw call reduction |
| MRT (deferred) | 2.0 | 3.0 | 9 | 1.0 | 1.0 | Multiple render targets |
| 3D Textures | 1.2 | 3.0 | 10 | 1.0 | 1.0 | Volume data |
| Texture arrays | 3.0 | 3.0 | 10 | 1.0 | 1.0 | Atlasing alternative |
| Floating point tex | 3.0 | 3.0 | 10 | 1.0 | 1.0 | HDR, data textures |
| Integer textures | 3.0 | 3.0 | 10 | 1.0 | 1.0 | ID buffers |
| Geometry shaders | 3.2 | 3.2* | 10 | 1.0 | N/A | *ES extension |
| Tessellation | 4.0 | 3.2* | 11 | 1.0 | 1.0 | *ES extension |
| Compute shaders | 4.3 | 3.1 | 11 | 1.0 | 1.0 | GPGPU |
| SSBO | 4.3 | 3.1 | 11 | 1.0 | 1.0 | Large buffers |
| Indirect draw | 4.0 | 3.1 | 11 | 1.0 | 1.0 | GPU-driven |
| Bindless textures | 4.4* | N/A | N/A | 1.0* | N/A | *Extension |
| Mesh shaders | N/A | N/A | 12U | 1.2* | 3.0 | *Extension |
| Ray tracing | N/A | N/A | 12U | 1.2* | 3.0 | *Extension |
| Variable rate shading | N/A | N/A | 12U | 1.2* | 2.0 | *Extension |
| Concern | Impact | Techniques Affected |
|---|---|---|
| Bandwidth | Deferred rendering expensive | R5, T4 |
| Fill rate | Complex fragment shaders hurt | R2, P4, IM1 |
| Thermal | Sustained compute throttles | All compute-heavy |
| Memory | Limited VRAM | T4, G6, large textures |
| Precision | mediump/lowp required | P4, T6 (precision issues) |
| Tile-based | Different perf characteristics | R5 (can help), MRT |
| No geometry shaders | Many devices lack support | G9 (hardware tess) |
These techniques work on virtually any GPU from the last 20 years:
Geometry:
Textures:
Rendering:
Animation:
Lighting:
LOD:
These require compute shaders and are the current mainstream:
Geometry:
Procedural:
Textures:
Rendering:
Compression:
These require latest hardware:
Geometry:
Rendering:
Features used:
WebGL has specific limitations that affect technique viability:
| WebGL Version | Equivalent | Key Limitations |
|---|---|---|
| WebGL 1.0 | ES 2.0 | No 3D textures, no instancing*, no MRT*, limited precision |
| WebGL 2.0 | ES 3.0 | No compute shaders, no geometry shaders, no tessellation |
| WebGPU | Vulkan-like | Compute shaders, modern features, still emerging |
*Extensions may provide some features
WebGL 1.0 Compatible Techniques:
WebGL 2.0 Additional:
Requires WebGPU:
VR adds additional constraints:
| Requirement | Impact | Affected Techniques |
|---|---|---|
| 90+ FPS | Halves frame budget | All compute-heavy techniques |
| Stereo rendering | 2x geometry | G6 helps, G2/R2 hurt (2x rays) |
| Low latency | No heavy post-process | S4 (limited), R7 |
| Reprojection | Needs depth | R2 must output depth |
| Foveated rendering | Helps perf | Works with most techniques |
| Single-pass stereo | Needs instancing | Requires SW1+ |
VR-Friendly:
VR-Challenging:
| Project Type | Target HW | Target Mobile | Target SW | Key Techniques |
|---|---|---|---|---|
| Demoscene 4KB | HW1 | N/A | SW0 | G2, R2, P4, T6, IM1 |
| Indie (wide reach) | HW1 | MW1 | SW1 | G3, R1, T1, A2, L1 |
| Indie (stylized) | HW1 | MW1 | SW1 | G1, M7, ART* |
| Mobile game | HW2 | MW2 | SW1 | G3, R1, T1 (ASTC), M4 |
| PC mid-range | HW2 | N/A | SW2 | P6, R6, T4 |
| PC high-end | HW3 | N/A | SW3 | G6, R7, T11 |
| VR (standalone) | HW3 | MW3 | SW2 | G3, R1, M4, L1-4 |
| VR (PC) | HW4 | N/A | SW3 | G6, R1, L1 |
| Web (broad) | HW1 | MW1 | WebGL2 | G3, R1, P4, A2 |
| Web (modern) | HW3 | MW3 | WebGPU | P6, R2, more |
The website should allow filtering by:
Hardware:
Platform:
API:
Required Features:
Spectrum Position:
When user selects constraints, techniques that don't meet requirements are grayed out or hidden, and the compatibility matrix updates to show only viable combinations.
This section addresses the temporal dimension of when computation happens and how mutable/interactive the results can be.
INTERACTIVITY
│
Static ◄─────────┼─────────► Fully Interactive
(view only) │ (modify anything)
│
─────────────────────────┼─────────────────────────────
│
Offline ◄───────────┼───────────► Online
(precompute) COMPUTATION (realtime)
TIMINGComputation Timing (Offline ↔ Online):
Interactivity (Static ↔ Interactive):
Key insight: Online enables interactive, but doesn't guarantee it. You can compute something every frame that the user can't meaningfully change.
| Tier | Name | When | Latency | Examples |
|---|---|---|---|---|
| CT0 | Build-time | Asset pipeline | Minutes-hours | Lightmaps, LOD generation, mesh compression |
| CT1 | Load-time | Game startup/level load | Seconds | Shader compilation, texture transcoding |
| CT2 | Streaming | Background during play | 100ms-seconds | Terrain chunks, texture streaming |
| CT3 | Per-frame | Every frame | 16ms budget | Standard rendering, animation |
| CT4 | Per-pixel/vertex | Shader execution | Microseconds | Procedural textures, SDF evaluation |
| CT5 | Per-interaction | On user input | <100ms for feel | Physics response, terrain deformation |
| Level | Name | Description | Examples |
|---|---|---|---|
| I0 | Fully Static | Cannot change at all | Pre-rendered video, baked lightmaps |
| I1 | View Interactive | Camera/viewpoint changes only | Architectural walkthrough, photo viewer |
| I2 | Parameter Interactive | Tweak predefined parameters | Color grading, time-of-day slider |
| I3 | Object Interactive | Move/modify discrete objects | Standard game objects, physics |
| I4 | Content Interactive | Add/remove/reshape content | Voxel editing, terrain sculpting |
| I5 | Fully Generative | Create anything in real-time | Live coding, Dreams PS4 sculpting |
More Precomputation ───────────────────────► Less Precomputation
┌─────────────────────────────────────────────────────────┐
│ OFFLINE │ ONLINE │
│ │ │
│ • Higher quality possible │ • Lower quality │
│ • More computation time │ • Strict time budget │
│ • Results are static │ • Results can change │
│ • Storage cost for results │ • Compute cost │
│ • Iteration requires rebake │ • Instant iteration │
│ • Works on weak runtime HW │ • Needs strong HW │
└─────────────────────────────────────────────────────────┘The fundamental trade-off:
Description: Pre-generate filtered lower-resolution versions of textures.
Computation Timing: CT0 (build-time) or CT1 (load-time) Interactivity Impact: None - transparent optimization Storage Cost: +33% texture size Runtime Benefit: Proper filtering, reduced bandwidth, fewer artifacts
What it enables:
Without it: Runtime would need to filter on-the-fly (expensive) or accept aliasing.
Works with: All texture-based techniques Engine support: Universal, automatic
Description: Pre-compute global illumination, shadows, ambient occlusion into textures.
Computation Timing: CT0 (build-time), minutes to hours Interactivity Impact: I0-I1 (lighting is static, can only move camera/dynamic objects) Storage Cost: Significant (often largest asset) Runtime Benefit: Complex GI "for free" at runtime
What it enables:
Without it: Need runtime GI (expensive) or accept flat lighting.
Variants:
Limitations:
Works with: M4, R9, any static environment Does not work with: Fully dynamic scenes, destructible geometry
Description: Pre-generate simplified mesh versions for distance rendering.
Computation Timing: CT0 (build-time) Interactivity Impact: None - transparent optimization Storage Cost: ~50-100% additional mesh data Runtime Benefit: Massive triangle reduction at distance
Approaches:
What it enables:
Works with: L1, L3, L4, standard mesh workflows Does not work with: Fully procedural geometry (must regenerate or cache)
Description: Pre-compile shader variants for all material/feature combinations.
Computation Timing: CT0 (build-time) or CT1 (load-time) Interactivity Impact: None - transparent Storage Cost: Can be huge (permutation explosion) Runtime Benefit: No shader compilation stalls
Problem it solves: Runtime shader compilation causes frame hitches.
Approaches:
Challenges:
Description: Pre-compute walkable surface representation for AI pathfinding.
Computation Timing: CT0 (build-time) Interactivity Impact: I0-I3 (navmesh is static, but objects can move on it) Storage Cost: Small-moderate Runtime Benefit: Fast pathfinding
What it enables:
Dynamic alternatives:
Description: Pre-generate simplified collision geometry from render mesh.
Computation Timing: CT0 (build-time) Interactivity Impact: Physics is interactive (I3), but collision shape is static Storage Cost: Small Runtime Benefit: Fast collision detection
Approaches:
Description: Pre-compute per-vertex or texture-space ambient occlusion.
Computation Timing: CT0 (build-time) Interactivity Impact: I0-I1 (AO is static) Storage Cost: Per-vertex: small. Texture: moderate Runtime Benefit: High-quality AO without SSAO cost
Variants:
Runtime alternative: SSAO, GTAO, HBAO (CT3)
Description: Pre-compute signed distance field in 3D texture from mesh.
Computation Timing: CT0 (build-time), can be slow Interactivity Impact: I0-I1 (SDF is static, but enables dynamic queries) Storage Cost: Moderate-high (3D texture) Runtime Benefit: Fast distance queries, soft shadows, AO
What it enables:
Tools:
Works with: G2 (as alternative to analytical SDF), H5 (hybrid)
Description: Pre-compute which areas can see which other areas.
Computation Timing: CT0 (build-time), can be hours Interactivity Impact: I0-I1 (visibility is static) Storage Cost: Moderate Runtime Benefit: Instant occlusion culling
What it enables:
Classic approach: Potentially Visible Sets (Quake-era) Modern: GPU occlusion queries, hierarchical Z-buffer (online)
Works with: Indoor environments, levels with walls Does not work with: Open worlds, destructible environments
Description: Pre-compress textures to GPU-friendly formats.
Computation Timing: CT0 (build-time) Interactivity Impact: None - transparent Storage Cost: Reduced (that's the point) Runtime Benefit: Lower memory, faster sampling
Formats: BC1-7, ASTC, ETC1/2 (see T1)
Why offline: Quality compression (BC7, ASTC) is slow. Runtime transcoding (Basis) is faster but still CT1.
Description: Pre-compress animation curves, removing redundancy.
Computation Timing: CT0 (build-time) Interactivity Impact: None - animation plays back identically Storage Cost: Reduced Runtime Benefit: Lower memory, potentially faster playback
Techniques:
Description: Pre-render 3D object from multiple angles to use as billboard.
Computation Timing: CT0 (build-time) Interactivity Impact: I0-I1 (impostor is static representation) Storage Cost: Texture atlas per object Runtime Benefit: Render complex objects as single quad
Variants:
What it enables:
Works with: L4, G1
Description: Pre-filter environment maps for different roughness levels.
Computation Timing: CT0 or CT1 Interactivity Impact: I0-I1 (environment is static) Storage Cost: Moderate (mip chain of cubemaps) Runtime Benefit: PBR specular IBL at single texture sample
What it enables:
Without it: Would need importance sampling at runtime (expensive).
Related: Pre-integrated BRDF LUT
Description: Pre-reorder vertices and indices for GPU cache efficiency.
Computation Timing: CT0 (build-time) Interactivity Impact: None - transparent Storage Cost: None (same data, different order) Runtime Benefit: Better GPU cache utilization, faster rendering
Tools: meshoptimizer, AMD Tootle, Forsyth algorithm
Should always do this: Free performance, no downside.
Description: Pre-compute occlusion contribution of objects for culling hints.
Computation Timing: CT0 (build-time) Interactivity Impact: I0-I3 (objects can move, but their occlusion properties are static) Storage Cost: Small per object Runtime Benefit: Better culling decisions
Example: Mark objects as "large occluder" or "never occludes"
Description: Pre-simulate hydraulic/thermal erosion on heightmap terrain.
Computation Timing: CT0 (build-time), minutes Interactivity Impact: I0-I1 (terrain is static) Storage Cost: Just heightmap Runtime Benefit: Realistic terrain without runtime simulation
Can be online: GPU erosion simulation exists but expensive.
Works with: P2, G13
Description: Run procedural generation offline, store results.
Computation Timing: CT0 (build-time) or CT1 (load-time, seed-based) Interactivity Impact: I0-I2 (can't modify the generation, only parameters) Storage Cost: Full generated content Runtime Benefit: Use procedural algorithms that are too slow for real-time
Pattern:
Offline: Run expensive procedural algorithm
Store result as static asset
Online: Load and use as normal mesh/textureEnables: Complex generation algorithms (expensive erosion, multi-pass synthesis) Loses: Runtime variation, interactivity
Description: Pre-divide meshes into GPU-friendly clusters for culling.
Computation Timing: CT0 (build-time) Interactivity Impact: None - transparent Storage Cost: Additional index data Runtime Benefit: Enables per-cluster culling, mesh shaders
Required for: G6 (Nanite-style), mesh shader pipelines Tools: meshoptimizer, Nanite importer
Description: Pre-build bounding volume hierarchies for ray tracing or collision.
Computation Timing: CT0 (static) or CT3 (dynamic, for RT) Interactivity Impact: Varies - static BVH = I0, dynamic rebuild = I3+ Storage Cost: Moderate Runtime Benefit: Fast ray-geometry intersection
For ray tracing: Modern RT APIs build/update AS at runtime, but static geometry can pre-build.
Description: Pre-convert mesh to voxel representation.
Computation Timing: CT0 (build-time) Interactivity Impact: I0-I1 (voxels are static) Storage Cost: Depends on resolution Runtime Benefit: Enables voxel-based algorithms (GI, AO)
What it enables:
| Technique | Typical Timing | Can Be Precomputed? | Interactivity Level | Notes |
|---|---|---|---|---|
| G1: Billboards | CT3 | Yes (PRE12) | I1-I3 | Pre-bake for static, dynamic for characters |
| G2: SDFs (analytical) | CT4 | N/A (pure math) | I2-I5 | Inherently online, fully interactive |
| G2: SDFs (baked) | CT0 (PRE8) | Yes | I0-I1 | Trade interactivity for quality |
| G3: Meshes | CT0 | Yes (standard) | I0-I3 | Static meshes + dynamic transforms |
| G4: Voxels | CT0-CT3 | Partially | I0-I5 | Minecraft: online editable |
| G5: Gaussian Splats | CT0 | Yes (captured) | I0-I1 | Mostly for captured content |
| G6: Nanite | CT0 (PRE18) | Yes (required) | I1-I3 | Clustering must be offline |
| G7: Mesh Compression | CT0 | Yes (required) | N/A | Compression is inherently offline |
| G8: Implicit Noise | CT4 | Can cache (PRE17) | I2-I5 | Online by nature |
| G9: Subdivision | CT0 or CT3 | Yes (pre-subdivide) | I1-I3 | Runtime tess or pre-subdivide |
| G10: Displacement | CT0 or CT3 | Yes (bake to mesh) | I1-I3 | Similar to subdivision |
| G11: CSG | CT0 or CT4 | Yes (bake) or No (SDF) | I0-I5 | Baked mesh vs real-time SDF |
| G13: Height Maps | CT0 or CT3 | Usually yes | I0-I4 | Editable terrain possible |
| Technique | Typical Timing | Can Be Precomputed? | Interactivity Level | Notes |
|---|---|---|---|---|
| P1: Proc Buildings | CT0-CT2 | Yes, commonly | I0-I2 | Generate at build/load time |
| P2: Proc Terrain | CT0-CT3 | Yes, but loses variety | I0-I4 | Online enables infinite terrain |
| P3: Proc Vegetation | CT0-CT1 | Yes | I0-I2 | Generate on load |
| P4: Proc Textures | CT4 | Can bake (PRE17) | I2-I4 | Baking loses runtime variation |
| P5: Wang Tiles | CT0 | Yes | I0-I2 | Tiles themselves are precomputed |
| P6: Compute Gen | CT3 | Defeats purpose | I3-I5 | Point is runtime generation |
| P7: Grammar-Based | CT0-CT2 | Yes | I0-I2 | Usually generate on load |
| P8: Fractals | CT4 | Can bake | I2-I5 | Usually online for interaction |
| Technique | Typical Timing | Can Be Precomputed? | Interactivity Level | Notes |
|---|---|---|---|---|
| T1: GPU Compression | CT0 (PRE10) | Required | N/A | Must be offline |
| T2: Supercompression | CT0 | Required | N/A | Offline compress, runtime transcode |
| T3: Atlasing | CT0 | Yes | N/A | Build-time packing |
| T4: Virtual Texturing | CT0+CT2 | Tiles precomputed | I1 | Streaming is online, content is static |
| T5: Tex Synthesis | CT0 or CT3 | Can pre-synthesize | I0-I3 | Offline: quality. Online: variation |
| T6: Procedural Tex | CT4 | Can bake (PRE17) | I2-I5 | Bake for mobile, online for PC |
| T7: Triplanar | CT4 | No (it's a mapping) | I1-I3 | Online projection |
| T8: Palette-Based | CT0 | Yes | I2-I3 | Palette can change at runtime |
| T9-T10: Polynomial/DCT | CT0 | Yes (encode offline) | I0-I2 | Encoding is offline |
| T11: Neural | CT0 | Required (training) | I0-I1 | Training is very offline |
| T12: Detail Textures | CT0 | Yes | I1 | Standard textures |
| Technique | Typical Timing | Can Be Precomputed? | Interactivity Level | Notes |
|---|---|---|---|---|
| R1: Forward | CT3 | No | I3 | Online rendering |
| R2: Ray Marching | CT3-CT4 | Not typically | I3-I5 | Online, enables interactivity |
| R5: Deferred | CT3 | No | I3 | Online rendering |
| R7: Ray Tracing | CT3 | AS can be static | I3-I5 | Mix of precomputed AS + online tracing |
| R9: PRT/Lightmaps | CT0 (PRE2) | Required | I0-I1 | Precomputation is the point |
| Technique | Typical Timing | Can Be Precomputed? | Interactivity Level | Notes |
|---|---|---|---|---|
| M1-M3: Direct Lighting | CT3-CT4 | No | I3 | Online by nature |
| M4: Lightmaps | CT0 (PRE2) | Required | I0-I1 | Static lighting |
| M5: SH Probes | CT0 or CT3 | Usually yes | I0-I2 | Bake probes, sample at runtime |
| M6: Light Probes | CT0 | Usually yes | I0-I2 | Same as SH |
| M7-M8: Toon/Matcap | CT3-CT4 | No | I3 | Simple online shading |
| Technique | Typical Timing | Can Be Precomputed? | Interactivity Level | Notes |
|---|---|---|---|---|
| A1: Keyframe | CT0+CT3 | Data is precomputed | I0-I3 | Data offline, playback online |
| A2: Skeletal | CT0+CT3 | Rig offline, skinning online | I0-I3 | Mix |
| A4: Procedural | CT3 | Defeats purpose | I3-I5 | Online is the point |
| A5: VAT | CT0 | Required | I0-I2 | Bake simulation to texture |
Demoscene has a unique relationship with precomputation because executable size is limited:
What demoscene precomputes (at build time):
What demoscene computes at runtime:
The demoscene philosophy: Precomputation requires storage. Extreme size limits push everything online. The "compression" is the algorithm itself.
Research insight: Demoscene techniques prove what's achievable with zero precomputation, establishing the lower bound of quality at any given runtime budget.
| Project Type | Precomputation Budget | Online Budget | Strategy |
|---|---|---|---|
| Mobile game | High | Low | Bake everything possible (lightmaps, LODs, compressed textures) |
| PC indie | Moderate | Moderate | Balance: bake lighting, runtime procedural details |
| AAA | Very high | High | Massive baking + runtime enhancements |
| VR | High | Very low | Extreme precomputation due to 90fps requirement |
| Demoscene | None | All | Everything runtime procedural |
| Arch viz | Very high | Low | Pre-render quality, runtime just navigation |
| Procedural game | Low | High | Minimal precompute to enable runtime generation |
| Live performance | None | All | Everything must be real-time interactive |
Add these filters to the interactive website:
Computation Timing:
Interactivity Required:
Precomputation Constraints:
Some precomputation can offload runtime requirements:
| If you precompute... | You can reduce runtime to... | HW savings |
|---|---|---|
| Lightmaps (PRE2) | Texture sample | HW2 → HW0 |
| LODs (PRE3) | LOD selection | N/A (always needed) |
| SDFs (PRE8) | 3D texture sample | HW2 → HW1 |
| Impostors (PRE12) | Billboard render | HW3 → HW0 |
| Procedural content (PRE17) | Static mesh | HW2 → HW0 |
| Erosion (PRE16) | Heightmap sample | HW2 → HW0 |
Pattern: Heavy precomputation can enable running on weaker hardware by trading storage for compute.
| Spectrum Position | Precomputation Role | Notes |
|---|---|---|
| D1-D2 (Retained) | Heavy precomputation expected | Data loaded once, used many times |
| D3-D4 (Mixed) | Moderate precomputation | Static data + dynamic updates |
| D5-D6 (Flexible) | Optional precomputation | Can go either way |
| D7-D8 (Streaming/Generating) | Minimal precomputation | Data computed on demand |
| D9-D10 (Immediate) | No precomputation | Everything computed per-frame |
Description: Replace 3D geometry with camera-facing 2D planes textured with pre-rendered or stylized images.
Variants:
Works well with:
Does not work well with:
Description: Represent geometry as mathematical functions returning distance to nearest surface. Rendered via ray marching.
Variants:
Works well with:
Does not work well with:
Engine Compatibility:
Spectrum Position: D8-D10 (inherently immediate mode)
Description: Standard triangle/quad meshes. Included for compatibility reference.
Works well with:
Does not work well with:
Description: Represent geometry as 3D grids of filled/empty cells, optionally with material data.
Variants:
Works well with:
Does not work well with:
Description: Represent surfaces as collections of points, rendered as small discs or gaussians.
Variants:
Works well with:
Does not work well with:
Description: Stream and render massive meshes by breaking into clusters, culling aggressively, and using software rasterization for small triangles.
Works well with:
Does not work well with:
Engine Compatibility:
Spectrum Position: D1 (maximally retained, GPU-driven)
Description: Compress traditional meshes using specialized algorithms.
Variants:
Works well with:
Does not work well with:
Description: Define surfaces as isosurfaces of noise functions (e.g., Perlin, Simplex, Worley).
Works well with:
Does not work well with:
Description: Store coarse control cage, subdivide at runtime to desired detail.
Works well with:
Does not work well with:
Description: Use simple base geometry + displacement maps for detail.
Works well with:
Does not work well with:
Description: Build complex shapes from boolean operations on primitives.
Works well with:
Does not work well with:
Description: Define surfaces mathematically via control points and basis functions.
Works well with:
Does not work well with:
Description: Represent terrain as 2D grid of heights.
Works well with:
Does not work well with:
Description: Stack 2D sprite layers to create pseudo-3D effect (popular in indie games).
Works well with:
Does not work well with:
Description: Render simple geometry, apply neural style transfer to add apparent detail/dimension.
Works well with:
Does not work well with:
Description: Encode mesh geometry as 2D images (positions, normals as RGB). GPU-friendly compression.
Works well with:
Does not work well with:
Description: Represent solid volumes with tetrahedra for simulation/deformation.
Works well with:
Does not work well with:
Description: Generate architectural geometry from rules, grammars, or parameters.
Variants:
Works well with:
Does not work well with:
Description: Generate terrain from noise functions, erosion simulation, etc.
Variants:
Works well with:
Does not work well with:
Description: Generate trees, plants from L-systems or space colonization algorithms.
Works well with:
Does not work well with:
Description: Generate textures entirely in shaders from noise and math.
Works well with:
Does not work well with:
Description: Small set of tiles that can be combined infinitely without visible repetition.
Works well with:
Does not work well with:
Description: Generate mesh data directly in compute shaders, output to vertex buffers.
Variants:
Works well with:
Does not work well with:
Engine Compatibility:
Spectrum Position: D8 (per-frame GPU generation)
Description: Use formal grammars (L-systems, graph grammars) to generate content.
Works well with:
Does not work well with:
Description: Self-similar mathematical structures (Mandelbrot, Menger sponge, etc.)
Works well with:
Does not work well with:
Description: Hardware-accelerated block compression, typically 4:1 to 8:1 ratio.
Variants:
Works well with:
Does not work well with:
Description: Compress textures to universal intermediate, transcode to platform-specific format.
Works well with:
Does not work well with:
Description: Pack multiple textures into single larger texture.
Works well with:
Does not work well with:
Description: Stream texture tiles on demand, potentially unique texturing for entire world.
Works well with:
Does not work well with:
Description: Generate large textures from small exemplars.
Variants:
Works well with:
Does not work well with:
Description: Compute texture entirely mathematically (no stored data).
Variants:
Works well with:
Does not work well with:
Engine Compatibility:
Spectrum Position: D8-D9 (computed per-frame, no stored texture data)
Description: Project textures from three axes, blend based on normal. No UV unwrapping needed.
Works well with:
Does not work well with:
Description: Store texture as indices into small color palette.
Variants:
Works well with:
Does not work well with:
Description: Represent textures as polynomial coefficients, reconstruct in shader.
Works well with:
Does not work well with:
Description: Store texture as frequency domain coefficients (like JPEG internally).
Works well with:
Does not work well with:
Description: Use neural networks to encode/decode textures.
Variants:
Works well with:
Does not work well with:
Description: Tile small detail texture over base, blending at distance.
Works well with:
Does not work well with:
Description: Special encoding for normal maps (2 channels, reconstruct Z).
Variants:
Works well with:
Does not work well with:
Description: Single channel texture indexes into material database.
Works well with:
Does not work well with:
Description: Use system emoji/glyphs as instant free textures.
Works well with:
Does not work well with:
Description: Project textures onto surfaces dynamically.
Works well with:
Does not work well with:
Description: Standard GPU triangle rendering.
Works well with:
Does not work well with:
Description: Step along rays, evaluate SDF or volume at each step.
Works well with:
Does not work well with:
Engine Compatibility:
Integration notes: All engines expect rasterized depth buffers. Integrating ray-marched content with engine-rendered content (for shadows, reflections, etc.) requires extra work to output compatible depth.
Spectrum Position: D8-D10 (inherently immediate, stateless per-pixel)
Description: Cast rays through voxel grids.
Works well with:
Does not work well with:
Description: Render many small elements (points, quads).
Works well with:
Does not work well with:
Description: Separate geometry pass from lighting pass.
Works well with:
Does not work well with:
Description: Forward rendering with light culling.
Works well with:
Does not work well with:
Description: Use RT for specific effects (reflections, shadows, GI).
Works well with:
Does not work well with:
Description: CPU or compute shader triangle rasterization (Nanite-style for small triangles).
Works well with:
Does not work well with:
Description: Bake complex lighting into per-vertex or texture data.
Works well with:
Does not work well with:
Description: Store differences from previous frame/value.
Works well with:
Does not work well with:
Description: Reduce precision (e.g., 32-bit to 16-bit, 8-bit).
Variants:
Works well with:
Does not work well with:
Description: Organize spatial data hierarchically for compression and queries.
Works well with:
Does not work well with:
Description: Encode runs of repeated values.
Works well with:
Does not work well with:
Description: General-purpose compression (gzip, zstd, lz4).
Works well with:
Does not work well with:
Description: Optimal bit-level encoding based on symbol frequency.
Works well with:
Does not work well with:
Description: Convert octrees to DAGs by merging identical subtrees.
Works well with:
Does not work well with:
Description: Decompose data into basis components, keep most important.
Works well with:
Does not work well with:
Description: Multiple pre-authored detail levels, switch based on distance.
Works well with:
Does not work well with:
Description: Smoothly vary detail based on screen coverage.
Variants:
Works well with:
Does not work well with:
Description: Group distant objects into single merged mesh.
Works well with:
Does not work well with:
Description: Replace distant geometry with billboards.
Works well with:
Does not work well with:
Description: Load assets on-demand based on player position.
Works well with:
Does not work well with:
Description: Use modulo/fract to repeat SDF or geometry infinitely.
Works well with:
Does not work well with:
Description: Modify vertex positions in vertex shader.
Works well with:
Does not work well with:
Description: Fake depth on flat surfaces via ray marching in texture space.
Works well with:
Does not work well with:
Description: Post-process effects working on rendered buffers.
Variants:
Works well with:
Does not work well with:
Description: Blend between SDF shapes smoothly using polynomial smooth-min.
Works well with:
Does not work well with:
Description: Techniques to speed up SDF ray marching.
Variants:
Works well with:
Does not work well with:
Description: Simpler shader for distant objects.
Works well with:
Does not work well with:
Description: Store key poses, interpolate between them.
Works well with:
Does not work well with:
Description: Animate bone hierarchy, skin mesh to bones.
Works well with:
Does not work well with:
Description: Compress animation curves.
Variants:
Works well with:
Does not work well with:
Description: Generate animation from code (physics, IK, etc.).
Variants:
Works well with:
Does not work well with:
Description: Bake animation into textures, sample in vertex shader.
Works well with:
Does not work well with:
Description: Blend between different mesh poses.
Works well with:
Does not work well with:
Description: Bake complex rig to simpler one.
Works well with:
Does not work well with:
Description: Frame-by-frame sprite animation.
Works well with:
Does not work well with:
Description: No lighting calculation, albedo only.
Works well with:
Does not work well with:
Description: Classic simple lighting.
Works well with:
Does not work well with:
Description: Energy-conserving lighting with roughness/metallic.
Works well with:
Does not work well with:
Description: Pre-baked lighting into textures.
Works well with:
Does not work well with:
Description: Encode lighting as low-frequency spherical function.
Works well with:
Does not work well with:
Description: Sample lighting at points in space.
Works well with:
Does not work well with:
Description: Quantized shading for cartoon look.
Works well with:
Does not work well with:
Description: 2D texture encodes entire material response.
Works well with:
Does not work well with:
Description: Share materials across many objects.
Works well with:
Does not work well with:
Description: Generate sounds from synthesis (no samples).
Works well with:
Does not work well with:
Description: Small samples + pattern data.
Works well with:
Does not work well with:
Description: Note data + shared instrument samples.
Works well with:
Does not work well with:
Description: Build sounds from tiny grains of sampled audio.
Works well with:
Does not work well with:
Description: Compress executables with runtime decompression (UPX, kkrunchy, crinkler).
Works well with:
Does not work well with:
Description: Remove whitespace, shorten names in shaders.
Works well with:
Does not work well with:
Description: Generate repetitive code rather than writing by hand.
Works well with:
Does not work well with:
Description: Write minimal custom code instead of using large engine.
Works well with:
Does not work well with:
Description: Behavior defined in data, interpreted by small runtime.
Works well with:
Does not work well with:
Description: SDFs containing other SDFs at different scales.
Works well with:
Does not work well with:
Description: ML-based scene representations.
Works well with:
Does not work well with:
Description: Modern GPU pipeline with flexible geometry processing.
Works well with:
Does not work well with:
Description: Shade into texture, reuse across frames.
Works well with:
Does not work well with:
Description: Use SDFs for some objects, meshes for others.
Works well with:
Does not work well with:
Description: Progressive mesh refinement over network.
Works well with:
Does not work well with:
Description: Store multiple depth samples per pixel for view synthesis.
Works well with:
Does not work well with:
Description: Entire game uses only cubes, spheres, etc.
Works well with:
Does not work well with:
Description: Entire game uses N colors (e.g., 4, 8, 16).
Works well with:
Does not work well with:
Description: Render at very low resolution, upscale with filters.
Works well with:
Does not work well with:
Description: Only render edges of geometry.
Works well with:
Does not work well with:
Description: Design all content for readability in silhouette.
Works well with:
Does not work well with:
When combining techniques:
Major paradigm splits:
This document is designed to eventually become an interactive website where users can: