A voxel engine written from scratch in C++ and Modern OpenGL. This engine features infinite terrain generation, dynamic chunk management, fundamental physics (AABB collision) and voxel interaction (raycasting).
It is designed as a foundational tech demo for voxel-based games, implementing core mechanics similar to Minecraft Alpha.
- Procedural Generation: Infinite 3D terrain generation using 3D Perlin Noise.
- Chunk System: Dynamic mesh generation with optimized face culling.
- Infinite World: Chunk loading and rendering based on player position.
- Physics Engine:
- Gravity and jumping.
- Axis-Separated AABB Collision Detection (sliding along walls).
- Ghost Mode (Flying) vs. Walking Mode toggles.
- Interaction:
- Raycasting: Precise block selection using the DDA (Digital Differential Analyzer) algorithm.
- Destruction: Break blocks instantly with visual updates.
- Construction: Place blocks on specific faces of existing voxels.
- Block Selection: Hotbar system to swap block types.
- Visuals:
- Texture Atlas support with correct UV mapping.
- Wireframe Selection Box highlighting targeted blocks.
| Key / Mouse | Action |
|---|---|
| W / A / S / D | Move Player |
| Space | Jump (Walk Mode) / Fly Up (Ghost Mode) |
| Left Ctrl | Fly Down (Ghost Mode only) |
| Left Shift | Sprint (2x Speed) |
| C | Toggle Mode (Ghost/Walk) |
| Left Click | Destroy Block |
| Right Click | Place Block |
| 1 / 2 / 3 | Select Block (Grass / Dirt / Stone) |
| ESC | Exit |
- Language: C++20
- Graphics API: OpenGL 4.5 (Core Profile)
- Windowing: GLFW
- Extension Loader: GLAD
- Mathematics: GLM
- Texture Loading: stb_image
- Noise Generation: stb_perlin
- CMake (3.14+)
- C++ Compiler (MSVC, GCC, or Clang) supporting C++20.
- Clone the repository:
git clone https://github.com/ernerdgn/voxel-engine.git cd voxel-engine - Create a build directory:
mkdir build cd build - Generate project files using CMake:
cmake ..
- Compile:
- Windows: Open the generated
.slnfile in Visual Studio or runcmake --build . - Linux/Mac: Run
make
- Windows: Open the generated
The engine uses Axis-Aligned Bounding Box (AABB) collision detection. To prevent moving through walls and allow moving diagonally against a wall, the engine employs Axis-Separated Movement.
The Algorithm: Instead of moving the player directly to the target position, movement is splitted into three separate steps (X, Y, Z).
- Apply Velocity on X axis.
- Check Collision:
- Defining the player's bounding box (Width: 0.3m, Height: 1.7m).
- Sampling 12 points around the player model (Feet, Waist, Head).
- If any of these points intersect a solid voxel (
BlockID > 0), this considers as a collision.
- Resolve X: If a collision occurred, reset the X position to the previous safe value.
- Repeat for Z axis.
- Repeat for Y axis (Gravity).
To determine which block the player is looking at Digital Differential Analyzer (DDA) algorithm is used.
The Concept:
A 3D grid is composed of integer boundaries (
The Math:
Given a ray origin
-
Step Direction (
$step$ ):- If
$D_x > 0 \Rightarrow step_x = +1$ - If
$D_x < 0 \Rightarrow step_x = -1$
- If
-
Delta Distance (
$\Delta dist$ ): The distance the ray travels to cover exactly 1 unit on a specific axis.$ \Delta dist_x = \sqrt{1 + \frac{D_y^2}{D_x^2} + \frac{D_z^2}{D_x^2}} = \left| \frac{1}{D_x} \right| $
-
Side Distance (
$sideDist$ ): The distance from the origin to the first boundary.$ sideDist_x = (map_x + 1.0 - O_x) \times \Delta dist_x $
-
The Loop: Comparing
$sideDist_x$ ,$sideDist_y$ , and$sideDist_z$ .- If
$sideDist_x$ is the smallest, the ray hits an X-boundary first. - Increment map X by
$step_x$ . - Add
$\Delta dist_x$ to$sideDist_x$ . - Check map at new
$(x, y, z)$ . If solid, its a hit.
- If
- Ambient Occlusion (AO) for better depth perception.
- Save/load system (chunk serialization).
- Multithreaded chunk generation.
- Water and transparent blocks.