A landscape displayed from a heightmap and single diffuse texture. Landscapes were from 4-8 million vertices. Regions consisted of 4096 vertices and could be drawn as anywhere from 2 tris to 8 thousand tris. Distance to camera and intrinsic detail bias based determination of which level-of-detail to use. A normal map was also calculated at first load to show consistent lighting despite changing LOD.
I created a stitching system to allow connected regions to differ in LOD. This required 16 different stitch patterns for each level of detail based on which touching regions were at a different LOD. This code follows:
void LODLandscape::CreateIndexBuffers()
{
/**
* Create space for all the index buffers. And
* the ids/lengths for talking to the GPU.
*
* iBuffers gets enough memory for the largest
* possible index buffer.
*
* VERTCHUNKWIDTH - Number of heightvals across in each chunk
* NUMSUBSAMPLES - Number of LOD levels being used
*
* NORTH, SOUTH, EAST, WEST: 1, 2, 4, 8
*/
unsigned short *iBuffers = new unsigned short[VERTCHUNKWIDTH*VERTCHUNKWIDTH*NUMSUBSAMPLES];
iBuffIds = new size_t*[NUMSUBSAMPLES+1];
iBuffLengths = new size_t*[NUMSUBSAMPLES+1];
for( int i=1 ; i<=NUMSUBSAMPLES ; ++i )
{
iBuffIds[i] = new size_t[16];
iBuffLengths[i] = new size_t[16];
for( int dir=0 ; dir <= (NORTH|EAST|SOUTH|WEST) ; ++dir )
{
int currIndexSize=0;
#define HEIGHT (VERTCHUNKWIDTH+1)
#define STEP (1<<(NUMSUBSAMPLES-i))
#define PUSHBACK(n) iBuffers[ currIndexSize++ ] = n
for( int y=0 ; y < VERTCHUNKWIDTH ; y+=STEP )
for( int x=0 ; x < VERTCHUNKWIDTH ; x+=STEP )
{
if( !(( x/STEP+y/STEP )%2) )
{
if( y==(VERTCHUNKWIDTH-STEP) && dir&NORTH )
{
PUSHBACK( (y+STEP)*HEIGHT + x+STEP );
PUSHBACK( (y )*HEIGHT + x );
PUSHBACK( (y+STEP)*HEIGHT + x-STEP );
}
else if( !(x==0 && dir&WEST) )
{
PUSHBACK( (y )*HEIGHT + x );
PUSHBACK( (y+STEP)*HEIGHT + x );
PUSHBACK( (y+STEP)*HEIGHT + x+STEP );
}
if( x==(VERTCHUNKWIDTH-STEP) && dir&EAST )
{
PUSHBACK( (y+STEP)*HEIGHT + x+STEP );
PUSHBACK( (y-STEP)*HEIGHT + x+STEP );
PUSHBACK( (y )*HEIGHT + x );
}
else if( !(y==0 && dir&SOUTH))
{
PUSHBACK( (y+STEP)*HEIGHT + x+STEP );
PUSHBACK( (y )*HEIGHT + x+STEP );
PUSHBACK( (y )*HEIGHT + x );
}
}
else
{
if( y==0 && dir&SOUTH )
{
PUSHBACK( (y )*HEIGHT + x-STEP );
PUSHBACK( (y+STEP)*HEIGHT + x );
PUSHBACK( (y )*HEIGHT + x+STEP );
}
else if( (x==0 && dir&WEST) )
{
PUSHBACK( (y-STEP)*HEIGHT + x );
PUSHBACK( (y+STEP)*HEIGHT + x );
PUSHBACK( (y )*HEIGHT + x+STEP );
}
else
{
PUSHBACK( (y )*HEIGHT + x );
PUSHBACK( (y+STEP)*HEIGHT + x );
PUSHBACK( (y )*HEIGHT + x+STEP );
}
if( !( y==(VERTCHUNKWIDTH-STEP) && dir&NORTH ) && !( x==(VERTCHUNKWIDTH-STEP) && dir&EAST ))
{
PUSHBACK( (y+STEP)*HEIGHT + x+STEP );
PUSHBACK( (y )*HEIGHT + x+STEP );
PUSHBACK( (y+STEP)*HEIGHT + x );
}
}
}
iBuffIds[i][dir] = Renderer::GetInstance()->CreateIndexId( iBuffers, currIndexSize );
iBuffLengths[i][dir] = currIndexSize;
}
}
delete [] iBuffers;
#undef HEIGHT
#undef STEP
#undef PUSHBACK
}



LinkedIn
Facebook
Twitter




Magnetism
Memory Manager
Lockless, Threadsafe Queue