Berkay Orhan
WorkResearchExperienceAboutAskContact
Contact
← All projects

PROJECT / 2026

VoxelCraft

C++20 Voxel Game Engine

From-scratch Minecraft-inspired voxel engine with infinite procedural terrain, cave systems, a multi-pass rendering pipeline, and multithreaded chunk generation — all in C++20 and OpenGL 4.6.

stack
C++20 · OpenGL 4.6 · GLAD · CMake 3.28+ · GLFW 3.4 · GLM 1.0.1 · FastNoiseLite 1.1.1 · stb_image · nlohmann/json · BS::thread_pool · Google Test

Live site ↗

How it works

  1. seed
    noise for terrain and caves

  2. worker threads
    mesh chunks in parallel

  3. upload queue
    4 meshes per frame

  4. render passes
    shadows, SSAO, water

Voxel Engine surface exploration with procedural terrain

01 / Overview

A voxel game engine built from scratch in C++20, inspired by Minecraft. The core architecture splits engine subsystems (graphics, rendering, scene, atmosphere, settings) from game logic, with a state machine driving the full lifecycle: title screen, settings, world loading, and gameplay. The world generates infinite terrain using 3D Perlin noise with smoothstep biome blending (Plains, Mountains), carves spaghetti cave networks with natural water flooding, distributes ores at depth-appropriate strata, and cuts rivers using cellular noise. Rendering runs a multi-pass OpenGL 4.6 pipeline: shadow map depth pass with texel-boundary stabilization, half-resolution SSAO with a 64-sample hemisphere kernel and box blur, the main forward-lit pass with per-vertex AO and biome tinting, transparent water, volumetric clouds (2D and 3D modes), and instanced weather particles. Chunk generation and meshing happen on a thread pool, with GPU uploads capped at 4 per frame on the main thread. Blocks and textures are data-driven via a JSON-backed registry.

02 / Key features

  • –Infinite procedural terrain with 3D Perlin noise, biome blending, spaghetti caves with water flooding, ore veins, and cellular-noise rivers
  • –Multi-pass rendering pipeline: shadow maps (with texel stabilization to prevent swimming), half-res SSAO, forward-lit pass, transparent water, volumetric clouds, and weather particles
  • –Multithreaded chunk generation on BS::thread_pool with a 5-state atomic lifecycle — mesh data is computed off-thread and GPU uploads are rate-limited to 4 per frame
  • –Per-vertex ambient occlusion computed during mesh building by sampling 3 neighbors per vertex, plus a sky-light attribute so caves keep a fixed ambient independent of the day/night cycle
  • –Data-driven block registry loaded from JSON, with all block properties (solid, opaque, transparent, tinted) queryable at runtime
  • –Full game UI rendered in OpenGL: title screen, settings with live-adjustable graphics options, and a loading screen with progress bar — all using pre-rendered PNG text to avoid font library dependencies
  • –Google Test suite running in CI via GitHub Actions, covering ray math, chunk storage, heightmaps, block registry, and DDA voxel raycasting

03 / Challenges

  • –OpenGL is single-threaded, so chunk generation had to be split into a thread-safe compute phase and a main-thread-only GPU upload phase with a mutex-guarded queue between them — getting the 5-state atomic chunk lifecycle right without races or stalls took some iteration
  • –Shadow maps swim when the camera moves unless you snap the light-space frustum center to texel boundaries, which requires careful math in the projection setup
  • –Transparent water needs depth-write off and backface culling disabled, rendered strictly after opaques — and chunk boundaries need special handling to suppress water faces at seams between neighboring chunks
  • –The SSAO implementation required depth reconstruction from the depth buffer via inverse projection, a Gram-Schmidt TBN for hemisphere orientation, and range-checking to prevent distant surfaces from causing false darkening

04 / Solution

The threading problem drove the biggest architectural decision: mesh generation is split so ChunkMeshBuilder does all geometry work (iterating 65k blocks, checking 6 faces each, computing per-vertex AO) on worker threads, then hands off the vertex data via std::move to a queue. The main thread picks up finished meshes in ProcessPendingMeshes, capped at 4 GPU uploads per frame to avoid stalls. The render pipeline runs passes in a fixed order — shadow depth, SSAO at half-res, sky (depth-write off), opaque geometry, block selection wireframe, transparent water, then weather particles — with each pass managing its own FBO, blend state, and cull-face toggling. Shadow stabilization snaps the orthographic projection to texel boundaries. The cave carver uses an ICaveCarver interface so the strategy is pluggable, and the current SpaghettiCaveCarver applies altitude-based fade-out with surface protection to avoid breaking terrain above.

05 / Outcome

The engine runs at 60+ FPS with a 20-chunk render distance, handling infinite terrain generation, caves, ores, and rivers without noticeable pop-in thanks to the rate-limited async pipeline. The multi-pass renderer produces pretty convincing lighting — shadow maps, SSAO, and per-vertex AO combine well, and the day/night cycle with 8 lunar phases and volumetric clouds adds a lot of atmosphere. The modular architecture kept things maintainable as the codebase grew to ~340k lines of C++ and ~25k lines of GLSL. The test suite runs automatically on every push via GitHub Actions, covering the non-GPU subsystems.

06 / Screens

01 / 03

01Surface exploration with procedural terrain generation and biome transitions
02Spaghetti cave systems with natural entrances and water flooding
03General gameplay showcasing terrain, lighting, and block interactions

Berkay Orhan© 2026

WorkResearchExperienceCVBack to top ↑