I'm sharing my WIP game engine with the Nim community, as I believe it's in a state where folks could start building games using it. There are still some features I need to implement (such as release builds with static linking), but I figured I might as well share the code in case it is useful to others.
I'm currently in the process of constructing examples and authoring documentation. The engine supports macOS and Linux. I will get Windows support added soon, it just hasn't been a priority for me. Some features (like the fire propagation system for instance) are still under development and aren't ready for use yet. Also, I still need to invest a lot of work on the 2D side of things, as it's been less of a priority for me than features needed for 3D games.
Here's a quick rundown of the engine's features:
Core architecture
- Hot-reloadable plugin system: gameplay, examples, and the editor are all shared libraries the engine loads at runtime and
rebuilds in place without restarting.
- First-class C ABI plugin API — plugins are written in any language that can produce a shared library, not just Nim.
- Cross-platform application + windowing layer (macOS arm64 and Linux today; Windows scaffolded).
- Fiber-based job system with work-stealing scheduling for parallel task graphs.
- Lock-free queues, atomics, and a thread pool used throughout the engine internals.
- Virtual file system with mount points, alias resolution, and absolute-path passthrough.
- Hot-reloading asset pipeline: live file watching on mount points triggers re-imports of textures, shaders, scenes,
etc.
- Asynchronous, handle-based asset manager with reference counting and reload notifications.
- Project-wide custom allocator routing all Nim allocations through a high-performance heap.
- Built-in CPU/GPU profiler integration with zone instrumentation across engine + plugin code.
- Live shader hot-reload driven by compiled reflection metadata (pipelines rebuilt at runtime from YAML).
- Cross-backend graphics abstraction (Metal / GL / D3D11 / WebGPU) selected per-platform.
- In-engine logging, string utilities, temp allocator, pool allocator, and slug/handle primitives shared across
plugins.
Rendering
- Clustered forward+ renderer with a phase-based callback system so technique plugins can inject passes.
- PBR forward shading with point lights, directional lights, and cascaded shadow maps.
- Screen-space ambient occlusion with separable blur.
- Bloom (threshold + blur + composite) and FXAA post-processing.
- Outline / silhouette rendering pass.
- Depth + normal prepass exposed to plugins for screen-space effects.
- Skeletal mesh skinning on the GPU.
- Sky rendering.
- Vegetation rendering pass.
- Vector graphics renderer for 2D shapes, curves, gradients, and textured geometry.
- High-quality vector text rendering with signed-distance / Slug-style glyph shaders.
- Immediate-mode debug draw: lines, grids, axes, shapes, frustums.
- GPU compute particle system modeled after a familiar VFX graph: emission, simulation, distortion, mesh particles,
sub-emitters.
World, scene, and gameplay systems
- Entity-Component-System core with a registered-component model and scene-aware iteration.
- Scene plugin for loading, saving, and clearing ECS worlds.
- Editor camera (orbit + fly) and an ECS CameraComponent for in-game cameras.
- Rigid-body physics: world, bodies, box/sphere/capsule/mesh colliders, raycasting, ECS components.
- Skeletal animation with animation graphs, blending, and runtime playback.
- AI utility system: response curves and Decision Score Evaluators (DSE) for behaviour selection.
- Navigation: offline navmesh bake from level geometry plus runtime path queries.
- CDLOD heightmap terrain with LOD morphing and a node-graph terrain authoring layer.
- Cellular-automata fire propagation system layered onto terrain (fuel / heat / moisture / burn).
- Stylized water with Gerstner waves, depth-based colouring, shore foam, and physics interaction hooks.
- Spatial 3D audio: one-shots, managed sounds, sound groups, and listener positioning.
- Spline system with cubic-Bezier / Catmull-Rom sampling and rasterization.
UI and tools
- Layout-engine-based retained UI with vector-graphics drawing, exposed at both a low-level and high-level API.
- 2D scene system that bridges retained ECS entities with immediate-mode UI layout (Container / Label compositions).
- Full immediate-mode dev GUI with gizmos for translation / rotation / scale manipulation.
- In-engine editor plugin (loaded the same way as a game) with scene editing, a profiler view, and live entity
inspection.
- Native file-dialog support for asset import flows.
Build / dev experience
- Single-command build for engine, plugins, examples, and editor; debug and release flavours of each.
- Per-example build configs so an individual demo can be rebuilt in isolation.
- A growing library of demos (cube, physics, audio, input, GUI, ImGui canvas, debug draw, navigation, spline, jobs,
profiler, asset loading, game template).
--- Third-party dependencies
Graphics / windowing / UI
- sokol (app, gfx, time, glue, imgui backend)
- sokol-shdc + a YAML reflection pipeline
- cimgui (Dear ImGui C bindings) and ImGuizmo
- Clay layout engine
- vg-renderer (vector graphics core, Nim port)
- Slug glyph rendering
- stb_image, stb_truetype
- tinyfiledialogs
Simulation / gameplay
- Jolt Physics (via a C wrapper)
- Recast & Detour navigation (via a C wrapper)
- ozz-animation
- flecs ECS
- HandmadeMath (hmm)
- miniaudio
Asset import / runtime
- cgltf
- ufbx
- PhysFS
Infrastructure
- cr.h (hot-reload host)
- dmon (file watching)
- mimalloc (global allocator)
- Tracy (profiler)
- c89atomic
All the code and some of the third-party dependencies I've needed to fork an modify, are available here on my codeberg instance: https://codeberg.org/hahaitsfunny
I haven't figured out licensing on the engine yet, but most likely I'll aim for MIT or some sort of do whatever the hell you want with the code license, unless there's a strong incentive not to.
Thanks for checking out my project, and I hope at the very least it's a valuable learning resource for folks interested in game engine / game development.
Can you create some sort of bunnmark with rotation/color/direction per sprite + fps counter? How many sprites it will takes for 60fps on 1060/1070 (or any other mass hardware from steam statistics)?
Ask and you shall receive: https://codeberg.org/hahaitsfunny/frag/src/branch/profile-build-debug/examples/bunnymark/bunnymark_example.nim
As far as how many sprites - I'll have to get back to you. I haven't done any benchmarking, but the sprites are batched and as long as sprites belong to the same atlas they'll be drawn with a single draw call.
Tilemap with animations looks good. Have you support tmx/tmj maps with animated tilesets?
I don't have any examples but yes the plan is to support both. I'll add some examples soon demonstrating loading of tilemaps with animated tilesets from tiled and ldtk.
What about web platform support (as you support webgpu)?
It hasn't been a priority but certainly possible. It will take some work, but once I have things stabilized I will add support for the web.
Btw what is the name of this modern Iso-but-I-don't-give-a-fuck-perspective that is everywhere these days? (I mean the lack of diagonals where there should be some.)
I think people call it 3/4 perspective but I could be wrong. https://www.cs.cornell.edu/courses/cs3152/2020sp/lectures/15-Perspective.pdf
Ask and you shall receive:
Link is invalid, but i found proper one.
Looks good except manual pointer cast everywhere - its... not user friendly, needs some foolproof :)
the sprites are batched and as long as sprites belong to the same atlas they'll be drawn with a single draw call.
Sounds good.
I have my own 2d pet game engine: only wasm/emscripten + webgl2 (then webgpu)+webaudio, wrapping to webview on mobiles and electron on desktops.
You can compare your bunnymark results on your hardware with mine in web build
Build size: 49kb code + 1.4kb content bundle. I got 400k sprites at 60fps in small (500x300) window on 780m igpu (fillrate too low for fullscreen) and even more on rtx4060 + fullhd. All sprites renders in one drawcall (instancing).
Sources of my bunnymark (use translator for comments).
Users can also author plugins in any language that can produce a C API, not just Nim.
That's no excuse to avoid some basic type safety... Even C has type-safe pointers (more or less).
Offer a Nim API for the people who enjoy programming in Nim and offer a C API for the poor souls that can't use Nim. Or leave out the C API altogether because of costs vs benefits. Nobody wants a C API anyway, the Rust/D/Swift/Python etc people build their own wrappers on top of C and rightly so.
I view the C API as table stakes. The engine is plugin-based and C is much easier to deal with across DLL boundaries than Nim, at least historically. Maybe ARC/ORC has improved the situation, but I disagree that C APIs are useless. Almost every popular library in any language that people want to make available to users in other languages, gets one.
In Nim callbacks you can avoid env: pointer arguments by using .closure procs that keep type-safety.
Once the APIs are stabilized and I'm not hacking on the engine, I will write a Nim API for Nim users, but it's not my priority at the moment, especially since as far as I know, I am the only one using the engine presently.
Unrelated - going to work on the demo level for my game today and I will upload some videos showing my progress later.
especially since as far as I know, I am the only one using the engine presently, and APIs are in flux.
Exactly my point. You developed a feature nobody asked for, while weakening your foundation significantly. You lost type-safety at the interface boundaries where it's most important.
Exactly my point. You developed a feature nobody asked for, while weakening your foundation significantly. You lost type-safety at the interface boundaries where it's most important.
No one asked for any of what I created. I created it for myself to use - folks are free to use it if they want or they can choose not to - that is up to them. I haven't seen any other 3d Nim game engines created that feature hot-reloading and that are moddable / extensible via plugins. Plenty of folks over the years have asked for hot-reloading and moddable game engines. The choices are scripting or plugins and both have their tradeoffs.
Most game development related libraries that any game engine is going to depend on are written in C/C++ and expose C interfaces. I guess we shouldn't ever use any of them because they lose type-safety at the interface boundary?
I didn't say your feedback wasn't useful or productive - the Nim API is a good idea, but there's no point in writing one now when the APIs are changing, it would just be another interface to maintain. My foundation hasn't been weakened simply because I started with C interfaces. I can easily add a type-safe Nim layer on top of the C APIs.
Exactly my point. You developed a feature nobody asked for, while weakening your foundation significantly. You lost type-safety at the interface boundaries where it's most important.
At external interface boundaries, you would make a lot of checks and fuzzing anyway. Type safety doesn't matter when you are dlopen-ing a library and people just declare fake types.
Plugins and modding are now a key staple to grow a community around any game project and thinking on how to make it easy for people to contribute and extend is really a plus.
I'm working on the first mission that I plan to eventually release as a demo for the game.