Simple Miner

Project Features:

Procedurally Generated Worlds Using Perlin Noise

In Simple Miner, the generation of all worlds was based on seeded Perlin noise. The world features of humidity, temperature, terrain height, rivers, oceans, beaches, ice, deserts, lightning, tree types, tree locations, village locations, desert temple locations, and cave pathing were all randomly determined based on the Perlin noise and the world seed. Because of the seeded worlds, each time a player loads into the game, they still see the same generated world that existed where they last left off. Also, because of the use of Perlin noise, the world is infinite and will never stop generating randomized terrain.


Optimized Rendering and Chunk Loading

In order to keep the FPS above 60 when rendering such a large world, an optimized rendering and chunk loading solution was created. This solution included hidden surface removal, vertex buffer rendering, and multithreaded amortized mesh rebuilding. Hidden surface removal only draws the faces of blocks that are exposed to air (the player has the ability to see this block’s face), therefore cutting the number of vertices being drawn per chunk by 95%. Vertex buffer rendering allowed for the vertices of a chunk to be cached on the GPU and only be repopulated on chunk creation or rebuilding. The multithreaded amortized mesh rebuilding restricted the total number of chunks being built per frame to a limited amount based on a chunk’s distance from the player. This priority order based on distance, keeps the FPS low while also maintaining the player experience. Because the chunk loading process is a heavy task for the CPU, multithreading was added to free up more CPU cores to help with the chunk loading and building process.


Block-Based Light Propagation

Due to the total number of blocks in the world that are constantly being generated and rendered, a traditional lighting technique would not have been feasible. Therefore, a custom light propagation algorithm was implemented by storing light data per block (if the light is dirty, and the indoor and outdoor light influence), and managing a dirty light block queue that assigns light values based on adjacently lit blocks and light sources. After all the light values have been calculated, the affected chunk becomes dirty and the mesh is rebuilt. When rebuilding the chunk’s mesh, each block’s light values are sent to the GPU in the red and green channel of the vertex colors so that the world shader can take these values and multiply them with the world indoor and outdoor light colors to calculate each pixel’s final color.