top of page

Mini Minecraft

Developed a 3D voxel game engine in a team of three using OpenGL, C++, GLSL. I personally implemented shadow mapping with Percentage Closer Filtering, procedural terrain generation and biome blending with various noise functions, texturing, and animation.

Highlights Video

Shadowmapping

I implemented shadow mapping by writing to a shadow map texture and sampling it later to determine where shadows should be created. I stored the orthographic depth from the sun’s position.

To improve the shadow mapping, I focused on:

  • Increasing the texture image size and using a higher decimal approximation for the z-value

  • Integrating the sun's movement with the player and day-night cycle, alongside teammates’ implementations.

  • Applying Percentage Closer Filtering to blur the shadow edges:

Clear Edges (Single sampling)

Blurred Edges (Percentage Closer Filtering)

Biomes/Terrain Generation

I implemented a system to blend a 3x3 grid of biomes, with each biome blending smoothly with its 4 closest neighbors based on its position on the grid. I used Perlin noise to control the transitions between biomes and performed remapping to ensure a more even distribution. Each biome is uniquely textured based on height.

Some biomes I implemented are:

  • Mountain

  • Grassland

  • Desert

  • Steep Canyon

  • Snow Pitfall


Additionally, I created floating islands by curving out the islands and their bottom layers using Perlin noise, then generating biomes on the top layer.

Texture / Texture Animation

To implement texture mapping for the blocks, I organized block data and their corresponding texture coordinates (256x256) in a map. These texture coordinates were then passed to the shader, where I utilized texelFetch to accurately sample the texture at the specified coordinates.

For animated blocks, such as lava or water, I applied an offset to the texture coordinates in the fragment shader. This offset dynamically shifts by 1 to 16 pixels over time, creating the desired animation effect.

A time variable, incremented with each call to tick(), was used to drive these animations.

bottom of page