A 3D terrain generator and editor
Adjustable noise for varied terrain options
Uses three layers of noise values at different frequencies and strengths in order to create a more detailed landscape
noiseValue =
1 * noise(x / frequency1, y / frequency1, z / frequency1) +
0.5 * noise(x / frequency2, y / frequency2, z / frequency2) +
0.25 * noise(x / frequency3, y / frequency3, z / frequency3);
Options
- Sliders to adjust noise frequencies
- Button to generate random seed
- Toggle interpolation and wireframe view
Explore the terrain in first person
Controls
W
,A
,S
,D
orArrow Keys
to moveSpace
to jumpMouse
to look around
Deformable terrain in real time
Controls
Left Click
to add terrainRight Click
to remove terrain
Install the dependencies and run the app
cd marching-cubes-v2
npm install
npm run dev
Run tailwind to edit the CSS and styling
npm run tailwind:dev
- Three.js - Library for creating 3D graphics in a web browser
- Typescript - Superset of Javascript with strong static typing
- TailwindCSS - CSS framework for rapid styling
- Vite - Frontend build tool for quicker development
Marching cubes is an algorithm used for generating 3D terrain. It works by sampling the corner points of a cube using a function that takes in a point and returns a single value.
If the value is below a certain "surface-level" threshold, it is considered empty space. However, if the value is above the surface-level value then it is considered to be inside the surface, or underground.
After doing this for each corner of the cube, we get a list of above-ground and underground points, and the goal is to construct a surface to surround the underground points.
Repeat this for each cube in a chunk and the result is a terrain-like shape.
Bolded corners are underground and a surface is created to enclose the corner
From taking seconds just to render a few chunks, to an infinite chunk generator with deformable terrain, here are some of the optimizations that made it all possible.
Optimization | Result |
---|---|
BufferGeometry | Buffer geometries are a feature in Three.js that store geometry data in buffers representing parallel arrays. This reduces the amount of memory and time used to store and transform the data. |
Noise Caching | On the noise editor page, sliding the frequency sliders requires recomputing the noise map multiple times per second. To reduce the number of computations required, noise values are cached so that only the layer that changes will get recomputed and added on to the cached values. |
Simplex Noise | Simplex noise is an improved version of Perlin noise. It requires less calculations, scales better to higher dimensions, and reduces directional artifacts. It has a complexity of |
Web Workers | While Javascript is a single-threaded language, web workers make it possible to create multithreaded applications by running scripts in background threads. They are used in the first person mode to calculate the noise maps and meshes of new chunks in parallel, allowing the main thread to focus on rendering and handling input. This significantly improves the framerate and prevents the window from freezing up when loading new chunks. |
Inspired by Sebastian Lague's Coding Adventure: Marching Cubes
Improved version of marching-cubes (live)