Mini-Minecraft
Real-time voxel game with procedural terrain and dynamic sky
Overview
For the final project of my Computer Graphics class, I worked with two teammates to build a real-time voxel game inspired by Minecraft. The engine was written in C++ with OpenGL and GLSL, with chunked voxel terrain, player traversal, dynamic environmental rendering, and shader-based post-processing.
My work focused on the visual systems that shape the world at a distance and the procedural systems that generate the terrain. I built the procedural skybox, day/night cycle, distance fog, ambient occlusion baking, snow and grassland terrain generation, cave generation, fluid-aware player physics, and the lava/water screen shaders.
Procedural Skybox
The skybox is driven by GLSL shaders and a continuously advancing time parameter. Rather than swapping static images, the shader interpolates between a small set of hand-authored color palettes for morning, daytime, sunset, night, and sunrise.
This gave the scene a controllable art direction while still keeping the lighting responsive. Sunrise and sunset are handled as palette blends, which made it easy to tune horizon color, zenith color, and overall atmosphere independently.
I also implemented distance fog in the shader to soften far terrain and reduce the harsh cutoff of voxel chunks. The fog acts as both an atmospheric effect and a practical composition tool, helping the terrain read at large scale without exposing the chunk boundary too aggressively.
Shooting Stars
The night sky includes procedural shooting star streaks generated from 3D Perlin Noise. The noise domain is stretched along the world Y axis, turning the noise field into thin, elongated strands rather than soft volumetric blobs.
By thresholding and animating this field over time, the shader produces intermittent streaks that feel embedded in the sky rather than placed as individual billboard sprites.
Ambient Occlusion
I implemented block-based ambient occlusion by checking surrounding blocks for each vertex and baking the result into the vertex color before sending the mesh to the GPU.
The AO value is packed into the alpha component of the vertex color:
AO = 1.0 -> alpha flag = 1 -> color.a = 1.1
AO = 0.4 -> alpha flag = 0 -> color.a = 0.04
This encoding let the shader recover both the occlusion state and intensity from a compact vertex attribute. It also kept the runtime shading cost low, since the expensive neighborhood checks happen during mesh construction instead of per fragment.
The result gives block corners and contact areas more depth, making the voxel terrain read less flat while preserving the simple Minecraft-like material style.
Terrain And Caves
I was responsible for generating the snow and grassland terrain using noise-based height maps. The terrain generator samples procedural noise to produce broad elevation changes, then assigns surface materials based on biome and height rules.
For underground spaces, I generated caves with 3D Perlin Noise. Sampling a volumetric noise field made it possible to carve connected tunnels and cavities through the terrain instead of relying only on 2D height data.
Water, Lava, And Post-Process Shaders
I also implemented player physics responses for water and lava volumes. Entering these blocks changes how the player moves and how the screen is rendered.
The water and lava post-process effects are screen-space shaders layered on top of the rendered scene. They provide immediate feedback when the player enters a fluid volume and help distinguish the physical state change from normal traversal.