embedded-3dgfx
A no_std 3D graphics and physics engine for embedded systems: software rasterization, rigid/soft-body physics, skeletal animation, and effects tuned for MCUs.
Fork of embedded-gfx by Kezii, extended with textures, fog/dithering, DMA swapchains, AA, physics, BSP, and more.
Highlights
- Modular Architecture — explicit
raster,shader,shapes,camera_controller,navmesh,absm, andinputnamespaces - Zero-Cost
FragmentShaderPipeline — composable decorator shaders (FogShader,DitherShader,ScreenTintShader,PaletteShader,WaterReflectShader, or custom materials) - Record / execute — traverse once, rasterize from a fixed-capacity command buffer (
PrimitiveHeader+ packed typed descriptors for low RAM footprint) - Rendering — MVP + frustum/backface cull, Z-buffer, flat/Gouraud/Blinn-Phong, perspective textures, Bayer dither, Reinhard tonemapping, sub-pixel Q16.16 rasterization, lights, particles, LOD, HUD
- Physics & Navigation (features
physics,scene) — rigid bodies, joints, soft body, ray primitives, NavMesh A* pathfinding - Animation — skeletal LBS, vertex morphs, ABSM state machines, transform tracks, spline curves / tweens
- Embedded-friendly —
heaplesscaps, Cortex-M SWAR/DSP SIMD optimizations, async-agnostic swapchain present, silicon hardware offloading hooks (HardwareAccelerator)
Screenshots
Installation
[]
# Embedded (no_std) — slim default is row_width_240
= { = "0.6", = false, = ["row_width_320", "depth-u16"] }
# Orientation-style lit meshes
= { = "0.6", = false, = ["row_width_320", "depth-u16", "lighting"] }
# Desktop / simulator
= { = "0.6", = ["std", "physics"] }
MCU feature recipes
| Recipe | Features |
|---|---|
| Minimal wireframe | default-features = false, row_width_320, depth-u16 |
| Lit mesh (Gouraud / Blinn / Toon) | add lighting |
| Retro / Doom-style | lighting, textured, raycast, hud |
| Physics demo | add physics |
Quick start
use ;
use Vector3;
let mut engine = new;
engine.camera.set_position;
let geometry = Geometry ;
let mut mesh = new;
mesh.set_render_mode;
let mut commands = new;
engine.record.unwrap;
engine.execute.unwrap;
Geometry & Surface Normals for Lighting
When using lit render modes (RenderMode::SolidLightDir, BlinnPhong, Toon, GouraudLightDir), the engine requires surface face normals in Geometry.normals (or vertex_normals) to evaluate light angles (N · L):
- Static Flash ROM Storage (Recommended for MCUs): Precompute face normals offline or at compile-time and store them alongside vertices as
&'static [[f32; 3]](0 RAM overhead). - On-Demand Helper: If authoring procedural geometry in code, use
Geometry::compute_face_normals_into(&verts, &faces, &mut out_normals)orGeometry::compute_face_normals(&verts, &faces):
let mut normals = ;
compute_face_normals_into;
let geometry = Geometry ;
More patterns (particles, lights, fog, physics, skeleton, soft body, async present) live under examples/ and on docs.rs.
Feature flags
| Flag | Default | Description |
|---|---|---|
row_width_* |
240 |
Row-buffer width (96 / 160 / 240 / 320, mutually exclusive) |
std |
off | Desktop helpers / perfcounter |
lighting |
off | SolidLightDir / Gouraud / Blinn / Toon / SectorBright + lights |
textured |
off | Texture modes + texture module (implies lighting) |
raycast |
off | Doom-style raycaster, BSP helpers, sector_lights |
scene |
off | Skeleton, character, particles, billboard, animation / scene stream |
hud |
off | HUD helpers |
painters |
off | Painter's algorithm helpers (painters module) |
physics |
off | Rigid body, soft body, physics raycast |
aa-heuristic / aa-coverage |
off | Triangle edge AA (coverage needs a W×H buffer) |
dsp / fixed-transform / fixed-raster |
off | Shared Q16.16 / quat path via embedded-dsp |
triple-buffering / embassy / dma2d |
off | Swapchain / Embassy / DMA2D hooks |
perfcounter / dwt-profiler / rtt-trace / itm-trace |
off | Timing / trace sinks |
Flash impact of the slim recipes is tracked in docs/feature-size.md (size_harness + CI budget).
Optional scene extras (off by default — keeps MCU binaries lean)
| Feature | What you get |
|---|---|
aabb-cull |
Cached AABB, two-stage frustum cull, raycast broadphase |
render-layers |
Camera ↔ mesh layer bitmasks |
record-sort |
Priority / distance sort in record |
lod-crossfade |
LOD fade margins |
anim-blend |
Clip blending, bone slerp, skinned AABBs (also enables scene) |
gizmos |
AABB / frustum debug wireframes |
visibility-extras |
aabb-cull + render-layers + record-sort + lod-crossfade |
scene-extras |
All of the above |
= { = "0.6", = ["std", "scene-extras"] }
Examples
# physics demos also need: --features "std,physics"
Rendering: basic_rendering, rotating_cube, scene_viewer, lighting_demo, gouraud_demo, blinn_phong_demo, fog_dithering_demo, texture_mapping_demo, mesh_texture_demo, retro_presets_demo, bsp_builder_demo, dma_rendering_demo, billboard_demo, lod_demo, vertex_animation_demo, painters_algorithm_demo, boot_menu, stl_viewer, water_reflection_ssr_demo, hybrid_hud_sprite_demo, star_striker_demo, …
Physics: physics_rolling_ball, physics_bouncing_balls, physics_pendulum, physics_newtons_cradle, physics_stack_tower, cloth_simulation, jelly_cube_demo, raycast_demo, walkable_demo, capsule_physics_demo, …
Docs & tools
| Resource | Topic |
|---|---|
docs/caps-and-telemetry.md |
Caps, telemetry, CI budgets |
docs/feature-size.md |
Slim vs full flash (.text) budgets |
docs/backend-integration.md |
Board bring-up, memory sizing |
docs/asset-pipeline.md |
Offline assets / scene streaming |
tools/blender_addon |
Blender mesh / animation export add-on |
Typical target: Cortex-M4F/M33 with FPU; ~128 KB RAM minimum, ~512 KB+ recommended for double-buffer + Z + physics at 240×135.
Testing
Git hooks (fmt on commit / push): ./scripts/install-git-hooks.sh
Contributing
PRs welcome — especially board backends, broad-phase spatial structures, and extra joint / collider types.
License
Dual-licensed under MIT OR Apache-2.0. See LICENSE-MIT, LICENSE-APACHE, and NOTICE.