Top Related Projects
A simple Minecraft clone written in C using modern OpenGL (shaders).
I challenged myself to see if I could create a voxel game (Minecraft-like) in just one week using C++ and OpenGL, and here is the result
Quick Overview
VoxelSpace is a JavaScript implementation of the Comanche voxel space rendering engine. It recreates the terrain rendering technique used in the 1992 game Comanche, allowing for fast and efficient rendering of large landscapes using a height map and color map.
Pros
- Efficient rendering of large terrains with minimal computational resources
- Smooth performance even on older hardware or mobile devices
- Educational value for understanding classic 3D rendering techniques
- Easy to integrate into web-based projects
Cons
- Limited to rendering terrain-like surfaces; not suitable for complex 3D scenes
- Lack of advanced features found in modern 3D engines (e.g., dynamic lighting, shadows)
- May appear dated compared to contemporary 3D graphics techniques
- Requires careful optimization for larger or more detailed maps
Code Examples
- Initializing the renderer:
const canvas = document.getElementById('canvas');
const renderer = new VoxelSpace(canvas);
renderer.setResolution(320, 200);
renderer.setFOV(90);
- Loading map data:
const heightMap = await loadImage('height_map.png');
const colorMap = await loadImage('color_map.png');
renderer.setMaps(heightMap, colorMap);
- Rendering a frame:
function render() {
renderer.render(cameraX, cameraY, cameraHeight, cameraAngle, horizon);
requestAnimationFrame(render);
}
render();
Getting Started
To use VoxelSpace in your project:
-
Include the VoxelSpace library in your HTML:
<script src="https://cdn.jsdelivr.net/gh/s-macke/VoxelSpace/VoxelSpace.js"></script>
-
Create a canvas element:
<canvas id="voxel-canvas"></canvas>
-
Initialize and use the renderer in your JavaScript:
const canvas = document.getElementById('voxel-canvas'); const renderer = new VoxelSpace(canvas); renderer.setResolution(640, 480); // Load maps and set up rendering loop // ... (see code examples above)
For more detailed instructions and advanced usage, refer to the project's README and documentation on GitHub.
Competitor Comparisons
A simple Minecraft clone written in C using modern OpenGL (shaders).
Pros of Craft
- More feature-rich, offering a complete 3D voxel-based game engine
- Supports multiplayer functionality
- Provides a more interactive and immersive experience
Cons of Craft
- Higher complexity and steeper learning curve
- Requires more system resources due to its 3D nature
- Less focused on specific rendering techniques
Code Comparison
VoxelSpace (JavaScript):
for (var i = 0; i < screenwidth; i++) {
var height = heightmap[Math.floor(plx) + Math.floor(ply) * mapwidthperiod];
if (height < camera.height) DrawVerticalLine(i, height, camera.height, color);
plx += dx;
ply += dy;
}
Craft (C):
for (int dx = -1; dx <= 1; dx++) {
for (int dy = -1; dy <= 1; dy++) {
for (int dz = -1; dz <= 1; dz++) {
if (dx == 0 && dy == 0 && dz == 0) {
continue;
}
int w = chunk_get(chunk, x + dx, y + dy, z + dz);
if (w > 0) {
set_block(p, q, x, y, z, w);
}
}
}
}
I challenged myself to see if I could create a voxel game (Minecraft-like) in just one week using C++ and OpenGL, and here is the result
Pros of MineCraft-One-Week-Challenge
- More complex and feature-rich, implementing a full 3D Minecraft-like game
- Uses modern C++ and SFML for graphics, providing a more comprehensive codebase
- Includes advanced features like world generation, block placement, and basic gameplay mechanics
Cons of MineCraft-One-Week-Challenge
- Larger codebase and more complex architecture, potentially harder to understand for beginners
- Higher system requirements due to 3D graphics and more intensive computations
- Less focused on a single rendering technique, as it implements various game systems
Code Comparison
VoxelSpace (JavaScript):
for (var i=0; i<heightBuffer.length; i++) {
var height = heightBuffer[i]|0;
if (height < minHeight) continue;
this.DrawVerticalLine(i, minHeight, height, color);
if (height > maxHeight) maxHeight = height;
}
MineCraft-One-Week-Challenge (C++):
void Chunk::makeMesh()
{
for (int y = 0; y < CHUNK_SIZE; y++)
for (int x = 0; x < CHUNK_SIZE; x++)
for (int z = 0; z < CHUNK_SIZE; z++)
{
auto block = getBlock(x, y, z);
if (block == BlockId::Air)
continue;
The code snippets show different approaches: VoxelSpace focuses on 2D rendering of height maps, while MineCraft-One-Week-Challenge deals with 3D voxel-based world generation and rendering.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Voxel Space
Web Demo of the Voxel Space Engine
History
Let us go back to the year 1992. The CPUs were 1000 times slower than today and the acceleration via a GPU was unknown or unaffordable. 3D games were calculated exclusively on the CPU and the rendering engine rendered filled polygons with a single color.
Game Gunship 2000 published by MicroProse in 1991
It was during that year NovaLogic published the game Comanche.
Game Comanche published by NovaLogic in 1992
The graphics were breathtaking for the time being and in my opinion 3 years ahead of its time. You see many more details such as textures on mountains and valleys, and for the first time a neat shading and even shadows. Sure, it's pixelated, but all games in those years were pixelated.
Render algorithm
Comanche uses a technique called Voxel Space, which is based on the same ideas like ray casting. Hence the Voxel Space engine is a 2.5D engine, it doesn't have all the levels of freedom that a regular 3D engine offers.
Height map and color map
The easiest way to represent a terrain is through a height map and color map. For the game Comanche a 1024 * 1024 one byte height map and a 1024 * 1024 one byte color map is used which you can download on this site. These maps are periodic:
Such maps limit the terrain to "one height per position on the map" - Complex geometries such as buildings or trees are not possible to represent. However, a great advantage of the colormap is, that it already contains the shading and shadows. The Voxel Space engine just takes the color and doesn't have to compute illumination during the render process.
Basic algorithm
For a 3D engine the rendering algorithm is amazingly simple. The Voxel Space engine rasters the height and color map and draws vertical lines. The following figure demonstrate this technique.
- Clear Screen.
- To guarantee occlusion start from the back and render to the front. This is called painter algorithm.
- Determine the line on the map, which corresponds to the same optical distance from the observer. Consider the field of view and the perspective projection (Objects are smaller farther away)
- Raster the line so that it matches the number of columns of the screen.
- Retrieve the height and color from the 2D maps corresponding of the segment of the line.
- Perform the perspective projection for the height coordinate.
- Draw a vertical line with the corresponding color with the height retrieved from the perspective projection.
The core algorithm contains in its simplest form only a few lines of code (python syntax):
def Render(p, height, horizon, scale_height, distance, screen_width, screen_height):
# Draw from back to the front (high z coordinate to low z coordinate)
for z in range(distance, 1, -1):
# Find line on map. This calculation corresponds to a field of view of 90°
pleft = Point(-z + p.x, -z + p.y)
pright = Point( z + p.x, -z + p.y)
# segment the line
dx = (pright.x - pleft.x) / screen_width
# Raster line and draw a vertical line for each segment
for i in range(0, screen_width):
height_on_screen = (height - heightmap[pleft.x, pleft.y]) / z * scale_height. + horizon
DrawVerticalLine(i, height_on_screen, screen_height, colormap[pleft.x, pleft.y])
pleft.x += dx
# Call the render function with the camera parameters:
# position, height, horizon line position,
# scaling factor for the height, the largest distance,
# screen width and the screen height parameter
Render( Point(0, 0), 50, 120, 120, 300, 800, 600 )
Add rotation
With the algorithm above we can only view to the north. A different angle needs a few more lines of code to rotate the coordinates.
def Render(p, phi, height, horizon, scale_height, distance, screen_width, screen_height):
# precalculate viewing angle parameters
var sinphi = math.sin(phi);
var cosphi = math.cos(phi);
# Draw from back to the front (high z coordinate to low z coordinate)
for z in range(distance, 1, -1):
# Find line on map. This calculation corresponds to a field of view of 90°
pleft = Point(
(-cosphi*z - sinphi*z) + p.x,
( sinphi*z - cosphi*z) + p.y)
pright = Point(
( cosphi*z - sinphi*z) + p.x,
(-sinphi*z - cosphi*z) + p.y)
# segment the line
dx = (pright.x - pleft.x) / screen_width
dy = (pright.y - pleft.y) / screen_width
# Raster line and draw a vertical line for each segment
for i in range(0, screen_width):
height_on_screen = (height - heightmap[pleft.x, pleft.y]) / z * scale_height. + horizon
DrawVerticalLine(i, height_on_screen, screen_height, colormap[pleft.x, pleft.y])
pleft.x += dx
pleft.y += dy
# Call the render function with the camera parameters:
# position, viewing angle, height, horizon line position,
# scaling factor for the height, the largest distance,
# screen width and the screen height parameter
Render( Point(0, 0), 0, 50, 120, 120, 300, 800, 600 )
More performance
There are of course a lot of tricks to achieve higher performance.
- Instead of drawing from back to the front we can draw from front to back. The advantage is, the we don't have to draw lines to the bottom of the screen every time because of occlusion. However, to guarantee occlusion we need an additional y-buffer. For every column, the highest y position is stored. Because we are drawing from the front to back, the visible part of the next line can only be larger then the highest line previously drawn.
- Level of Detail. Render more details in front but less details far away.
def Render(p, phi, height, horizon, scale_height, distance, screen_width, screen_height):
# precalculate viewing angle parameters
var sinphi = math.sin(phi);
var cosphi = math.cos(phi);
# initialize visibility array. Y position for each column on screen
ybuffer = np.zeros(screen_width)
for i in range(0, screen_width):
ybuffer[i] = screen_height
# Draw from front to the back (low z coordinate to high z coordinate)
dz = 1.
z = 1.
while z < distance
# Find line on map. This calculation corresponds to a field of view of 90°
pleft = Point(
(-cosphi*z - sinphi*z) + p.x,
( sinphi*z - cosphi*z) + p.y)
pright = Point(
( cosphi*z - sinphi*z) + p.x,
(-sinphi*z - cosphi*z) + p.y)
# segment the line
dx = (pright.x - pleft.x) / screen_width
dy = (pright.y - pleft.y) / screen_width
# Raster line and draw a vertical line for each segment
for i in range(0, screen_width):
height_on_screen = (height - heightmap[pleft.x, pleft.y]) / z * scale_height. + horizon
DrawVerticalLine(i, height_on_screen, ybuffer[i], colormap[pleft.x, pleft.y])
if height_on_screen < ybuffer[i]:
ybuffer[i] = height_on_screen
pleft.x += dx
pleft.y += dy
# Go to next line and increase step size when you are far away
z += dz
dz += 0.2
# Call the render function with the camera parameters:
# position, viewing angle, height, horizon line position,
# scaling factor for the height, the largest distance,
# screen width and the screen height parameter
Render( Point(0, 0), 0, 50, 120, 120, 300, 800, 600 )
Links
Web Project demo page
Voxel terrain engine - an introduction
Maps
License
The software part of the repository is under the MIT license. Please read the license file for more information. Please keep in mind, that the Voxel Space technology might be still patented in some countries. The color and height maps are reverse engineered from the game Comanche and are therefore excluded from the license.
Top Related Projects
A simple Minecraft clone written in C using modern OpenGL (shaders).
I challenged myself to see if I could create a voxel game (Minecraft-like) in just one week using C++ and OpenGL, and here is the result
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot