A Minecraft clone rendered using ray tracing
The game has quite a few features one can expect a Minecraft clone to have, namely:
- ability to place and remove blocks and cubes (more on what cubes are later)
- player and liquid physics
- terrain and structures generation
- loading and saving multiple worlds
- ambient occlusion
- sky and block lighting
Although the feature set is borrowed from Minecraft, the implementation is quite different for a few reasons:
- fixed-point coordinates are used to represent positions
- the basic unit of structure is not a block but a cube
Cube is 1/2 the dimension of a block, so there are 8 cubes in a block. This subdivision allows for finer control of the shapes of the blocks. Cubes are used for the majority of the algorithms, like AO and lighting calculations, collision resolution, liquids and physics (though block coordinates of the cubes are still used for the texture and id lookup for all the blocks excluding liquids).
The rendering, as was mentioned above, is raytracing-based. This particular implementation allows multiple rays to be casted from a single intersection point.
First, intersections are found, then resolved, and then new rays are created, after which the cycle is repeated until no more rays are created.
The intersection finding algorithm is a modification of a DDA ray caster, adapted for rendering with chunks, blocks, and cubes (which can have overlaping faces), and which also allows calculating intersections with arbitrary geometry inside the cubes.
When there are multiple rays casted from a single intersection, they are calculated in depth-first manner. When there are no more rays in one branch to calculate, results are combined with their parent and other branches are calculated.
All of the results, new rays, and intersections are stored in one local, per-invocation array.
Because the intersection finding algorithm is specialized, such rendering results are possible:
here reflective and refractive glass and water are touching reflective metal block, water and glass are touching each other, and grass is submerged in water
Text is rendered using signed distance field bitmap.
Hiero was used to create original font image and characters info. SDF font bitmap is updated automatically whenever the bitmap font image or characters info is updated. It also can be called manually via
make update_sdf
Note: the bitmap font image needs to be created manually from the original image if it was updated
-
Interaction options
Grave accent
( ` ) - toggle cursor mode (disabled when rotating the camera)LMB
- break cube / blockRMB
- place block / liquidWASDQE
- player / spectator camera movementSpace
- player jumpShift
- increase movement speedCtrl
- decrease movement speed / don't replace blocks like leaves and grass when placing blocks onto themZ
- toggle breaking one cube / full blockX
- toggle liquid placing modeScroll wheel
- change selected block
-
Camera options
MMB
- enable smooth camera-
- decrease smooth camera zoom=
- increase smooth camera zoom
-
Some other options
F2
- toggle debug infoF3
- toggle spectator modeF4
- take screenshot (saved as ./screenshot.bmp)F5
- toggle trace bufferF6
- toggle overlay visibility optionsNumpad 0-9
- toggle various actions
-
Hot reloading
Ctrl +
F1
- configuration fileF2
- texturesF3
- buffersF4
- framebuffersF5
- shadersF6
- everything above
-
Esc
- close the game
In order to build the project you need to have these programs:
setup
make build
game
or
br