Raymarch Bevy
A ray-marching renderer built in Rust using Bevy and WGSL shaders.
A custom fullscreen shader is used to replace the camera with an in-shader camera that performs ray marching to display the scene.
Integrated with eGUI to allow for real-time modification of parameters at runtime.
Project Summary
- Built a real-time ray-marched 3D scene renderer using a fullscreen shader pipeline in
Bevy. - Implemented responsive rendering that compensates for window rescaling to remove texture stretching.
- Created a fly camera system which pans via mouse input, translates based on keyboard inputs, and includes sprint controls for faster movement.
- Designed a modular shape system built using Signed Distance Functions, currently implemented for spheres, cubes, and planes.
- Added smooth unions or boolean blending for combining SDFs, with configurable blending constants.
- Implemented dynamic lighting, surface shading, and gamma correction in the fragment shader, consistent with the Phong shading model.
- Built a custom ray-march loop with collision detection, outlines for near-misses, and a gradient sky background.
- Structured shader data using Rust-side materials passed directly into
WGSLuniforms. - Included development-build
eGUItooling to modify in-game data in real-time.
Technical Challenges
- Balancing of ray-march step count against rendering performance.
- Maintaining visual quality while avoiding excessive shader calculations.
- Preventing stretched output across varying window aspect ratios.
- Ensuring stable camera controls with smooth rotation, while avoiding gimbal locking issues.
- Passing structured data from
Rustinto the shader efficiently using uniforms, including dynamic shape data arrays.
Rendering Pipeline
- A fullscreen quad rendered each frame.
- Fragment shader casts a ray from the camera for each pixel.
- Ray marches through the scene using Signed Distance Functions.
- Closest hit point is shaded using normals and lighting, near-misses are highlighted and become outlines.
Shader Camera
- Replaced the traditional in-engine camera with an in-shader camera.
- Calculated a ray direction, per-pixel, using screen-space coordinates and the calculated view frustum (based on camera parameters).
- Implemented free-fly movement with keyboard translation across forward, right, and up axes of the camera.
- Added mouse-look controls to rotate camera smoothly in real-time.
- Camera rotations are stored and modified as quaternions to avoid gimbal lock.
- Passed camera position, rotation, FOV, and basis vectors from
RustintoWGSLuniforms on each frame. - Included sprint movement for faster scene navigation (Controlled via
Shift ). - Integrated camera parameters with the
eGUIwindows to allow real-time modification while the scene is running.
Shape System
- Scene geometry represented using modular Signed Distance Functions primitives.
- Currently supports spheres, cubes, and planes.
- New shapes can be added by implementing additional SDF definitions.
- Each shape stores its position, scale, and colour, as well as its shape type (represented as an integer).
- Shapes can be blended using smooth unions or combined using boolean operations.
- Blending parameters are exposed at runtime and can be modified using the
eGUIwindows.
Lighting & Shading
- Surface normals are approximated from neighbouring SDF samples.
- Phong-style lighting model used for the diffuse and specular shading.
- Single dynamic light source with configurable position and colour.
- Gamma correction applied before final colour output for improved colour accuracy.
- Background rendered as a sky gradient when the ray didn't collide with any geometry.
- Silhouette outlines are generated from near-miss ray distances.
- Hard shadows are calculated to darken areas where the shapes block the light from the light source.
Future Improvements
- Portal rendering using non-linear ray traversal through SDF space.
- Soft shadows, and ambient occlusion to improve realism of the rendering.
- Multi-light support with extended material properties (roughness, emissiveness, etc).
- Adaptive ray-march step optimisation based on scene complexity.
- Additional SDF primitives: cylinders, capsules, and toruses.