One Spatial Algebra, Four Industries
Why a robot arm, a ray tracer, a GPU shader, and an AI model are the same math — and why every other platform implements them four times
Why a robot arm, a ray tracer, a GPU shader, and an AI model are the same math — and why every other platform implements them four times
A rigid-body transform in a robot's kinematic chain and an object transform in a ray tracer are the same mathematical object. A 6-D velocity in a dynamics simulator and a ray direction in a renderer are the same type. A spatial inertia tensor and a symmetric 3x3 matrix for physics are the same structure.
Every platform today implements these four times — once in the renderer's C++, once in the physics middleware, once in the shader language, once in the ML framework — and then pays forever to keep the four copies agreeing.
We implemented them once, in the compiler, as first-class types with SIMD register mappings. Rendering, robotics, GPU shading, and AI matrix work then stop being four integrations and become four backends of one language.
This is the story of Aurora, our rendering engine — and why it turned out to be much more than a renderer.
The four-codebase problem
Unreal Engine has a C++ codebase for rendering, a separate Blueprint VM for gameplay logic, HLSL for GPU shaders, and whatever ML framework you bolt on for AI features. Unity has C# for scripts, HLSL/GLSL for shaders, C++ for the engine core, and a Python binding for ML. Every game engine, simulation platform, and robotics stack has this split.
The cost is not just "four languages to learn." It's four type systems that must agree on what a 4x4 matrix is, four serialization formats for scene data, four debugging toolchains, and an integration layer between each pair — 6 integration surfaces for 4 systems. Every integration surface is a place where things break, performance degrades, and engineers spend time on glue instead of features.
EPL eliminates this. vec3, color, mat3, mat4, quat, se3 (rigid-body transform), sym3 (symmetric 3x3) are first-class compiler types with operator overloads. T1 * T2 on two SE3 transforms compiles directly to a transform composition — no function call overhead, no library dispatch. The compiler maps these to SIMD registers with AVX2+FMA instruction sequences for the performance-critical 4-wide kernels.
There is no math library. The math is the language.
The type mapping that makes robotics engineers stop scrolling
This table is the most persuasive artifact in the entire project, because a robotics engineer reads it and immediately sees their own stack:
| Pinocchio (robotics) | Aurora (rendering) | Shared EPL type |
|---|---|---|
| SE3 rigid-body transform | Object transform | se3 (mat3 + vec3) |
| Motion (6-D velocity) | Ray direction, animation velocity | motion |
| Force (6-D wrench) | Light direction, surface force | force |
| Spatial inertia | Mass for physics | inertia (mass + COM + sym3) |
| Forward kinematics | Forward ray tracing | Chain of SE3 composes |
Pinocchio (stack-of-tasks/pinocchio) is the reference open-source robotics library. The point is not "Aurora also does robotics." The point is that the digital twin and the render of the digital twin are the same object in the same file, under the same compiler. The kinematic model you simulate and the visual model you render share types, share data, and share version control.
Training simulations, industrial XR, and location-based entertainment all live in this intersection. Every other platform requires a bridge between the simulation engine and the rendering engine. Aurora doesn't — because there's no boundary.
The operator architecture — rendering without material knowledge
Aurora inherits the six-operator model from its heritage codebase: MOP (material), LOP (light), LrOP (layer), ROP, ProOP, ObjOP. The hard architectural rule: the renderer contains zero knowledge of any specific operator.
No if (material.is_glass). No AddDirectionalLight(). The renderer finds a ray-surface intersection, builds a shading context, and calls material->Process(Ctx) through an abstract base pointer. Reflection and refraction re-enter the tracer through callbacks on the context.
This is the RenderMan lesson — the shading operator architecture that Pixar introduced decades ago. Almost nothing since has maintained this discipline. Game engines hardcode material models for performance. Real-time renderers bake assumptions into their shader pipelines.
Aurora keeps it clean. Anyone can add a material or light model without touching — or having — the renderer source. A third-party graphics programmer, a customer's technical artist, or an AI agent can drop in a new operator and it works. 88 operators currently instantiate through the registry.
SPIR-V and Vulkan RT — the architecture matched the hardware
From the SPIR-V design document, four pillars:
1. EPL to SPIR-V compiler backend. The same AST/IR that already feeds x64 and ARM64 code generators gets another backend: SPIR-V. It's another code generator, not a new language.
2. GPU-compatible operator subset, enforced at compile time. A gpu_allowed / gpu_denied attribute system checks operator compatibility before the code runs. You learn at compile time that an operator can't run on GPU — not at 3 a.m. during a production render.
3. Hybrid dispatch. The renderer asks per frame: "is this material's whole operator graph GPU-compatible?" GPU runs what it can. CPU transparently runs the rest. No manual partitioning.
4. Vulkan RT pipeline maps to operator types 1:1. This is the one that matters most. VK_KHR_ray_tracing_pipeline stages — raygen, closest-hit, any-hit, miss — correspond directly to Aurora operator categories. Every other engine adapts its shading model onto hardware RT. Aurora's model was already shaped like the hardware pipeline — because both descend from the same rendering theory.
The architecture was designed before the hardware existed. When the hardware arrived, it matched.
Vector operations for AI — the same types, different silicon
Two distinct claims, and they're worth keeping separate:
Compiler-level SIMD spatial types. When you write T1 * T2 on two SE3 transforms, the compiler emits the AVX2+FMA instruction sequence for the transform composition. No function call. No library dispatch. No "call out to GLM or Eigen." The operation compiles to the SIMD registers directly.
Backend directives route matrix work to the right silicon. Source-level attrib(backend, [gpu_cuda, gpu_spirv, cpu]) with a precedence ladder — per-instance, per-method, per-class, project rules, user defaults, auto. The gpu_cuda backend reaches NVIDIA tensor cores via PTX, with access to cuBLAS/cuSPARSE/cuDNN.
The consequence: the same mat4 type is a bone transform in animation, a camera matrix in rendering, and an inference weight tensor in an ML-driven material — and the routing decision is a source annotation, not a rewrite. An ML-driven material (a layer operator running on tensor cores) is a natural expression of this architecture, not an integration project.
What works today, what's designed, what's next
This audience checks claims. Here's the honest status:
Working today:
- CPU ray tracer written from scratch in EPL: BVH (TLAS/BLAS), Möller-Trumbore intersection, 4x4 anti-aliasing, shadows, mirror reflection, Fresnel glass refraction — all shaded through operator dispatch
- 88 operators instantiate through the registry
- Shipped render: a 48-frame seamless 1080p animation at 4x4 AA
- fp64 throughout — EPL's
floatis 8 bytes. For engineering, simulation, and CAD this differentiates against game engines that are fp32 to the core - A 12 GB/frame memory leak was traced by instrumenting the allocator (not guessing) to two sites in the executor that never freed spatial variant storage. After the fix: flat at ~100 MB. Same image, byte-for-byte.
Designed and specified (not yet built):
- SPIR-V backend and Vulkan RT hybrid dispatch
- Robotics / Pinocchio integration (type mapping is analyzed; integration code is not written)
- CUDA/PTX backend for tensor cores
- Distance-hybrid rendering — fp64 CPU for nearest objects, fp32 GPU for far field, composited
Roadmap:
- Render farm orchestration
- Embedded firmware (STM32H7 — the robot arm you simulate and the firmware driving it in one project)
- Living NPCs — every NPC as a Foundation Model instance with persistent per-player memory, goals, tools, and coordinator-orchestrated swarms
- Plan-as-source-of-truth modeling — the plan is the canonical generative program; the mesh is a cache
The real argument
The four named pillars — rendering, robotics, GPU shading, AI matrix work — are not a feature list. They are four consequences of one decision: put the spatial algebra in the compiler.
When the math is in the language, every domain that uses that math becomes a backend, not an integration. The renderer doesn't know about the robot arm. The robot arm doesn't know about the shader. The shader doesn't know about the inference engine. They all know about se3, motion, force, mat4 — and that's enough.
Every other platform will keep maintaining four copies of the same linear algebra, four type systems for the same 4x4 matrix, four serialization formats for the same scene graph. We'll maintain one.
The estimate for Aurora to reach full feature parity with established engines is roughly 100-160 development sessions. That's honest, and we say it. What makes it tractable is that the language, the database, the compiler, the spatial types, and the operator architecture already exist. The foundation is not hypothetical — it's running, rendering, and shipping frames.
Aurora is built on the Elastic Platform — the same compiler (EPL), database (Orion DB), and protocol (TProtocol) that powers 9 shipping products. We built the compiler, database, protocol, HTTP server, and GUI framework from scratch. 20 AI agents build it daily.
More: elastcode.com/investors