Skip to main content
The white-box properties that make Euca a world engine sit on top of a real game engine: an archetype ECS, a real-time PBR renderer, and a custom physics solver. This page maps what’s actually implemented — what runs by default, what’s opt-in, and what’s built but not yet wired into the default frame.

The ECS core

The world is an archetype ECS (euca-ecs), built for throughput:
  • Columnar (SoA) storage — components of the same archetype live in contiguous columns, so systems iterate cache-friendly arrays.
  • Generational entities — an entity is an index + a generation; freed slots are recycled with a bumped generation so stale handles are detected, never silently reused.
  • Opt-in sparse sets — rarely-attached components can be stored sparsely to avoid archetype churn.
  • Rayon-parallel queriespar_for_each shards iteration across cores in 2048-row chunks (falling back to sequential below ~16K rows or for sparse components).
  • Change detection — per-row change ticks drive Changed<T> filters.
  • Bulk opsspawn_batch for fast mass spawning; a Commands buffer defers structural mutation so it can’t race in-flight queries.
  • Parallel scheduler — systems are topologically ordered and run concurrently when their component access doesn’t conflict; a debug-only access guard catches violations with zero release-build cost.
  • Double-buffered events — events live two ticks so producers and consumers at different points in the frame both see them.
This is the substrate behind the world-as-a-table view and the performance numbers.

Rendering

Euca ships a real-time physically-based forward renderer (euca-render) over a generic RHI (euca-rhi), with two backends: wgpu 27 (cross-platform, default) and a hand-written native Metal backend (macOS).
PBR material sweep rendered by Euca's renderer

A PBR material sweep — varying roughness and metalness — rendered headless by the visual_check example: Cook-Torrance shading, cascaded soft shadows, SSAO, and ACES tonemapping.

Live by default — what the frame method actually executes:
  • PBR — Cook-Torrance specular (GGX distribution, Smith geometry, Schlick Fresnel).
  • Shadows — 3-cascade cascaded shadow maps (2048² depth array) with 16-tap rotated-Poisson PCF filtering.
  • Anti-aliasing — MSAA 4× + FXAA.
  • HDR + postRgba16Float HDR target, bloom, ACES tonemapping, color grading, vignette.
  • SSAO, separate transparent and water passes, an editor outline pass, and a velocity/motion-vector pass.
  • Volumetric fog — enabled by default (tune or disable via /fog/settings).
Opt-in (built, tested, off by default): TAA, motion blur, depth-of-field, screen-space reflections, image-based lighting (split-sum) + spherical-harmonic probes (a dummy environment is bound until you supply one), HZB occlusion culling, GPU particles, and MetalFX upscaling (Metal backend only). Headless rendering to PNG is real, by two paths: the visual_check example renders the full PBR pipeline to an offscreen target and saves a PNG, and the dataset CaptureRenderer renders flat-shaded geometry plus ground-truth segmentation and depth channels (the answer-key’s visual side).
Built but not yet wired into the default frame (so we don’t overclaim): a deferred / G-buffer path, clustered/tiled lighting, bindless materials, mesh shaders, and a frame-graph all exist in the codebase but are not driven by the default renderer (the shipped path is capped forward — fixed small point/spot arrays — not Forward+). GPU-driven indirect draw is active where the device supports multi-draw-indirect (e.g. Apple Silicon); bindless and mesh shaders are opt-in setters an app must enable. An SSGI compute pass dispatches each frame but its result is currently discarded. Treat the unwired items as in-progress, not shipping features.

Physics

euca-physics is a custom, dependency-free 3D physics engine (no Rapier/PhysX):
A physics stack simulated and rendered by Euca

A stack of rigid bodies settling under gravity — rendered headless by visual_check, simulated by the euca-physics solver.

  • Solver — fixed-timestep semi-implicit Euler with a two-stage constraint solve: position correction then an iterated sequential-impulse (PGS) velocity solve with cross-frame warm-starting, full world-space inertia tensors, and union-find contact islands solved in parallel.
  • Broad phase — a uniform spatial-hash grid (large bodies handled all-pairs).
  • Narrow phase — AABB/OBB boxes (SAT + clipped manifolds), spheres, capsules, convex hulls (SAT + clip), static triangle meshes (BVH + per-triangle clip), and compound colliders.
  • Articulation — reduced-coordinate articulation (RNEA + Cholesky) for serial fixed-base chains of 1-DoF revolute/prismatic joints, plus a free-floating 6-DoF body, with motors, limits, link colliders, and contacts; alongside maximal-coordinate joints (distance/ball/ revolute with motors and limits).
  • Controllers — a kinematic capsule character controller (ground probe, coyote time) and a raycast-suspension vehicle controller (engine curve, auto gears).
  • Queries — raycast, overlap, and sweep.
  • Determinism — the solver is run-to-run bit-identical within the same binary, gated by a committed golden-hash test.
Scope and caveats (see the physics review framing): continuous collision detection (CCD) is a center-ray raycast of a body’s per-step displacement against non-dynamic bodies only — it is not a shape-sweep, dynamic-vs-dynamic tunneling is unhandled, and trimesh/compound statics fall back to discrete. Capsules are Y-axis only; triangle meshes are static-only; cook-time convex decomposition is a built-in median-split approximation (not V-HACD/CoACD). Determinism is within a build and platform, not a cross-machine guarantee.

Measured performance

Real benchmark numbers — 1M entities per parallel tick, and how to reproduce them.