I've just been checking out the Terrain extension. It looks great, and it's super fast!
However, it currently generates a lot of overdraw. I found a few improvements that made my GeForce 7600 Go a lot happier:
1: The geometry skirts are very big. I found that multiplying the skirt size by the eye distance to maintain an approximately constant screen-space size allowed much smaller skirts while still giving good results at larger distances.
2: Block rendering sequence is independant of camera position, sometimes resulting in a lot more back-to-front overdraw than is necessary. By trying to render in a more front-to-back order, depth culling can be a lot more effective.
3: (Not yet tested.) There's only one index buffer at the moment. If we use four instead, then they can traverse the geometry patch in different directions, and the renderer can pick the buffer with a mostly front-to-back sequence for the current camera location.
Some code for (1) and (2):
Code:
Index: terrain.cpp
===================================================================
--- terrain.cpp (revision 457)
+++ terrain.cpp (working copy)
@@ -136,7 +136,8 @@
// Create skirt
if( v == 0 || v == size - 1 || u == 0 || u == size - 1 )
{
- *vertHeight = maxf( *vertHeight - TerrainSkirtHeight, 0 );
+ float skirtHeight = TerrainSkirtHeight * dist;
+ *vertHeight = maxf( *vertHeight - skirtHeight, 0 );
}
}
}
@@ -148,10 +149,26 @@
else
{
scale /= 2;
- drawTerrainBlock( terrain, minU, minV, halfU, halfV, level + 1, scale, localCamPos );
- drawTerrainBlock( terrain, halfU, minV, maxU, halfV, level + 1, scale, localCamPos );
- drawTerrainBlock( terrain, minU, halfV, halfU, maxV, level + 1, scale, localCamPos );
- drawTerrainBlock( terrain, halfU, halfV, maxU, maxV, level + 1, scale, localCamPos );
+ Vec4f blocks[] =
+ {
+ Vec4f( minU, minV, halfU, halfV ),
+ Vec4f( halfU, minV, maxU, halfV ),
+ Vec4f( minU, halfV, halfU, maxV ),
+ Vec4f( halfU, halfV, maxU, maxV )
+ };
+ // Sort blocks by distance from camera
+ if( localCamPos.x > halfU )
+ {
+ std::swap( blocks[0], blocks[1] );
+ std::swap( blocks[2], blocks[3] );
+ }
+ if( localCamPos.z > halfV )
+ {
+ std::swap( blocks[0], blocks[2] );
+ std::swap( blocks[1], blocks[3] );
+ }
+ for( int b = 0; b < 4; ++b )
+ drawTerrainBlock( terrain, blocks[b].x, blocks[b].y, blocks[b].z, blocks[b].w, level + 1, scale, localCamPos);
}
}
Much kudos to Volker for a clever and very fast system! I hope you can use these suggestions
Edit: Is it Volker's? I'm just guessing that from the credits line at the top including his name.