rndr
rndr is a CPU-side rendering and physics experiment in Rust. It implements its own math primitives, camera projection, triangle rasterization, fragment-shader abstraction, depth-buffered pixel output, ray casting, mesh collision checks, and rigid-body collision response.
The workspace is divided into:
rndr-math,rndr-core,rndr-phys,- several executable examples.
rndr-math
The math crate defines custom vector and matrix types rather than delegating to a standard linear-algebra package.
Vector support
V3 implements:
- vector addition and subtraction,
- scalar multiplication and division,
- magnitude and normalization,
- dot products,
- cross products,
- reflection-vector generation,
- Euler-angle rotation through internally constructed rotation matrices,
- weighted interpolation.
These primitives are reused across camera projection, geometry transforms, ray intersection tests, and rigid-body response.
Matrix support
The rendering and collision code use custom M3x3 matrices for:
- camera basis transforms,
- rotation-related calculations,
- solving ray/triangle intersection systems through matrix inversion.
Scene and component model
The core crate uses an object/component structure:
Object,ObjectManager,Component,- built-in components such as
Transform,Camera, andMeshRenderable.
This provides a minimal engine-style organization. Rendering and physics systems fetch the components they require rather than operating on bespoke one-off structs.
Camera projection
The Camera component constructs a projection matrix from camera orientation vectors:
- forward,
- right,
- up.
For each vertex:
- Object transform is applied.
- Camera translation is removed.
- The point is multiplied by the projection matrix.
- Optional perspective scaling is applied if enabled.
- Points behind the near plane are rejected later in the render path.
The perspective branch uses a configurable display-surface offset and a zero_threshold guard to avoid unstable divisions near zero projected depth.
Mesh rendering pipeline
The main renderer processes mesh triangles in parallel using Rayon:
- Retrieve object transform and mesh.
- Compute the camera projection matrix.
- Project the three vertices of each triangle.
- Reject triangles that lie behind the near plane.
- Convert projected vertices into 2D triangle coordinates.
- Rasterize pixels inside the triangle bounding box.
- Compute barycentric weights through sub-triangle area tests.
- Interpolate vertex attributes with those weights.
- Create fragment data and call the mesh fragment shader.
- Emit candidate pixels to a
PixelGrid.
This is a software rasterization pipeline. The fragment stage is abstracted through a FragShader trait, allowing different shading behavior without changing the triangle traversal logic.
Rasterization detail
Triangle coverage is determined by comparing the sum of sub-triangle areas to the total triangle area within a small epsilon. For covered pixels, barycentric weights are derived from those sub-areas.
The interpolated values are used to construct:
- relative position,
- world-space position,
- interpolated color/depth output.
That fragment data is then passed to the active shader implementation.
Pixel storage and depth handling
PixelGrid maintains:
- RGB pixel storage,
- one depth value per pixel.
Each candidate fragment is written through set_pixel. The existing depth is compared before color replacement, which implements a z-buffer-style occlusion test.
Ray casting
The physics crate introduces:
Ray,ObjectIntersectionRay,- the
Raycastabletrait, - hit structures containing position, normal, and distance.
Ray intersection against mesh colliders is computed by transforming triangle vertices into world space, constructing a 3x3 system using triangle edges and ray direction, inverting that system, and reading the resulting barycentric coordinates plus ray distance.
The hit is accepted when:
- the distance is non-negative,
- barycentric coordinates are inside the triangle,
- the optional maximum distance constraint is satisfied.
Mesh collision detection
MeshCollider implements collision checks by:
- Finding the transformed mesh center.
- Iterating vertices in parallel.
- Casting rays from the mesh center toward each vertex.
- Testing whether those rays hit another mesh before reaching the chosen vertex.
- Returning an intersection point and normal when a hit is found.
This is a geometric collision-detection strategy built from the ray-casting machinery rather than a broad-phase/narrow-phase physics library.
Collision response
The physics manager gathers collisions and reacts using:
- linear velocity,
- angular velocity,
- collision offsets relative to mesh centers,
- momentum-like directional calculations,
- updates to both translation and rotation state.
The implementation is still experimental, but it already connects detection, normal extraction, and response.