I've always been a big fan of the Geometrical MipMapping algorithm for terrain rendering to the point where I asked its creator, Willem de Boer, to write the foreword to my book. Geomipmapping was, far and away, my favorite of the three algorithms which I discussed in my book, and was also one of the two algorithms I chose to write about in my Graphics Programming Methods chapter. So, when trying to figure out a very GPU-friendly way of handling this D3D10 terrain renderer it should come as no surprise that the base of the implementation would be geomipmapping. I think the mesh structure is absolutely perfect for GPU optimization, something that I didn't really have the resources to rely on four years ago.
So, the first part of the implementation that I worked on was the basic mesh structure; I don't have much of a need for a dataset larger than 2048x2048 height set, so I created a mesh structure of sixteen by sixteen mesh blocks of 128x128 vertex resolution. Since I'm developing with Direct3D 10, I get the absolutely joyous knowledge that I'm guaranteed functionality for vertex textures, so I can create a single vertex buffer for the 128x128 resolution block, and that's all that is required as far as vertices are concerned. I'm planning on having about four to five LOD levels, so I'm planning on creating one index buffer per LOD level. So, given all of this, I can manage to render the entire terrain in one draw call per LOD level. I can render all of the blocks of a given LOD by just instancing their origin into the shader and the vertex shader should be able to take care of all of the rendering details (I think I may be able to handle crack-fixing within the VS as well, but I'm not sure about that quite yet).
One of the oddities I ran into last night was that the non-instanced rendering of the mesh (I'm not using any LOD management yet) seems to be running about thirty to forty frames-per-second faster than the instanced rendering. I'm going to try slimming down the instance data (I'm currently using a transformation matrix, but I should be able to just pack the data into two short values instead), but I'm not sure if that will solve the differences or not. Shots below (non-instanced on the left and instanced on the right):
Once I had the base rendering working, I then shifted my attention to getting the height values being read in correctly from the height data by sampling the texture in the terrain's vertex shader. This actually ended up being more difficult than I had expected, due entirely to the fact that getting information from the DirectX10 Documentation is about as straightforward as using an extra-large porcupine for a bob-sled. Here's the current vertex shader (still under heavy coding):
VS_OUTPUT RenderVS( VS_INPUT vsInput )
//Get the world origin using the instance data.
float2 v2WorldPos = vsInput.v2GridPos*v4ScaleFactor.xy + vsInput.v2Transform_Inst;
//Convert from grid XY to world XY coordinates.
//ScaleFactor.xy: Grid scale.
// //Compute coordinates for vertex texture.
float2 v2UV = v2WorldPos + float2( v4ScaleFactor.z, v4ScaleFactor.z );
float y = texFineLevel.SampleLevel( samFineLevel, float2( v2UV ), 0 ).r*128;
vsOutput.v4Position = mul( float4( v2WorldPos.x, y, v2WorldPos.y, 1 ), matWorldViewProj );
vsOutput.v2TexCoord = v2UV;
Anyway, here's a look at the terrain as it exists right now: