Skip to main content
GameDev.net gamedev.net
🔒 Locked

Geometry Clipmaps - sample heightmap?

Started by phivuu-2 Feb 9, 2016 at 3:53 PM 4 replies 7.2k views
Original Post
phivuu-2
phivuu-2

Hi,

I've read the geometry clipmaps, and also researched how it works. There are some parts I still don't understand.

If I have a heightmap texture that is bigger than the clipmap how do I sample the right height from it?

I currently have a grid that has as many vertices as the size of the heightmap just to be able to sample correctly. But clipmap has a specific amount of vertices.

Another part I don't understand is when the clipmap levels are updated. So that they are centered around the viewer. Do I have to update the heightmap texture somehow? Shouldn't it work if I just update the vertex, uv buffers for the clipmaps? And with the new uvs I should be able to sample from the heightmap? The paper mentioned toroidal access to update the texture which is confusing for me but I don't even see the purpose of updating the texture.

Aqua Costa
Aqua Costa

The main goal of Geometry Clipmaps is enabling you to draw terrains with higher resolution than you can fit in GPU memory (and still have space for the rest of the game assets).

Example: The Witcher 3 height map is 23552x23552 = ~1GB (0.37m resolution, I think there's a typo in the presentation). Clearly too much memory if you want other assets in your game.

You *probably* don't need full resolution height data to draw distant mountains, so you can use a clipmap.

dRiJCCN.png(source)

The top layer in blue is the full res height map. The blue layers below it are the mips (each half res of the previous one).

But you only load into GPU memory the green areas (centered around the camera).

Continuing using The Witcher 3 as example:

It uses 5 clip maps each with resolution 1024x1024 (eg: texture array).

1st layer - Full res - 1024 * 0.37m = 378m around the camera (in each direction)

2nd later - Half res - 1024 * 0.74m = 757m around the camera. (0.74m because it's half res so each pixel corresponds to double the distance)

...

5th layer - 1/16 res - 1024 * 5.92m ~ 6km around the camera

Full map is 23552 * 0.37 ~8.7km, so they're able to draw most of the map using only 1024*1024*5*2 bytes ~ 10 Mb height data.

Since you have all the data you need in the clip map, you don't need as many vertices as the size of the heightmap to render the terrain. Just create a 16x16 patch of vertices (15x15 rectangles), don't need any uvs, and reuse it to draw the terrain. In the vertex shader calculate the world position of the current vertex and use that to sample the clipmap in the correct position/layer.

Since you only have full res height data close to the camera, as soon as you start to use different layers of the clipmap render patches doubling the distance between vertices so each vertex matches one pixel of terrain data.

You'll run into problems in the borders when you start to render patches using a different layer because the height data won't match perfectly.

This GPU Gems article explains the types of patches to use and how to hide the seams between patches with different levels of detail.

When the camera moves (enough) you need to update some layers of the texture clipmap with data from the full map texture you have on disk. Doing toroidal access allows you to only update parts of the texture instead of having to move the parts that are still relevant over old parts and fill the "empty" space with new height data.

Some useful links:

http://www.gamedev.net/topic/652777-geometry-clipmaps-terrain-tutorial-with-source/

http://www.vertexasylum.com/downloads/cdlod/cdlod_latest.pdf (good solution for seams between layers, I use a modified version of this in my demos and it works very well) link to full source code in the end of paper)

Funkymunky
Funkymunky

For my implementation I have a separate texture store that I use as source data for updating the clipmap with. The clipmap is a texture array with N levels, and the texture store is a 3x3 grid of textures (with N levels of grids). When I'm updating the clipmap, I check if the necessary texture store entry is present before doing the update. If it's not, I drop that clipmap level until I can render. I also pre-emptively load the texture store based on the velocity of the camera.

I have a separate thread running that checks for texture requests and loads the data from the disk or generates it with procedural noise, and flags the entry as complete when it finishes a texture.

phivuu-2
phivuu-2

Is the green area the clipmap grid? The outer levels of the grid has a hole in the middle which is filled with a finer grid level. How does that work with the green area? How do I know where in the texture file on the disk to extract the right data? I assume I want the height data that is around the viewer? And I don't see how to extract it from a file on the disk.

I think I'll worry about the out of core stuff later. I'll begin with creating the grid levels and be able to update them when the camera moves. If I have a grid structure and it has n x n vertices like the paper mentions, 16x16. And for now I'll load a whole heightmap into the vram, let's say of size 1025x1025. My question is then how do i sample the heightmap when the grid isn't the size of the heightmap? I just want to sample a region of the heightmap I guess? but how do I decide the region?

phivuu-2
phivuu-2

I got my clipmap grid but I still don't understand how to sample the heightmap?

I store the whole heightmap in the memory and generate the mipmaps.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.