game engine WIP written in odin
The engine focuses on providing a simple and relatively powerful game engine interface for programmers to interact with, and it attempts to be interactive and extensible in every stage.
The project is semi-large, ~15K LOC.
| Indirect Environment Lighting Including ambient and specular occlusion |
Direct lighting |
|---|---|
![]() |
![]() |
| Clearcoat test Left: Fully reflective Middle: Rough Right: Same as rough middle but with a second reflective layer, requiring multiple reflectance evaluations with energy conservation |
|---|
odinprogramming language is installed, the current tested release isdev-2025-09:42c2cb89b.- A modern
OpenGLversion is installed (at least 4.3).
If you wish to build eno, you can do:
- Build the demo directly using
odin
odin build ./src/eno/demo -out:bin/eno-build
, adding .exe on windows, and provided bin/ exists.
- Use the build script
runeno.sh.
./runeno.sh -h gives the usage, the arguments -b -r -t -d -p give functionality on what you are building and how, including testing and debug symbol generation.
hello@hello:../eno$ ./runeno.sh -h
Usage: runeno.sh [
-b (odin build),
-r (odin run),
-t (odin test),
-m (enable memory tracking for testing),
-d (include debugging symbols),
-p (build subpackage instead of the whole of eno, example: ./runeno.sh -p ecs)
]
runeno.sh -r -p demo will run the demo.
SDL2.dll (Windows) / SDL2.lib may need to be added to bin/ (or the location of your binary), these can be obtained from {odin installation dir}/vendor/sdl2.
- When running the demo, the UI will open which may be behind the main window
- WASD controls are availabile, with cntrl -> down, space -> up, and m -> disable/enable mouse cursor
A list of features detailing what eno currently implements:
- Windowing using SDL2 (
windowpackage ) - Archetypal Entity Component System with a powerful query interface where entity component data is stored tighly packed (
ecspackage ) - GLTF model/scene loading with PBR material support (
resourcepackage ->gltf.odin). There is an issue with loading certain models which I haven't gotten around to fixing yet - Controls using a centralized hook structure (
controlpackage ) - OpenGL renderer backend (
renderpackage ) - Physically based rendering workflow supporting normal mapping, all glTF standard PBR materials, and the KHR_Clearcoat and KHR_Specular extensions
- Central resource manager with hashing and reference counting to share/store shaders, material permutations, vertex layout permuations etc. (
resourcepackage ) - Liberal render pass interface with a general
renderhandler - Image based environment indirect lighting - supporting physically based rendering, taking incoming light from a preloaded image environment (and precomputed BRDF components)
- Dear Imgui integration, with a UI element interface to create UI elements or use those available
- Ambient occlusion calculated in screen space (SSAO), with runtime bent normal calculation. Bent normals follow the Klehm2011 bent cones description, and are packed with the occlusion term. A seperated cross bilteral filter is then done to remove noise while preserving edges and the cone variance in the bent normals
- Specular occlusion using the bent cone variance and bent normal from the SSAO pass. This follows the Jimenez2016 specular occlusion (cone-cone approximation) term, using the solution given in Ambient Aperture Lighting Oat2006. This has limitations when using SSAO for the occlusion and bent normal calculation, as the (very typical and expected) SSAO artifacts are exacerbated when the specular cone leaks past the perfect visibility hemipshere - I have an experimental correction for this which can yield good results
- Custom file explorer UI element - ex. for picking texture, model URIs
What I'm working on:
- UI improvements, including resource inspection and a scene hierarchy
Things I'd like to implement if I have the time:
- Clustered forward rendering to support a large amount of lights on the screen
- Pre-render geometry processing for tangent approximations with
mikkt; an unweld ->mikkttangent generation -> weld process
Far reaching:
- Vulkan backend
- MoltenVK for Mac
The demo files provide an idea of how the engine could be interacted with by a programmer, this includes the usage of before_frame and after_frame function ptrs, configuration of controls, addition of ui elements, etc.
Game engines are complex layers of abstraction, often sacrificing user(developer) control in the development of internal systems or outwards functionality. To balance extensibility, developer control, and simplicity, I've opted to give internal functionality within layered abstractions. This means that the developer can choose the layer of abstraction they wish to work with, and that this is supported as defined behaviour by the source. Rendering for example has a render pass and pipelining interface which gives direct control of what is rendered in the central render procedure, but is heavy to configure. As such it has a facade which exposes existing implementations of SSAO, G-Buffer setup etc. The UI also instead of having a set UI like most engines exposes a UI element interface with some obvious UI elements provided. Developers have the ability to implement their own UI elements, potentially taking reference from the existing UI elements.
Most of the engine (at least recent changes) attempts to follow this idea, improving the usability despite the engine being smaller.



