mathieu.dev
All projects
Personal Project — GPU Mesh Generation

EarthMesh

A cube-sphere mesh of the Earth, built almost instantly on the GPU through HLSL compute shaders, shaded with a normal map baked ahead of time and a Shader Graph water system.

Built in 2021 in high school · not public

Demo

See it running

A recording of the current build generating the globe and orbiting around it — coming soon.

Demo video coming soon
Overview

One planet, three complete rewrites.

EarthMesh is a Unity project, started in high school around 2021, that generates a 3D mesh of the Earth from real height and color data. It went through three full rewrites: a first single-threaded CPU version, a multithreaded CPU rewrite, and finally today's version, where the mesh itself is generated on the GPU through HLSL compute shaders — turning what used to be a noticeable load time into something close to instantaneous.

The sphere is built from six subdivided squares rather than the usual latitude/longitude sphere, which spreads detail evenly instead of bunching it up at the poles. Height and color come from sampling real Earth textures, fine surface detail comes from a normal map precomputed once on the GPU, and the ocean is animated and shaded almost entirely through Shader Graph.

3
full rewrites: single-thread CPU → multithreaded CPU → GPU
6
subdivided cube faces make up the sphere
16k×8k
px normal map, baked once on the GPU
2021
started as a high-school project
01 — Cube to sphere

A sphere built from squares, not slices

Instead of the classic latitude/longitude sphere, each of the mesh's six faces starts as a flat square subdivided into a grid of smaller squares, each made of two triangles. Every vertex is then normalized — pushed out onto the unit sphere — and scaled up by the planet's radius. Spreading the same grid density over all six faces keeps vertices evenly spaced across the whole surface, instead of bunching them up at the poles the way a trigonometric UV sphere does, so detail stays consistent from the equator to the ice caps.

Cube-to-sphere process video coming soon
02 — Height and color from real Earth data

Sampling a height map and a planisphere

Once a vertex sits on the unit sphere, converting its position back to longitude and latitude gives a UV coordinate into two equirectangular textures: a grayscale height map that pushes the surface up or down, and a color map — a planisphere of the real Earth — used to paint the terrain. The same height map is reused later to precompute the normal map.

03 — Three rewrites, and a fixed resolution

From a single thread to the GPU

The project went through three complete rewrites: first a single-threaded CPU version, then a multithreaded CPU rewrite splitting mesh generation across cores, and finally today's version, where the mesh is built entirely on the GPU through an HLSL compute shader. Generation itself is now close to instantaneous — the actual bottleneck is reading the computed vertex and triangle buffers back from the GPU into a Unity Mesh.

An earlier CPU version could dynamically raise the mesh resolution while zooming in, but the resolution jumps it caused led to intempestive load hitches, so the final version fixes the resolution once, at launch, instead.

An earlier build of the project showing real planes tracked over the globe
An earlier build — real planes tracked via a free flight API, straits flagged with colored squares, no water animation or normal map yet.
04 — A normal map, baked ahead of time

Faking detail the mesh doesn't have

A dedicated compute shader walks the height map texel by texel, compares each point to its north, south, east and west neighbors on the sphere, and cross-products the resulting tangent vectors into a surface normal — baked once into a 16384×8192 texture. Lighting then reacts to that normal map as if every ridge and coastline were really there, without adding a single extra vertex to the mesh.

Before/after comparison coming soon
05 — Water, entirely in Shader Graph

Animating only what's actually water

A dedicated land/water mask flags which parts of the mesh are ocean, so only those vertices get animated — their color still comes from the same color map used for the rest of the surface. The wave motion itself, driven by 3D noise nodes found online, is built with Shader Graph rather than hand-written HLSL, which I tried and, at the time, found too hard to get right by hand.

Source data

Four textures build one planet

The height map and color map come from real Earth satellite imagery; the water mask and the normal map are baked specifically for this project.

Color map
Color mapAn equirectangular planisphere of the real Earth, used to paint the surface.
Height map
Height mapGrayscale elevation, sampled per vertex to push the mesh up or down.
Water mask
Water maskFlags which parts of the mesh are ocean, so only those vertices animate.
Normal map
Normal mapBaked once, 16384×8192px, from the height map's neighboring texels.
Built with
  • C#
  • Unity
  • URP
  • HLSL
  • Compute Shaders
  • Shader Graph