3D Development April 2026

Mini Minecraft

A feature-complete Minecraft-style 3D world engine built from scratch in C++ and OpenGL — 7 procedural biomes via layered Perlin/FBM noise, 3D cave systems, PCF shadow mapping, screen-space reflections, vertex ambient occlusion, a day-night cycle, multithreaded chunk streaming, and a predator-prey NPC ecosystem with A* pathfinding on a thread pool.

Role

Graphics & Systems
Engineer (Group of 3)

Timeline

April 2026

Tools

C++ OpenGL GLSL Qt Multithreading

Platform

Qt Creator 18.0.1

A full 3D voxel world engine, built from first principles

Mini Minecraft is a semester-long group project for CIS 4600 (GPU Programming) at Penn. The goal was to build a faithful recreation of Minecraft's core engine — procedural world generation, real-time rendering, player physics, and interactive terrain — using only C++17, OpenGL 3.3, and GLSL with no game engine or rendering framework. The final codebase spans 26 C++ source files and 13 GLSL shaders.

The project ran across three milestones, with each of three teammates owning distinct systems per milestone. My contributions spanned 7-biome procedural terrain generation, 3D cave systems with post-process fluid overlays, and a full render pipeline upgrade: PCF shadow mapping, screen-space reflections, vertex ambient occlusion, distance fog, Blinn-Phong specular highlights, and a day-night cycle.

Generating an infinite world across biomes

My first milestone was procedural terrain generation. The world supports 6 distinct biomes blended seamlessly using large-scale noise.

  • Grassland & Forest — Voronoi-based hill effect produces soft rolling terrain. Surface blocks are DIRT with GRASS on top; forests add procedurally placed tree assets.
  • Mountain & Rocky variants — fractal Brownian motion on Perlin noise with an abs() warp produces sharp jagged peaks of STONE capped with SNOW above Y = 200. Rocky Plains and Rocky Mountains use the same FBM stack at reduced amplitude for flatter stone fields.
  • Desert & Snowland — desert uses a low-amplitude Perlin field surfaced with SAND and beach blending at water edges; snowland uses the grassland height field with SNOW surface blocks and ice-covered lake fills.
  • Biome blending — a large-scale Perlin noise value, remapped to [0, 1] and run through smoothstep(0.25, 0.75), acts as the interpolation weight between adjacent biome height fields, creating clear zones with smooth transitions.
  • Block rules — Y = 0–128 fills with STONE; biome surface occupies Y = 128–255; empty columns between Y = 128–138 fill with WATER for lakes and coastlines.
Grassland coast with beach and mountains

Grassland biome — Voronoi hills, sandy coastline, distance fog

Biome border — stone mountain meets grassland

Biome blending — stone mountain meets grassland via smoothstep interpolation

Shoreline and lake coastline

Water generation — empty columns between Y=128–138 fill as lakes

Grassland terrain with water lake

Screen-space reflections — terrain and sky reflected on water surface via view-space ray marching

3D noise caves, fluid physics, and a post-process pipeline

The second milestone added underground depth to the world and a full post-process rendering pipeline.

  • 3D Perlin caves — Perlin noise extended to three dimensions with 8 surflet contributions per grid cell and trilinear interpolation. Every block below Y = 128 where the noise value falls below zero is carved to EMPTY. Caves below Y = 25 fill with LAVA; all Y = 0 blocks become unbreakable BEDROCK.
  • Fluid physics — WATER and LAVA are non-solid. The player moves at 0.8× speed inside fluid and swims upward on Spacebar. Fluid detection reads both body and camera position for correct immersion state.
  • Post-process pipeline — the scene first renders to a framebuffer; a second pass draws it onto a fullscreen quad and applies a blue tint (WATER) or red tint (LAVA) overlay based on camera position, simulating underwater vision.
Underground cave with lava lake

3D Perlin caves — blocks below Y=128 carved by negative noise; lava fills below Y=25

Shadow mapping, SSR, ambient occlusion, and more

The final milestone was a full upgrade to the rendering pipeline, pushing visual quality significantly beyond the base engine.

  • PCF shadow mapping — the scene renders from the directional light's orthographic view into a depth-only framebuffer. Terrain fragments transform into light clip space and compare depth using a 7×7 PCF kernel with slope-scaled bias to eliminate acne and Peter Panning. Texel snapping stabilizes the projection as the camera moves.
  • Screen-space reflections (SSR) — opaque geometry renders into a floating-point position buffer in view space. Water fragments compute the reflected ray in view space, project it into screen space, and ray-march against stored scene positions to find hits. Reflected color blends with water shading using Fresnel-based weights and shoreline masking.
  • Vertex ambient occlusion — neighboring block occupancy is sampled per face vertex during chunk VBO generation, producing a per-vertex AO factor baked into the interleaved 64-byte vertex layout. The fragment shader multiplies final lighting by this factor to darken corners and block intersections.
  • Day-night cycle — sun position, directional light color, shadow projection, fog color, and sky gradient all update together each frame to produce a continuous 24-hour cycle.
  • Distance fog — a smoothstep fog factor interpolates terrain color toward the sky color based on world-space camera distance, tracking the dynamic sky color through the day-night cycle.
  • Blinn-Phong specular — per-fragment specular highlights tuned per material: water (glossy), snow (matte), lava (emissive term added).
Mountain at dusk with sun bloom

Render pipeline — shadow mapping, Blinn-Phong specular, distance fog, and sun bloom post-process

Built across three milestones with a team of three

Beyond my own systems, the project's full feature set was built collaboratively:

  • Angelina — efficient terrain chunking with interleaved VBOs and face culling (M1); multithreaded chunk streaming with BlockTypeWorkers and VBOWorkers and mutex-protected queues (M2); view-frustum culling, GPU resource stability, chunk update batching, day/night cycle, procedural grass color, fluid distortion overlay, procedurally placed biome assets, and sound (M3).
  • Seth — player physics with InputBundle-driven movement, flight/ground modes, grid-march collision, mouse-look, and block add/remove (M1); texture atlas UV mapping, opaque/transparent VBO split, and animated water/lava shader with alpha blending (M2); A* pathfinding on a PathfindingWorker thread pool using a lazy-deletion min-heap with PathSnapshot isolation for thread safety, predator-prey NPC ecosystem with 3 roles and 6 mood states (IDLE/WANDER/HUNT/STALK/CHASE/FLEE), OBJ model rendering, a pre-load screen, and lossy chunk streaming with LRU eviction (M3).

What building a graphics engine teaches you

Working at the level of raw OpenGL — managing your own framebuffers, writing every shader, coordinating GPU state by hand — forces an understanding of the rendering pipeline that abstracted engines hide. Debugging shadow acne required understanding why floating-point depth comparisons fail at grazing angles. Getting SSR to not flicker required understanding how screen-space ray marching degrades at the edges of the view frustum.

The multithreading constraint was equally instructive. Any time a VBOWorker tries to call OpenGL on a non-main thread, the context is invalid and the call silently fails or crashes. Designing the pipeline around that constraint — workers compute data, main thread uploads — made the architecture cleaner than a naive approach would have been.

Most importantly, the project made abstract concepts from class concrete: noise functions that looked like math on slides produced actual mountains; the shadow map depth texture, once visualized, made the algorithm immediately legible. Building the whole stack yourself, even at high cost, produces a level of understanding that using a game engine simply cannot.