Skip to content

Commit 23b1019

Browse files
committed
[update] roadmap documentation
1 parent 2e7a3ab commit 23b1019

File tree

1 file changed

+225
-0
lines changed

1 file changed

+225
-0
lines changed

docs/game_roadmap_and_prototype.md

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
---
2+
title: "Lambda RS: Gaps, Roadmap, and Prototype Plan"
3+
document_id: "game-roadmap-2025-09-24"
4+
status: "living"
5+
created: "2025-09-24T05:09:25Z"
6+
last_updated: "2025-09-26T19:37:55Z"
7+
version: "0.2.0"
8+
engine_workspace_version: "2023.1.30"
9+
wgpu_version: "26.0.1"
10+
shader_backend_default: "naga"
11+
winit_version: "0.29.10"
12+
repo_commit: "2e7a3abcf60a780fa6bf089ca8a6f4124e60f660"
13+
owners: ["lambda-sh"]
14+
reviewers: ["engine", "rendering"]
15+
tags: ["roadmap","games","2d","3d","desktop"]
16+
---
17+
18+
# Lambda RS: Gaps, Roadmap, and Prototype Plan
19+
20+
This document outlines current engine capabilities, the gaps to address for 2D/3D games and desktop apps, concrete API additions, and a step‑by‑step plan to deliver a playable 2D prototype first, followed by a small 3D scene. Code sketches follow Lambda’s existing builder/command style.
21+
22+
## Architecture Today
23+
24+
Key modules: windowing/events (winit), GPU (wgpu), render context, runtime loop, and GLSL→SPIR‑V shader compilation (naga).
25+
26+
Frame flow:
27+
```
28+
App Components --> ApplicationRuntime --> RenderContext --> wgpu (Device/Queue/Surface)
29+
| | | |
30+
| V V V
31+
| Events/Loop Pass/Pipeline Adapter/Swapchain
32+
V
33+
RenderCommand stream per frame
34+
```
35+
36+
Currently supported commands: Begin/EndRenderPass, SetPipeline, SetViewports, SetScissors, BindVertexBuffer, PushConstants, Draw.
37+
38+
## Gaps to Ship Games
39+
40+
- Bind groups + uniform/storage buffers (beyond push constants)
41+
- Textures + samplers (images, sprites, materials)
42+
- Depth/stencil and MSAA
43+
- Index buffers + DrawIndexed; multiple vertex buffers; instancing
44+
- Offscreen render targets (multipass)
45+
- 2D layer: sprite batching, atlas loader, ortho camera, text, input mapping
46+
- 3D layer: cameras, transforms, glTF load, basic materials/lighting
47+
- Desktop apps: egui integration; dialogs/clipboard as needed
48+
49+
## Targeted API Additions (sketches)
50+
51+
Bind groups and uniforms (value: larger, structured GPU data; portable across adapters; enables cameras/materials):
52+
```rust
53+
// Layout with one uniform buffer at set(0) binding(0)
54+
let layout = BindGroupLayoutBuilder::new()
55+
.with_uniform(0, PipelineStage::VERTEX)
56+
.build(&mut rc);
57+
58+
let ubo = BufferBuilder::new()
59+
.with_length(std::mem::size_of::<Globals>())
60+
.with_usage(Usage::UNIFORM)
61+
.with_properties(Properties::CPU_VISIBLE)
62+
.build(&mut rc, vec![initial_globals])?;
63+
64+
let group = BindGroupBuilder::new(&layout)
65+
.with_uniform(0, &ubo)
66+
.build(&mut rc);
67+
68+
let pipe = RenderPipelineBuilder::new()
69+
.with_layouts(&[&layout])
70+
.with_buffer(vbo, attrs)
71+
.build(&mut rc, &pass, &vs, Some(&fs));
72+
73+
// Commands inside a pass
74+
RC::SetPipeline { pipeline: pipe_id };
75+
RC::SetBindGroup { set: 0, group: group_id, dynamic_offsets: vec![] };
76+
RC::Draw { vertices: 0..3 };
77+
```
78+
79+
Notes
80+
- UBO vs push constants: UBOs scale to KBs and are supported widely; use for view/projection and per‑frame data.
81+
- Dynamic offsets (optional later) let you pack many small structs into one UBO.
82+
83+
Textures and samplers (value: sprites, materials, UI images; sRGB correctness):
84+
```rust
85+
let tex = TextureBuilder::new_2d(TextureFormat::Rgba8UnormSrgb)
86+
.with_size(w, h)
87+
.with_data(&pixels)
88+
.build(&mut rc);
89+
let samp = SamplerBuilder::linear_clamp().build(&mut rc);
90+
91+
let tex_layout = BindGroupLayoutBuilder::new()
92+
.with_sampled_texture(0)
93+
.with_sampler(1)
94+
.build(&mut rc);
95+
let tex_group = BindGroupBuilder::new(&tex_layout)
96+
.with_texture(0, &tex)
97+
.with_sampler(1, &samp)
98+
.build(&mut rc);
99+
100+
// In fragment shader, sample with: sampler2D + UVs; ensure vertex inputs provide UVs.
101+
// Upload path should convert source assets to sRGB formats when appropriate.
102+
```
103+
104+
Index draw and instancing (value: reduce vertex duplication; batch many objects in one draw):
105+
```rust
106+
RC::BindVertexBuffer { pipeline: pipe_id, buffer: 0 };
107+
RC::BindVertexBuffer { pipeline: pipe_id, buffer: 1 }; // instances
108+
RC::BindIndexBuffer { buffer: ibo_id, format: IndexFormat::Uint16 };
109+
RC::DrawIndexed { indices: 0..index_count, base_vertex: 0, instances: 0..instance_count };
110+
```
111+
112+
Instance buffer attributes example
113+
```rust
114+
// slot 1: per-instance mat3x2 (2D) packed as 3x vec2, plus tint color
115+
let instance_attrs = vec![
116+
// location 4..6 for rows
117+
VertexAttribute { location: 4, offset: 0, element: VertexElement { format: ColorFormat::Rgb32Sfloat, offset: 0 }},
118+
VertexAttribute { location: 5, offset: 0, element: VertexElement { format: ColorFormat::Rgb32Sfloat, offset: 8 }},
119+
VertexAttribute { location: 6, offset: 0, element: VertexElement { format: ColorFormat::Rgb32Sfloat, offset: 16 }},
120+
// location 7 tint (RGBA8)
121+
VertexAttribute { location: 7, offset: 0, element: VertexElement { format: ColorFormat::Rgba8Srgb, offset: 24 }},
122+
];
123+
```
124+
125+
Depth/MSAA (value: correct 3D visibility and improved edge quality):
126+
```rust
127+
let pass = RenderPassBuilder::new()
128+
.with_clear_color(wgpu::Color::BLACK)
129+
.with_depth_stencil(wgpu::TextureFormat::Depth32Float, 1.0, true, wgpu::CompareFunction::Less)
130+
.with_msaa(4)
131+
.build(&rc);
132+
133+
let pipe = RenderPipelineBuilder::new()
134+
.with_depth_format(wgpu::TextureFormat::Depth32Float)
135+
.build(&mut rc, &pass, &vs, Some(&fs));
136+
```
137+
138+
Notes
139+
- Use reversed‑Z (Greater) later for precision, but start with Less.
140+
- MSAA sample count must match between pass and pipeline.
141+
142+
Offscreen render targets (value: post‑processing, shadow maps, UI composition, picking):
143+
```rust
144+
let offscreen = RenderTargetBuilder::new()
145+
.with_color(TextureFormat::Rgba8UnormSrgb, width, height)
146+
.with_depth(TextureFormat::Depth32Float)
147+
.build(&mut rc);
148+
149+
let pass1 = RenderPassBuilder::new().with_target(&offscreen).build(&rc);
150+
let pass2 = RenderPassBuilder::new().build(&rc); // backbuffer
151+
152+
// Pass 1: draw scene
153+
RC::BeginRenderPass { render_pass: pass1_id, viewport };
154+
// ... draw 3D scene ...
155+
RC::EndRenderPass;
156+
157+
// Pass 2: fullscreen triangle sampling offscreen.color
158+
RC::BeginRenderPass { render_pass: pass2_id, viewport };
159+
RC::SetPipeline { pipeline: post_pipe };
160+
RC::SetBindGroup { set: 0, group: offscreen_group, dynamic_offsets: vec![] };
161+
RC::Draw { vertices: 0..3 };
162+
RC::EndRenderPass;
163+
```
164+
165+
WGSL support (value: first‑class wgpu shader language, fewer translation pitfalls):
166+
```rust
167+
let vs = VirtualShader::WgslSource { source: include_str!("shaders/quad.wgsl").into(), name: "quad".into(), entry_point: "vs_main".into() };
168+
let fs = VirtualShader::WgslSource { source: include_str!("shaders/quad.wgsl").into(), name: "quad".into(), entry_point: "fs_main".into() };
169+
```
170+
171+
Shader hot‑reload (value: faster iteration; no rebuild): watch file timestamps and recompile shaders when changed; swap pipeline modules safely between frames.
172+
173+
## 2D Prototype (Asteroids‑like)
174+
175+
Goals: sprite batching via instancing; atlas textures; ortho camera; input mapping; text HUD. Target 60 FPS with 10k sprites (mid‑range GPU).
176+
177+
Core draw:
178+
```rust
179+
RC::BeginRenderPass { render_pass: pass_id, viewport };
180+
RC::SetPipeline { pipeline: pipe_id };
181+
RC::SetBindGroup { set: 0, group: globals_gid, dynamic_offsets: vec![] };
182+
RC::SetBindGroup { set: 1, group: atlas_gid, dynamic_offsets: vec![] };
183+
RC::BindVertexBuffer { pipeline: pipe_id, buffer: 0 }; // quad
184+
RC::BindVertexBuffer { pipeline: pipe_id, buffer: 1 }; // instances
185+
RC::BindIndexBuffer { buffer: ibo_id, format: IndexFormat::Uint16 };
186+
RC::DrawIndexed { indices: 0..6, base_vertex: 0, instances: 0..sprite_count };
187+
RC::EndRenderPass;
188+
```
189+
190+
Building instance data each frame (value: dynamic transforms with minimal overhead):
191+
```rust
192+
// CPU side: update transforms and pack into a Vec<Instance>
193+
queue.write_buffer(instance_vbo.raw(), 0, bytemuck::cast_slice(&instances));
194+
```
195+
196+
Text rendering options (value: legible UI/HUD):
197+
- Bitmap font atlas: simplest path; pack glyphs into the sprite pipeline.
198+
- glyphon/glyph_brush integration: high‑quality layout; more deps; implement later.
199+
200+
## 3D Prototype (Orbit Camera + glTF)
201+
202+
Goals: depth test/write, indexed mesh, textured material, simple lighting; orbit camera.
203+
204+
Core draw mirrors 2D but with depth enabled and mesh buffers.
205+
206+
Camera helpers (value: reduce boilerplate and bugs):
207+
```rust
208+
let proj = matrix::perspective_matrix(60f32.to_radians(), width as f32 / height as f32, 0.1, 100.0);
209+
let view = matrix::translation_matrix([0.0, 0.0, -5.0]); // or look_at helper later
210+
let view_proj = proj.multiply(&view);
211+
```
212+
213+
glTF loading (value: standard asset path): map glTF meshes/materials/textures to VBO/IBO and bind groups; start with positions/normals/UVs and a single texture.
214+
215+
## Milestones & Estimates
216+
217+
- M1 Rendering Foundations (2–3 weeks): bind groups/UBO, textures/samplers, depth/MSAA, indexed draw, instancing.
218+
- M2 2D Systems (2–3 weeks): sprite batching, atlas, 2D camera, input, text; ship prototype.
219+
- M3 3D Systems (3–5 weeks): cameras, glTF, materials/lighting; ship scene.
220+
- M4 Desktop UI (1–2 weeks): egui integration + example app.
221+
222+
## Changelog
223+
224+
- 2025-09-26 (v0.2.0) — Expanded examples, added value rationale per feature, offscreen/post, WGSL, and iteration tips.
225+
- 2025-09-24 (v0.1.0) — Initial draft with gaps, roadmap, and prototype plan.

0 commit comments

Comments
 (0)