Transparency
As you can see, the current handling of transparency presents some issues, especially when dealing with overlapping faces. This can be resolved using depth peeling, which I plan to experiment with in the future.
This voxel renderer, heavily inspired by Minecraft, was built from scratch using C++20,
Vulkan + SDL, and GLSL. The project is built on RealCore and my own Vulkan abstraction, Real3D,
which, while not perfect, taught me a great deal about graphics programming and C++ design.
The renderer implements several aspects of Minecraft’s visuals, including random terrain
generation, transparency, sprites, and animated textures.
Working on this project sparked my interest for graphics programming and gave me hands-on
experience with low-level rendering. I’m eager to continue improving this renderer, refining
Real3D, and exploring more advanced Vulkan techniques. I have many additional graphics projects
planned and look forward to expanding my skills further.
You’ve probably heard of Minecraft, the iconic sandbox game where players can build virtually anything they imagine. Its terrain is made of cubes arranged using a noise algorithm, and the world is divided into multiple chunks (meshes). For performance, only a limited number of chunks are rendered at any time. On my laptop, my Minecraft clone ran smoothly at 60 FPS with a render distance of 12 (25 × 25 chunks). As the player moves, new chunks are generated while distant chunks outside the render distance are removed. All progress in a save is preserved seamlessly.
Real3D was built by following the Vulkan Tutorial. The version the Minecraft clone was built upon was created in the course of 12 weeks. The engine of course handles everything render related, and comes with some handy components, like a camera component and a mesh component. There is also an option to load meshes, textures and shaders. Materials with custom pipelines can also be created by the user and applied to any mesh. Frustum culling using AABB is also implemented in the engine for a better performance. Sadly I didn't find the time to fully include ImGui in the project yet, but this is on the top of my todo list.
Some of notable features are transparency (water, leaves, flowers), animated textures (water),
sprites (flowers), procedurally generated terrain using simplex noise, dynamic meshes
and loading/saving of chunks.
Transparency was definitely the hardest to implement, I chose to
sort the faces of the transparent meshes from furthest to closest to the player,
but that came with its own flaws. I later learned about depth peeling, but I didn't have the
time anymore to implement this. I am very interested in this subject and have done already some research,
and would love to build a project around this. As mentioned, meshes in Real3D are dynamic, there can
be vertices added and removed during rum time, so the player can place and destroy blocks wherever
it wants.
Chunks are stored in a binary ,
I found it quit clever and fun to mess with this. Every chunk has one file, where its stores all the
blocks that have been changed. The position and type of the block are all mashed in a couple of bytes
for maximum efficiency.
As mentioned before, improving and learning more about transparency in graphics programming is definitely a priority for me. I found it quit intriguing that such a simple thing as transparency that we don't even think about in real life, can be so difficult to add on to our screens. I also wanted to experiment more with shaders, as this project lacks a bit of those. Dynamic lighting is also something that I could experiment with.
As you can see, the current handling of transparency presents some issues, especially when dealing with overlapping faces. This can be resolved using depth peeling, which I plan to experiment with in the future.
The water shader uses a larger sprite and a time parameter to create an animated effect by switching textures.
The mesh component is dynamic, allowing vertices to be added or removed during runtime. This means the player can place and destroy blocks in any chunk.
Chunks are created when in range and deleted when out of range. Placed and destroyed blocks are saved to a file to ensure your progress is preserved.