Rendering
While rendering voxels appears easy at a glance ("they're just cubes!"), there are actually many, many, trade-offs one has to take into account, mainly depending on the intended visual style and scale of the individual voxels.
Ultimately it depends on what your goals are; try not to set them too lofty!
Since there is no way to write about all possible methods, this article will talk about things in general and, if possible, link elsewhere for more details.
Hardware Acceleration
Talking about rendering is impossible without talking about hardware acceleration and thus GPUs; so let's do that real quick!
The primary purpose of a GPU is to calculate/compute/solve a massive number of highly similar problems1 "all at once", by splitting up large sets of data into smaller groups, which are then worked thru by a large number of tiny processing units2.
Historically, the problem in question was mainly vertex transformation and rasterization (and later fragment processing) of triangles via GPUs on dedicated graphics cards.
These days GPUs are much more general purpose and are used in so many applications that we won't bother listing them here.
To hopefully nobodies surprise, rendering voxels is such a massively parallel process, that not using GPUs would be very (very) silly!
How do we gain access to the awesome processing power of GPUs? Well...
Graphics Programming APIs
Unfortunately, directly accessing GPUs usually isn't possible, since:
- Operating systems must share GPU resources between multiple processes.
- There are a multitude of hardware vendors and thus GPUs, not to mention drivers!
As such, we are forced to use a Graphics Programming API... of which there are several.
However, since you are most likely to want to run your program across many platforms and hardware combinations, we can safely ignore a whole bunch of them and choose from one of three APIs:
- To get started as fast as possible, with no regard as to how modern GPUs and their drivers work, use OpenGL.
- To be future-proof and get as much performance as possible out of your GPU, use Vulkan.
- If you're okay with proprietary stuff and are targeting mainly Microsoft Windows & Xbox, you can use Direct3D via DirectX.
Graphics Programming Libraries
If you find the previously mentioned APIs too burdensome or low-level, there are various rendering abstraction libraries available, using the lower APIs as backends:
Only well-known libraries directly exposing 3D graphics are listed.
Name | Language | Backend/s |
---|---|---|
wgpu | Rust | various |
bgfx | C++ | various |
OGRE | C++ | OpenGL / Direct3D |
raylib | C | OpenGL |
libGDX | Java | OpenGL(ES) |
Note:
Some of these libraries have bindings for other languages,
so check out their documentation before rejecting any!
Windowing Abstraction Libraries
Creating a surface to actually draw into is terribly annoying, due to the many platforms and operating systems that exist, so it's best to leave it to a windowing library...
Name | Language | Platforms |
---|---|---|
SDL | C | various |
GLFW | C++ | various |
SFML | C++ | various |
Winit | Rust | various |
General Rendering Methods
There are, in general, two families of volume rendering methods:
Within the former family of surface extraction, the volume is pre-processed into a surface-only representation, such as a mesh or a point-cloud, which can then be rasterized (eg: triangles ⇒ visible pixels).
In the latter family of volume marching, the volume itself is marched through via raycasting/raymarching (eg: visible pixels ⇒ voxels).
It is possible to combine both families for more complex techniques and effects.
Aspects of Lighting
Lighting is commonly defined via some variant of the Bidirectional Reflectance Distribution Function...
- Global Illumination
- Ambient Occlusion
- Flood-Fill Lighting
- Shadow Mapping
- ...?
General Culling Methods
Depending on the method you choose to render voxels, you may have to cull your geometry, so as to not overload your GPU with draw-calls & geometry.
References
- GigaVoxels: Ray-Guided Streaming for Efficient and Detailed Voxel Rendering
- http://jojendersie.de/rendering-huge-amounts-of-voxels/
- http://jojendersie.de/rendering-huge-amounts-of-voxels-2/
- https://swiftcoder.wordpress.com/planets/isosurface-extraction/
- https://0fps.net/2012/06/30/meshing-in-a-minecraft-game/
- http://procworld.blogspot.com/2010/11/from-voxels-to-polygons.html
- http://ngildea.blogspot.com/2014/09/dual-contouring-chunked-terrain.html
- http://ngildea.blogspot.com/2015/06/dual-contouring-with-opencl.html
- https://web.archive.org/web/20200718072744/https://codeflow.org/entries/2010/dec/09/minecraft-like-rendering-experiments-in-opengl-4/
- https://gamedev.stackexchange.com/questions/22664/how-can-i-improve-rendering-speeds-of-a-voxel-minecraft-type-game
Commonly referred to as embarrassingly parallel.
Modern GPU's have literally hundreds, if not thousands, of 'units' running in parallel; the exact mapping of 'units' to 'threads' differs per GPU vendor.