Etcetera
Etcetera is a custom game engine written by myself and my friend and close collaborator Collin Eye. When we first started making games together we worked in Unity but we didn't enjoy the workflow and wanted direct access to graphics APIs, which prompted us to develop our own engine from scratch. We're just a scrappy team of two (Etal Games) and an engine is a tall order, so the bulk of the work so far has been on infrastructure and editing tools.
We have shipped one game with Etcetera (Changes), with another on the way soon (Art of Flight).
The engine itself is written in C++, has D3D12 and Vulkan graphics backends, and runs on Windows, Linux, and (formerly) OS X. Since it's just two programmers working on the engine for the forseeable future, the focus is to improve our particular and opinionated workflows.
Since we don't have a dedicated level designer on our projects we needed a flexible tool that allowed us to work quickly. We implemented a Constructive Solid Geometry (CSG) system that allows us to quickly sketch out indoor scenes. Our tool supports Union, Difference, and Intersection operations, arbitrary nesting of primitives, and outputs watertight meshes.
Once the main algorithm was working, the biggest challenge with the CSG system was building a set of tools that integrate well with our scene editor and were usable at interactive rates. We spent a lot of time architecting an immediate mode UI library that we have used for all sorts of internal tooling and in-game UI.
The focus on the CSG tool thus far has been on indoor scenes but we have plans to extend the tool to support terrain and roads.
One of the most useful features I've built for the engine is a preprocessor that generates a bunch of runtime-inspectable introspection data. For instance, we can mark up a struct in the code with STRUCT() (similar to Unreal's USTRUCT()) to generate a Schema that stores the name, byte offset, and types of all the fields. This data makes it easy to serialize data, write GUI editors, generate lists of all assets referenced in a scene, etc.
The preprocessor also generates a ton of boilerplate code that helps us avoid mistakes and work a lot faster. For instance, we can mark up any struct as an ASSET() and automatically generate an entry in the AssetType enum, a handle type so we can store a typesafe weak pointer to a loaded asset, and overloaded functions for loading assets of that type. We do a similar process for storing weak "persistent" functions that can safely survive after reloading game code at runtime. Essentially, our preprocessor acts as a more powerful standin for the macros we were used to from our experiments with LISP and Clojure (see below), and does more to increase our productivity than any other feature in the engine.
There's a ton more in the engine that I haven't mentioned yet: an audio mixer, scene/script editing tools, asset/level streaming, asset/code hot-reloading, prefabs, a 3D physics engine, and more! While there's so, so much left to do on the engine, we now have enough groundwork laid to turn an eye towards gameplay implementation.