stylized 1-bit rendering
This commit is contained in:
53
CLAUDE.md
53
CLAUDE.md
@@ -6,6 +6,8 @@ This file provides guidance to Claude Code when working with code in this reposi
|
||||
|
||||
This is a pure Rust game project using SDL3 for windowing/input, wgpu for rendering, rapier3d for physics, and a low-res retro aesthetic with dithering. This is a migration from the Godot-based snow_trail project, implementing the same snow deformation system and character controller without engine dependencies.
|
||||
|
||||
**Content Creation:** Blender 5.0 is used for terrain modeling and asset export (glTF meshes + EXR heightmaps).
|
||||
|
||||
## Code Style
|
||||
|
||||
**Code Documentation Guidelines**:
|
||||
@@ -143,12 +145,17 @@ SDL Events → InputState → player_input_system() → InputComponent → movem
|
||||
- Final blit pass upscales framebuffer to window using nearest-neighbor sampling
|
||||
- Depth buffer for 3D rendering with proper occlusion
|
||||
|
||||
**Terrain Height Deformation:**
|
||||
**Terrain Rendering:**
|
||||
- glTF mesh exported from Blender 5.0 with baked height values in vertices
|
||||
- No runtime displacement in shader - vertices rendered directly
|
||||
- Separate terrain pipeline for terrain-specific rendering
|
||||
- Terrain mesh has heights pre-baked during export for optimal performance
|
||||
|
||||
**Terrain Physics:**
|
||||
- EXR heightmap files loaded via `exr` crate (single-channel R32Float format)
|
||||
- Height displacement applied in vertex shader
|
||||
- Separate terrain pipeline with texture sampling in vertex stage
|
||||
- TerrainUniforms includes height_scale parameter for tweaking displacement strength
|
||||
- R32Float textures require non-filterable samplers (FilterMode::Nearest)
|
||||
- Heightmap loaded directly into rapier3d heightfield collider
|
||||
- No runtime sampling or computation - instant loading
|
||||
- Both glTF and EXR exported from same Blender terrain, guaranteed to match
|
||||
|
||||
**Lighting Model:**
|
||||
- Directional light (like Godot's DirectionalLight3D)
|
||||
@@ -194,7 +201,7 @@ cargo fmt
|
||||
|
||||
WGSL shaders are stored in the `shaders/` directory:
|
||||
- `shaders/standard.wgsl` - Standard mesh rendering with directional lighting
|
||||
- `shaders/terrain.wgsl` - Terrain rendering with height displacement
|
||||
- `shaders/terrain.wgsl` - Terrain rendering with shadow mapping (no displacement)
|
||||
- `shaders/blit.wgsl` - Fullscreen blit for upscaling low-res framebuffer
|
||||
|
||||
Shaders are loaded at runtime via `std::fs::read_to_string()`, allowing hot-reloading by restarting the application.
|
||||
@@ -224,10 +231,9 @@ Shaders are loaded at runtime via `std::fs::read_to_string()`, allowing hot-relo
|
||||
**Rendering:**
|
||||
- `render.rs` - wgpu renderer, pipelines, bind groups, DrawCall execution
|
||||
- `shader.rs` - Standard mesh shader (WGSL) with diffuse+ambient lighting
|
||||
- `terrain.rs` - Terrain mesh generation and pipeline creation
|
||||
- `terrain.rs` - Terrain entity spawning, glTF loading, EXR heightmap → physics collider
|
||||
- `postprocess.rs` - Low-res framebuffer and blit shader for upscaling
|
||||
- `mesh.rs` - Vertex/Mesh structs, plane/cube mesh generation, glTF loading
|
||||
- `heightmap.rs` - EXR heightmap loading using `exr` crate
|
||||
- `draw.rs` - DrawManager (legacy, kept for compatibility)
|
||||
|
||||
**Game Logic:**
|
||||
@@ -260,32 +266,32 @@ Shaders are loaded at runtime via `std::fs::read_to_string()`, allowing hot-relo
|
||||
- **bytemuck**: Safe byte casting for GPU buffer uploads (Pod/Zeroable for vertex data)
|
||||
- **anyhow**: Ergonomic error handling
|
||||
- **gltf**: Loading 3D models in glTF format
|
||||
- **exr**: Loading EXR heightmap files (single-channel float data)
|
||||
- **image**: Image loading and processing (includes EXR support)
|
||||
- **half**: Float16 support (dependency of exr)
|
||||
- **exr**: Loading EXR heightmap files (single-channel float data for physics colliders)
|
||||
- **kurbo**: Bezier curve evaluation for movement acceleration curves
|
||||
|
||||
## Technical Notes
|
||||
|
||||
### EXR Heightmap Loading
|
||||
When loading EXR files with the `exr` crate:
|
||||
### EXR Heightmap Loading (Physics Only)
|
||||
When loading EXR files with the `exr` crate for physics colliders:
|
||||
- Must import traits: `use exr::prelude::{ReadChannels, ReadLayers};`
|
||||
- Use builder pattern: `.no_deep_data().largest_resolution_level().all_channels().all_layers().all_attributes().from_file(path)`
|
||||
- Extract float data: `channel.sample_data.values_as_f32().collect()`
|
||||
- Create R32Float texture for height data
|
||||
- R32Float is non-filterable, requires `FilterMode::Nearest` sampler
|
||||
- Convert to nalgebra DMatrix for rapier3d heightfield collider
|
||||
- No GPU texture creation - physics data only
|
||||
|
||||
### wgpu Texture Formats
|
||||
- R32Float = single-channel 32-bit float, **non-filterable**
|
||||
- Use `TextureSampleType::Float { filterable: false }` in bind group layout
|
||||
- Use `SamplerBindingType::NonFiltering` for sampler binding
|
||||
- Attempting linear filtering on R32Float causes validation errors
|
||||
### Blender Export Workflow
|
||||
**Using Blender 5.0** for terrain creation and export:
|
||||
- Export terrain as **glTF** with baked height values in mesh vertices
|
||||
- Export same terrain as **EXR** heightmap (single-channel R32Float)
|
||||
- Both files represent the same terrain data, guaranteeing visual/physics sync
|
||||
- glTF used for rendering (vertices rendered directly, no shader displacement)
|
||||
- EXR used for physics (loaded into rapier3d heightfield collider)
|
||||
|
||||
### Multiple Render Pipelines
|
||||
- `Pipeline` enum determines which pipeline to use per DrawCall
|
||||
- Different pipelines can have different shaders, bind group layouts, uniforms
|
||||
- Terrain pipeline: includes height texture binding in vertex stage
|
||||
- Standard pipeline: basic mesh rendering without height displacement
|
||||
- Terrain pipeline: shadow-mapped rendering with line hatching shading
|
||||
- Standard pipeline: basic mesh rendering with diffuse lighting
|
||||
- Each pipeline writes to its own uniform buffer before rendering
|
||||
|
||||
### ECS Component Storages
|
||||
@@ -589,7 +595,8 @@ let time = Time::get_time_elapsed(); // Anywhere in code
|
||||
- ✅ Low-res framebuffer (160×120) with Bayer dithering
|
||||
- ✅ Multiple render pipelines (standard mesh + terrain)
|
||||
- ✅ Directional lighting with diffuse + ambient
|
||||
- ✅ EXR heightmap loading and terrain displacement
|
||||
- ✅ Terrain rendering (glTF with baked heights, no shader displacement)
|
||||
- ✅ EXR heightmap loading for physics colliders
|
||||
- ✅ glTF mesh loading
|
||||
- ✅ render_system (ECS-based DrawCall generation)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user