+
On the Care and Feeding of HTML Voxels
(best in Chrome! Slides thataway → )
Andy Hall
5.15.2015
Using this presentation:
move around:
invert mouse:
destroy block:
place block:
pick block:
zoom:
jump:
jet pack:
WASD, arrows
I
LMB, tap
E, RMB
Q, middle mouse
scroll
space
R
(mobile users: sorry lol)
About me:
@fenomas
free gamedev, sometime Adobe evangelist
github/andyhall
aphall.com
Voxels - definition
tl;dr:
Ever seen Minecraft?
Yeah those.
Voxels - proper definition

Rasterized 3D data.

Colloquially, if pixels represent the rasterization of 2D data, voxels are the 3D equivalent.
(Hence "voxel": volumetric pixel)
Conceptually, voxels are a sampling over some 3D space, just as pixels in a bitmap are samples of some 2D data (vector graphics, photos, etc).
Note: nothing (per se) to do with gaming!
(CT scan data)
Voxels and Gaming
Comanche, 1992
Voxel advantages
Provides game with easily grasped structure -
Equivalent to grids in 2D games
Conceptually easy to work with
  • Technical tradeoffs (e.g. CPU vs memory) largely similar to vectors/bitmaps
  • Some hard things become easy (raycasting, collision tests..)
  • (Of course some easy things become hard..)
Voxel advantages

Mutable worlds for free! (ish)

World-affecting game rules
c.f. "Emergent gameplay"
Note:
"3" to place a Conway Block
"4" to stop/start simulation
Note: not just for rendering!
Voxels are often useful behind the scenes regardless of how a game looks (e.g. for physics simulation).
Conceptually: 3D games should use voxels wherever a 2D game would use a grid.
Rendering Voxels

GPUs do not grok voxels!

In general a conversion step ("meshing") is necessary to convert voxels into stuff that GPUs understand (vertex lists, normals, etc).
Here are three approaches:
Naive Meshing
Create one cubic mesh per voxel
Problems: poly counts, draw calls
Culled Meshing
Merge voxels into one large mesh,
omitting faces between adjacent voxels.
Result: fewer draw calls, still a lot of polys
"Greedy Meshing"
Scan across voxel slices, merging faces of adjacent voxels (of the same value).
Credit: all-around genius Mikola Lysenko
Chunking
Necessary tradeoff for large worlds:
faster meshing, more draw calls.
Minecraft chunks: 16x16x256 (divided vertically)
This demo: arbitrary (32x32x32 at the moment)
Ambient Occlusion
Comparatively simple for voxels,
and greatly improves visuals
Note: Voxels needn't be blocks!
Voxel Quest
CT scan data
(google "marching squares")
In fact...
World generation
Driven deterministically by noise (Perlin, simplex) and hashing.
In this demo:
2D noise: height map
3D noise: clouds
Hashing: tree/flower placement
Other world algorithms
Many voxel algos extend naturally from 2D cases (often heavily researched).
  • Collision tests: simple grid check
  • Raycasting: equivalent to line rasterization (e.g. Bresenham)
  • Physics: had to roll my own, but easier than 3D
noa (this engine)

And how I built it
Dev stack:
node | npm | browserify | beefy
Why roll a new engine?
I started trying to use voxel.js
Pros:
Tons of great code
Extremely modular
Cons:
Massively coupled
Dependency hell
Renders on bare metal
noa's approach:
  • Reuse code from voxel.js where feasible
    (raycasting, meshing..)
  • Otherwise written from scratch
    (physics, rendering, controls, AO..)
  • Babylon.js for rendering (click)
State of the project
  • Works(?), performant(?)
  • No docs, all APIs in flux
  • Features: see testbed app (click)
  • Collaboration welcome, drop me a mail/issue/etc
Thoughts after 5 months of this:
  • Gamedev on HTML/webGL is fun if you can choose your browser
  • JS a fun dev platform if you use npm well and modularize responsibly
  • Chrome/v8 is really fast, yo
  • Mobile: what's that? Is it tasty?
Thanks!
@fenomas
github.com/andyhall