K.Engine is a WIP custom game engine written in C++.
You can test the current development build here. The build folder holds a current build of the repository.
.kscene text format)ScriptBehavior behaviours with authored parameters, native + web)| Module | Contents |
|---|---|
K.Engine.Core |
Application loop, window, layer stack, ImGui editor shell, demo |
K.Engine.Graphics |
Batched renderer (quads/cubes), DrawMesh for terrain, camera, lights |
K.Engine.Physics |
Shapes, collision manifolds, rigidbodies, PhysicsWorld (broadphase + solver), raycasts |
K.Engine.Terrain |
HeightField, LOD TerrainChunk meshing, Terrain (noise gen + sculpting) |
K.Engine.Common |
ECS, math, events, QualitySettings dial, Transform, scene components, noise |
K.Engine.Input |
Keyboard/mouse polling, platform window |
K.Engine.Editor |
Scene serializer (.kscene) + C++ scripting (ScriptBehavior, registry, built-ins) |
The app is an editor over an ECS world. Every world item is an entity with
components (Transform, Prop, LightSource, Rigidbody, Collider,
Script, …); the Explorer lists them and the Properties panel edits
them. Play snapshots the world and runs physics + scripts; Stop restores
the snapshot, so editing is always non-destructive. File → Save/Open Scene
serializes the world (and environment) to a .kscene text file.
Game logic lives in C++ behaviours — engine for the game, not games for the
engine. A behaviour derives from KDot::ScriptBehavior, uses the KDot
namespace, and is registered by name; attach it via a Script component. Because
behaviours compile into the binary, the same code runs on native and web
(no separate scripting VM):
class Spin : public KDot::ScriptBehavior {
void OnUpdate(float dt) override {
if (auto* t = GetTransform())
t->rotation = glm::angleAxis(glm::radians(90.0f * dt),
glm::vec3(0, 1, 0)) * t->rotation;
}
};
KE_REGISTER_SCRIPT(Spin, "Spin"); // now selectable in the Script component
Built-ins: Spin, Hover, Patrol (see K.Engine.Editor/src/Script/BuiltinScripts.cpp).
Everything detail-related reads from one master value in QualitySettings
(K.Engine.Common/include/Core/QualitySettings.hpp), in the range [0, 1]:
KDot::QualitySettings::Get().SetFidelity(0.65f); // project default
| Fidelity | Render dist | Terrain chunk edge | Max LOD | Shadows |
|---|---|---|---|---|
| 0.00 (Iruna) | 120 | 17 | 2 | off |
| 0.65 (K.Engine) | ~1730 | 65 | 5 | 2048 |
| 1.00 (Elden) | 2600 | 129 | 6 | 4096 |
Changing it at runtime (there’s a slider in the demo’s Inspector panel) re-derives render distance, LOD bands, terrain density, shadow map size, light budget and texture sampling, so a settings menu only ever touches one call.
Rigidbody + Collider (box / sphere) components stepped over the ECS.LightManager (plain data) and are turned
into shader uniforms by the renderer.GrassField,
density + view distance from the fidelity dial, skipping water/steep/rock);
the GPU draws them in one instanced call, doing the billboarding, taper,
wind sway and distance fade in the vertex shader.Renderer::Begin2D/End2D switch to an orthographic, unlit,
alpha-blended mode for HUD/sprites (the demo draws a crosshair, status bars,
and a cursor brush marker).Picking::ScreenToRay) and queries PhysicsWorld::Raycast.Demo controls: WASD fly · right-drag look · scroll zoom ·
left-click sculpt (hold Shift to lower) · R re-drop the ball.
The engine now builds on both the web (Emscripten/WebGL2) and native desktop (GLFW + GLEW, OpenGL 3.3 core). Platform differences are isolated:
Platform/Platform.hpp — platform detection (KE_PLATFORM_WEB/WINDOWS/LINUX/MACOS).Platform/GL.hpp — one place for the GL + window-system includes.Window::Create returns a JavascriptWindow (web) or DesktopWindow (native);
the main loop is emscripten_set_main_loop on web and a plain while loop on desktop.ShaderUtil rewrites them to
GL 3.3 core on desktop on the fly.The gameplay systems (terrain, physics, ECS, config, math) are graphics-API
agnostic, so the remaining work is backend-only, behind the RHI seam
(RHI/ — Device/Buffer/Pipeline interfaces + GraphicsAPI.hpp, selected
via the KE_BACKEND_* CMake options):
RHI/GLDevice); GrassRenderer
ported onto it (buffers + pipeline + std140 uniform buffer, zero direct GL).rhi::Device for Vulkan; port the remaining renderer.
Native high-performance desktop path.rhi::Device for WebGPU; move the web target onto it.build.batbuild/bin/K.Engine.html in your browserInstall the dependencies, then a normal CMake build:
sudo apt install build-essential cmake libglfw3-dev libglew-dev libgl1-mesa-devbrew install cmake glfw glewvcpkg install glfw3 glew (configure with the vcpkg toolchain file)cmake -S . -B build-native -DCMAKE_BUILD_TYPE=Release
cmake --build build-native -j
./build-native/bin/K.Engine
The platform-agnostic modules (Physics / Terrain / Common) can also be compiled
and unit-tested with a normal host compiler (e.g. g++ -std=c++17 -I glm ...),
independently of any graphics backend.