ExoEngine: Writing a 3D Engine in C# Before Anyone Thought That Was a Good Idea

Back to Blog Listing

ExoEngine: Writing a 3D Engine in C# Before Anyone Thought That Was a Good Idea

After my Visual Insights internships, I went deep on C# and wrote ExoEngine3D to test whether managed languages could handle real-time 3D graphics.

Ben HoustonJune 18, 20256 min read

In the summer of 2001, I was on the beta of Microsoft Visual Studio .NET, one of the first public releases of C#. I was finishing my second internship at Visual Insights in Toronto, building DARPA battlefield visualization software in Java, and I had a specific frustration I couldn't shake.

Java had no structs.

In 3D graphics, your most-used types are small fixed-size math primitives: Vector3, Matrix4, Quaternion. In C++ these live on the stack: cheap to allocate, cheap to copy, no garbage collector involvement. In Java, everything is a heap-allocated object. Every new Vector3() is a heap allocation. In a real-time renderer you're creating and discarding these millions of times per frame, which means constant GC pressure on exactly the types you need to be fastest. Java's memory model fought the requirements of real-time graphics.

C# had structs, stack-allocated value types. You could define Vector3 as a struct and get the same semantics as C++: stack allocation, value copy on assignment, no heap pressure. That made C# interesting for 3D work. It gave managed code the memory semantics Java lacked for math primitives.

I came back to Ottawa for my fourth year at Carleton with a question I wanted to answer: could C# hold up as a language for real-time 3D graphics? Everyone in my fourth-year computer graphics course wrote their engine in C++. I wrote mine in C#.

Why This Question Mattered#

This was late 2001. C# 1.0 had just shipped. The conventional wisdom said managed languages, with garbage collection, runtime checks, and abstraction away from the metal, were unsuitable for performance-sensitive work like real-time graphics. Engine programmers wrote C++. That was the rule.

My argument was that the rule rested on a false assumption: that the CPU was doing the heavy lifting. By 2001 that was no longer true. The GPU handled rendering: rasterization, texture sampling, shading. The CPU handled coordination: scene graph traversal, visibility determination, state management, game logic. For that work, C# was more than fast enough. Structs solved the math primitive problem, removing the last serious performance objection.

I had also spent two summers working in Java at Visual Insights. Java was managed and garbage collected, and it had served well enough for a serious real-time 3D application used by US military commanders. The performance ceiling for managed languages was higher than the C++ community acknowledged.

By the end of the project I had written roughly 600KB of C# code. My conclusion, published on C# Corner and Code Project in July 2002, was that C# could handle real-time graphics and might replace C++ for some demanding real-time work.

Unity proved that prediction out. It launched in 2005, used C#, and became the dominant game engine for independent and mid-size studios. It worked for the reason I had identified: the GPU does the rendering, the CPU does the coordination, and C# is fast enough for coordination while letting developers move faster than they could in C++. Structs kept the math primitives efficient. The rest followed.

What ExoEngine Did#

The engine, ExoEngine3D, source on GitHub, loaded levels from Worldcraft, the level editor used for Quake and Half-Life. Worldcraft outputs world geometry as sets of bounding planes defining the contours of solid objects, so the first task was converting those bounding plane sets into polygon faces. The resulting geometry was then optimized to remove hidden and redundant faces created by adjacent objects, and converted into a BSP tree, a binary space partition tree used for both collision detection and efficient visibility determination.

The rendering pipeline supported multiple shading modes:

  • Flat shading: simple, fast, faceted
  • Gouraud shading: smooth per-vertex colour interpolation
  • Phong shading (fake): viewer-dependent specular highlights, used on duck sprites to make them look rounded and shiny
  • Reflection mapping: used on the animated pond to get a convincing water surface

The demo scene was a simple outdoor environment with a pond, ducks, and a surrounding landscape. It looked modest by 2001 standards because the point was proving the architecture worked, not visual complexity.

ExoEngine

The Architecture: Three Layers#

The 600KB of code was split into three distinct layers:

ExocortexNative: a small C++ support library handling the lowest-level concerns: OpenGL bindings (using Lloyd Dupont's OpenGL/C# library as a base, with modifications) and TIFF image loading. The things that needed to be close to the metal stayed in C++.

Exocortex: a reusable C# library intended to carry across projects. This contained the mathematical foundation: OpenGL-compatible matrix, vector, and quaternion classes implemented as structs, as well as a Marching Cubes implementation. It also incorporated Exocortex.DSP, a separate open source C# library I wrote as part of my undergraduate research project, providing single and double precision complex number types, complex math, and 1D, 2D, and 3D Fast Fourier Transforms. Exocortex.DSP was released on SourceForge in early 2002 and found wide adoption, used in projects ranging from Math.NET to speech recognition systems to EEG signal processing frameworks. The library page is still live at ben3d.ca/dsp.

ExoEngine: the application-specific layer: the BSP tree, the level loader, the rendering pipeline, the entity system for animated objects like the pond and the duck sprites.

The Exocortex library layer became the most consequential part of the project. ExoEngine was a student engine, but the shared library became production infrastructure.

The Exocortex Library's Longer Life#

When I joined Frantic Films in Winnipeg after graduation, I brought the Exocortex library with me. It became the shared foundation for three separate commercial products:

  • Deadline: a render farm management system that became an industry standard in VFX and animation, later acquired by Amazon/AWS
  • Krakatoa: a particle rendering system capable of rendering hundreds of millions of particles, used by major film and VFX studios
  • Flood: a fluid simulator for production VFX

All three were originally C# .NET applications, all three shared the Exocortex math and infrastructure library, and all three shipped to professional users in the film and VFX industry. The library became Frantic Films' property in the process.

After I left Frantic Films in early 2005, I founded a company called Exocortex Technologies, named after the same concept, the idea of software as an extension of human cognition, but built on a new codebase. The original Exocortex library stayed with Frantic Films and its successors.


Source code and screenshots: github.com/bhouston/ExoEngine3D

Original 2002 article: C# Corner · Code Project