Post on 28-Jan-2015
description
Overview
• Topographic Datasets
• Geometry partitioning
• Tesselating meshes
• Level of Detail (LOD)
• Data structures for geometry
• Projections
• Efficient Out of Core fetches
• Lighting
• Shaders
• Procedural detail
Basics - drawing path
Topography Normals
Bathymetry
Textures
Shaders
Topography
Shuttle Radar Topography Mission
(SRTM)
Blue Marble Next Generation
(BMNG)
SRTM
Resolution: 90m/pixel
Coverage: 60ºS to 60ºN Lat, 360º Long
Samples: 144000x432000, 16 bit
~115 GiB
Much higher resolutions available for limited areas
Others
Mars: MOLA + Viking
Moon: LOLA + Clementine
Mercury: Messenger + Mariner
Venus: Magellan + Venera
A couple more...
Back to Basics
432000x144000 samples (not counting poles)
16bit/sample topography+bathy
24bit/sample textures (+ 173GB)
24bit/sample normals (+ 173GB)
Add specular byte to topo+bathy
Totals 3x173 GB = 519 GB @ 90m/sample
Preparing the Data
What exactly do you need to achieve?
How much effort are you willing to put in?
• Data is but height samples - Mesh tesselation
• Too much data to draw everything every frame - Level of Detail
Terrain Rendering 101
• Realtime Optimally Adapting Meshes
• Geomipmapping
• Chunked Level of Detail (LOD)
• Geometry Clipmaps
Common Methods
Chunked LOD
Tesselating Meshes
Several options - I picked triangle strips
LOD - Level of Detail
Split each chunk into 4 when LOD increases
Chunk side vertex count must be 2^n
LOD - Level of DetailConnect patches by copying:
left of right to right of left
new count is (2^n)+1
LOD - Tricks
Optimize patch side vertex count for performance
You want few GPU ops with a lot of data
You don’t want the GPU to ‘swap’ from VRAM to RAM
Meet the Quadtree
Quadtree Basics
• vertex buffer object
• exactly 4 children per node (1-NE, 2-NW, 3-SE, 4-SW)
• index [1-4]
• last drawn timestamp
• vertex buffers for geometry, textures, normals
• Search: O(n), n = LOD level (follow pointers)
Cylindrical #FAIL
Linear sample density Non linear perimeter
6 Gnomonic Projections
Wolfram is your friend http://mathworld.wolfram.com/GnomonicProjection.html
Cube to Sphere
Normalize each vertex Add altitude
v = normalize(v) * (planet radius + altitude)
So Far
• Dealt with LOD, splitting
• Found a suitable projection system
• Triangulated the terrain meshes
• Each patch of terrain - Vertex Buffer Object
Redundancy
• Several representations of the same data
• Increased dataset size, up to 2x
• No way around for textures
• EP + 1 for everything else
EP + 1
EP + 1 Storage
• Reprocess the entire dataset
• Write all samples as chunks
• Arrange by LOD levels
• Don’t write duplicate samples
• Reading a chunk is now fseek+fread
Eye Candy 1 - Lighting
• Normals are crucial
• Light intensity directly proportional to LoN
Calculating Normals
• Use a single chunk of vertexes
• Rotate and scale accordingly
• Attach heightmap as texture
• Morph (planet radius + texture height)
• Sample neighboring heights for normal
Normal MapHeights stored in 16bit: Red+Green channels
Non spherical coordinate system
Planetary NormalsGet rotation from unit vector to the vertex position
Apply same rotation to normal vector
• Extract watermask from BMNG
• Single bit, store in blue component of heightmap (24 bit total)
Water Specular
Eye Candy 2 - Atmosphere
• Two types of scattering, Mie & Rayleigh
• Small molecules, O2, O3, etc - Rayleigh
• Aerosols - Mie (gray when it rains, pollution haze, etc)
Atmospheric ShaderPhase function - Amount of scattering for camera angle
Outscattering - Optical depth of ray from entry point to camera
Inscattering - Amount of light added by scattering on planet surface into camera
Atmospheric Shader
Atmospheric Shader
Atmospheric Shader
Fractal NoiseAdding in missing detail
Fractal NoiseAdding in missing detail
Height = dataset height + noise heightmap
Fun!
• Add gravity, each object is a node, it’s easy
• Export from SketchUp to .obj, auto triangulate + auto normals
• Write a script to convert .obj into a vertex buffer object
• Drop in a dead simple shader
Just for Fun
Final Results
Thanks!