diff options
Diffstat (limited to 'doc/SDF_EFFECT_GUIDE.md')
| -rw-r--r-- | doc/SDF_EFFECT_GUIDE.md | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/doc/SDF_EFFECT_GUIDE.md b/doc/SDF_EFFECT_GUIDE.md new file mode 100644 index 0000000..fba80e7 --- /dev/null +++ b/doc/SDF_EFFECT_GUIDE.md @@ -0,0 +1,164 @@ +# SDF Effect Guide + +Streamlined workflow for SDF raymarching effects using the `SDFEffect` base class. + +--- + +## Quick Start + +```cpp +// src/effects/my_sdf_effect.h +class MySDFEffect : public SDFEffect { + MySDFEffect(const GpuContext& ctx); + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; + RenderPass pass_; +}; +``` + +```cpp +// src/effects/my_sdf_effect.cc +#include "effects/my_sdf_effect.h" +#include "gpu/gpu.h" +#include "gpu/shaders.h" + +MySDFEffect::MySDFEffect(const GpuContext& ctx) : SDFEffect(ctx) { + ResourceBinding bindings[] = { + {uniforms_.get(), WGPUBufferBindingType_Uniform}, + {camera_params_.get(), WGPUBufferBindingType_Uniform}}; + pass_ = gpu_create_render_pass(ctx_.device, ctx_.format, + my_sdf_shader_wgsl, bindings, 2); + pass_.vertex_count = 3; +} + +void MySDFEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { + uniforms_.update(ctx_.queue, uniforms); + + // Orbiting camera + vec3 cam_pos(std::cos(uniforms.time * 0.5f) * 5.0f, 2.0f, + std::sin(uniforms.time * 0.5f) * 5.0f); + update_camera(cam_pos, vec3(0, 0, 0), vec3(0, 1, 0), 0.785398f, 0.1f, 100.0f, + uniforms.aspect_ratio); + + wgpuRenderPassEncoderSetPipeline(pass, pass_.pipeline); + wgpuRenderPassEncoderSetBindGroup(pass, 0, pass_.bind_group, 0, nullptr); + wgpuRenderPassEncoderDraw(pass, pass_.vertex_count, 1, 0, 0); +} +``` + +```wgsl +// workspaces/main/shaders/my_sdf.wgsl +#include "common_uniforms" +#include "camera_common" +#include "math/sdf_shapes" +#include "render/raymarching" + +@group(0) @binding(0) var<uniform> uniforms: CommonUniforms; +@group(0) @binding(1) var<uniform> camera: CameraParams; + +fn df(p: vec3<f32>) -> f32 { + return sdSphere(p, 1.0); +} + +@vertex +fn vs_main(@builtin(vertex_index) vid: u32) -> @builtin(position) vec4<f32> { + let x = f32((vid & 1u) << 2u) - 1.0; + let y = f32((vid & 2u) << 1u) - 1.0; + return vec4<f32>(x, y, 0.0, 1.0); +} + +@fragment +fn fs_main(@builtin(position) pos: vec4<f32>) -> @location(0) vec4<f32> { + let uv = (pos.xy / uniforms.resolution - 0.5) * 2.0; + let ray = getCameraRay(camera, uv); + let t = rayMarch(ray.origin, ray.direction, 0.0); + + var col = vec3<f32>(0.1); + if (t < MAX_RAY_LENGTH) { + let hit_pos = ray.origin + ray.direction * t; + let n = normal(hit_pos); + col = vec3<f32>(n * 0.5 + 0.5); + } + return vec4<f32>(col, 1.0); +} +``` + +--- + +## Available Uniforms + +### CommonUniforms (binding 0) +- `resolution`: vec2 (screen size) +- `time`: float (physical seconds) +- `beat_time`: float (musical beats) +- `beat_phase`: float (0-1 within beat) +- `audio_intensity`: float (peak) +- `aspect_ratio`: float + +### CameraParams (binding 1) +- `inv_view`: mat4x4 (inverse view matrix) +- `fov`: float (vertical FOV in radians) +- `near_plane`, `far_plane`: float +- `aspect_ratio`: float + +--- + +## WGSL Helpers + +From `camera_common.wgsl`: + +```wgsl +fn getCameraRay(cam: CameraParams, uv: vec2<f32>) -> Ray; +fn getCameraPosition(cam: CameraParams) -> vec3<f32>; +fn getCameraForward(cam: CameraParams) -> vec3<f32>; +fn getCameraUp(cam: CameraParams) -> vec3<f32>; +fn getCameraRight(cam: CameraParams) -> vec3<f32>; +``` + +From `render/raymarching.wgsl`: + +```wgsl +fn rayMarch(ro: vec3<f32>, rd: vec3<f32>, initt: f32) -> f32; +fn normal(pos: vec3<f32>) -> vec3<f32>; +fn shadow(lp: vec3<f32>, ld: vec3<f32>, mint: f32, maxt: f32) -> f32; +``` + +From `math/sdf_shapes.wgsl`: + +```wgsl +fn sdSphere(p: vec3<f32>, r: float) -> f32; +fn sdBox(p: vec3<f32>, b: vec3<f32>) -> f32; +fn sdTorus(p: vec3<f32>, t: vec2<f32>) -> f32; +fn sdPlane(p: vec3<f32>, n: vec3<f32>, h: f32) -> f32; +``` + +--- + +## Camera Control + +```cpp +// Method 1: Manual values +update_camera(position, target, up, fov, near, far, aspect); + +// Method 2: Camera object +Camera cam; +cam.position = vec3(0, 5, 10); +cam.target = vec3(0, 0, 0); +update_camera(cam, uniforms.aspect_ratio); +``` + +--- + +## Registration Checklist + +1. Add shader to `workspaces/main/assets.txt` +2. Add extern declaration to `src/gpu/shaders.h` +3. Add definition to `src/gpu/shaders.cc` +4. Add `.cc` to `cmake/DemoSourceLists.cmake` (both headless & normal) +5. Include header in `src/gpu/demo_effects.h` +6. Add to `src/tests/gpu/test_demo_effects.cc` + +--- + +## Example: workspaces/main/shaders/sdf_test.wgsl |
