Optimizing Terrain Drawing?

Blake
Unregistered
 
Post: #1
is there any way to optomize this, and no it doesnt take into account the different textures or y positions yet. It just seems to draw to slowly on larger maps
Code:
- (void) compileGround
{
    int i,j;
    
    glDeleteLists( groundCallList, 1 ); // Clearing Ground From Previous Game
    
    groundCallList = glGenLists( 1 ); // Generating New List
    
    glNewList( groundCallList, GL_COMPILE ); // Telling OpenGL To Compile The List
    
    glEnable( GL_CULL_FACE ); // Enable Cull Facings
    glCullFace( GL_FRONT ); // Telling OpenGL We Want To Draw The Fronts Of The Objects
    
    glPolygonMode( GL_FRONT, GL_FILL ); // Drawing And Filling Only The Front Of The Polygons
    
    glEnable( GL_TEXTURE_2D ); // Enabling Textures
    
    glEnable( GL_DEPTH_TEST ); // Enableing Depth Testing
    
    glColor3d( 1.0, 1.0, 1.0 ); // Setting It So That No Color Displacment Is Caused
    
    // Terrain
    glBindTexture( GL_TEXTURE_2D, terrainTextures[ 0 ].texID );
    for( i = 0; i < map.width; i++ )
    {
        glBegin( GL_TRIANGLE_STRIP );
        glTexCoord2f( 0, 1 );
        glVertex3d( i*0.5, 0, 0 );
        glTexCoord2f( 1, 1 );
        glVertex3d( (i+1)*0.5, 0, 0 );
        for( j = 0; j < map.depth; j++ )
        {
            
            glTexCoord2f( i, j );
            glVertex3d( i*0.5, 0, (j+1)*0.5 );
            glTexCoord2f( i+1, j );
            glVertex3d( (i+1)*0.5, 0, (j+1)*0.5  );
        }
        glEnd();
    }
    
    glDisable( GL_CULL_FACE ); // Disableing Cull Facings
    
    glEndList(); // Telling OpenGL We Are Done With The List
}
Quote this message in a reply
Moderator
Posts: 608
Joined: 2002.04
Post: #2
Random guess: could you put the glBegin and glEnd outside the for loop so that you send the vertices in one big batch?
Quote this message in a reply
Member
Posts: 72
Joined: 2006.10
Post: #3
Do you really need the double precision?

Switching from vertex3d() to vertex3f() calls should be somewhat faster, since all the memory accesses would be split in half. Also, in my personnal experience, unless you want really realistic physics ( or unless you terrain is ridiculously large ), doubles are completly overkill.

HTH.

- Sohta
Quote this message in a reply
Moderator
Posts: 365
Joined: 2002.04
Post: #4
Slightly OT:

Sohta Wrote:Switching from vertex3d() to vertex3f() calls should be somewhat faster, since all the memory accesses would be split in half.
Logically, you might expect that to be the case. In practice I've always found that it makes no appreciable difference when there's any other time consuming operation in the loop (such as rendering).

If you want to see this in action, take a look at the Yoink source code. There's a preprocessor switch which swaps between using single and double precision, but it runs at the same speed in either case.

Remember, measure before you optimise! Wink

Neil Carter
Nether - Mac games and comic art
Quote this message in a reply
Member
Posts: 72
Joined: 2006.10
Post: #5
True.

But the main problem ( on BIG maps ) are the shear number of polys ( already 32768 for a 128 * 128 map ), and there's not much going around that.

What you CAN do is: when you compile the display list, you find wich adjacent polys are coplanar. These polygons can then be rendered as one single polygon. So a flat surface wouldn't uselessly use polygons in that case. Compiling the display list would be longer, since you would have to pass at least two times trough the whole terrain matrix, but the rendering of the terrain would ( should, there might be exceptions ) be faster.

In my opinion, that's a lot of trouble, but it would be a nice optimisation.


Come to think of it, you can also split your terrain in multiple small terrains, and then do some frustrum culling ( i.e. not draw a terrain that is behind the camera ).

Good Luck!

- Sohta
Quote this message in a reply
Moderator
Posts: 365
Joined: 2002.04
Post: #6
Also, if you want to get sophisticated, you could look into polycount reduction algorithms such as ROAM (URL blindly pulled out of Google, might not be any good Ninja).

Neil Carter
Nether - Mac games and comic art
Quote this message in a reply
Blake
Unregistered
 
Post: #7
okay ive optomized the code a bit, it now will now combine the like polygons along the z axis, any idea on how i may do the x axis?
Code:
- (void) compileGround
{
    int i,j,currentType,count;
    float currentYPos[ 2 ];
    
    glDeleteLists( groundCallList, 1 ); // Clearing Ground From Previous Game
    
    groundCallList = glGenLists( 1 ); // Generating New List
    
    glNewList( groundCallList, GL_COMPILE ); // Telling OpenGL To Compile The List
    
    glEnable( GL_CULL_FACE ); // Enable Cull Facings
    glCullFace( GL_FRONT ); // Telling OpenGL We Want To Draw The Fronts Of The Objects
    
    glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); // Drawing And Filling Only The Front Of The Polygons
    
    glEnable( GL_TEXTURE_2D ); // Enabling Textures
    
    glEnable( GL_DEPTH_TEST ); // Enableing Depth Testing
    
    glColor3d( 1.0, 1.0, 1.0 ); // Setting It So That No Color Displacment Is Caused
    
    // Terrain
    glBindTexture( GL_TEXTURE_2D, terrainTextures[ 0 ].texID );
    for( i = 0; i < map.width; i++ )
    {
        glBegin( GL_TRIANGLE_STRIP );
        glTexCoord2f( i, 0 );
        glVertex3f( i*0.5, map.yPositions[ i ][ 0 ], 0 );
        glTexCoord2f( i+1, 0 );
        glVertex3f( (i+1)*0.5, map.yPositions[ i+1 ][ 0 ], 0 );
        
        currentYPos[ 0 ] = map.yPositions[ i ][ 0 ]; // Settings Up New CurrentY
        currentYPos[ 1 ] = map.yPositions[ i+1 ][ 0 ]; // Settings Up New CurrentY
        currentType = map.tilesType[ i ][ 0 ]; // Setting Up Current Type Type
        
        for( j = 0; j < map.depth; j++ )
        {
            if( !(map.yPositions[ i ][ j+1 ] == currentYPos[ 0 ]) || !(map.yPositions[ i+1 ][ j+1 ] == currentYPos[ 1 ]) || !(map.tilesType[ i ][ j+1 ] == currentType) || j == map.depth-1 )
            {
                glTexCoord2f( i, -j );
                glVertex3f( i*0.5, map.yPositions[ i ][ j+1 ], (j+1)*0.5 );
                glTexCoord2f( i+1, -j );
                glVertex3f( (i+1)*0.5, map.yPositions[ i+1 ][ j+1 ], (j+1)*0.5  );
        
                currentYPos[ 0 ] = map.yPositions[ i ][ j+1 ]; // Settings Up New CurrentY
                currentYPos[ 1 ] = map.yPositions[ i+1 ][ j+1 ]; // Settings Up New CurrentY
                currentType = map.tilesType[ i ][ j+1 ]; // Setting Up Current Type Type
                count +=1;
            }
        }
        glEnd();
    }
    NSLog( @"Polygons:%d",count );
    
    glDisable( GL_CULL_FACE ); // Disableing Cull Facings
    
    glEndList(); // Telling OpenGL We Are Done With The List
}
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #8
Well, the first thing I would do is get rid of triangle strips, just use gltriangles. It's not the fastest path on a lot of hardware. Use a display list for static terrain, a form of vertex array for dynamic terrain. Should give a nice speed boost.
Quote this message in a reply
Blake
Unregistered
 
Post: #9
DoG Wrote:Well, the first thing I would do is get rid of triangle strips, just use gltriangles. It's not the fastest path on a lot of hardware. Use a display list for static terrain, a form of vertex array for dynamic terrain. Should give a nice speed boost.

how could GL_TRIANGLES be faster than GL_TRIANGLE_STRIP when GL_TRIANGLES costs 3n (n = number of verticies) and GL_TRIANGLE_STRIP costs n+2?
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #10
'cos Q3A uses GL_TRIANGLES for everything Wink

It's also a bit easier for the display list optimizer, I believe.

Also remember that a strip longer than 65535 triangles falls back into slow mode, even in a display list, on all versions of Mac OS X so far...
Quote this message in a reply
Blake
Unregistered
 
Post: #11
okay now i got it to where it is quite quick by drawing only the tiles that are on the screen. Now if i could somehow check the x axis vertexs as well
Code:
- (void) drawBackground
{
    int i,j,currentType;
    float currentYPos[ 2 ],light;
    
    glEnable( GL_LIGHTING ); // Enable Lighting
    glEnable( GL_LIGHT0 ); // Enable Light 0
    
    /*
    * Dealing With Daylight
    if( countUp )
        daytime += 0.005;
    else
        daytime -= 0.005;
    
    if( daytime >= 2.0 )
        countUp = FALSE;
    if( daytime <= -1.0 )
        countUp = TRUE;
    
    light = daytime;
    if( daytime < 0 )
        light = 0;
    if( daytime > 1 )
        light = 1;
    */
    
    light = 0.5;
    float ambientLight[] = { light, light, light, 0.5f };
    glLightfv( GL_LIGHT0, GL_AMBIENT, ambientLight );  // Turning Lighting On
    
    glEnable( GL_CULL_FACE ); // Enable Cull Facings
    glCullFace( GL_FRONT ); // Telling OpenGL We Want To Draw The Fronts Of The Objects
    
    glPolygonMode( GL_FRONT, GL_FILL ); // Drawing And Filling Only The Front Of The Polygons
    
    glEnable( GL_TEXTURE_2D ); // Enabling Textures
    
    glEnable( GL_DEPTH_TEST ); // Enableing Depth Testing
    
    glColor3d( 1.0, 1.0, 1.0 ); // Setting It So That No Color Displacment Is Caused
    
    // Terrain
    glBindTexture( GL_TEXTURE_2D, terrainTextures[ 0 ].texID );
    for( i = [ self max:0 p2:(camera.x*2)-18 ]; i < [ self min:map.width p2:(camera.x*2)+18 ]; i++ )
    {
        glBegin( GL_TRIANGLE_STRIP );
        glTexCoord2f( i, 0 );
        glVertex3f( i*0.5, map.yPositions[ i ][ 0 ], 0 );
        glTexCoord2f( i+1, 0 );
        glVertex3f( (i+1)*0.5, map.yPositions[ i+1 ][ 0 ], 0 );
        
        currentYPos[ 0 ] = map.yPositions[ i ][ 0 ]; // Settings Up New CurrentY
        currentYPos[ 1 ] = map.yPositions[ i+1 ][ 0 ]; // Settings Up New CurrentY
        currentType = map.tilesType[ i ][ 0 ]; // Setting Up Current Type Type
        
        for( j = [ self max:0 p2:(camera.z*2)-26 ]; j < [ self min:map.depth p2:(camera.z*2)-2 ]; j++ )
        {
            if( !(map.yPositions[ i ][ j+1 ] == currentYPos[ 0 ]) || !(map.yPositions[ i+1 ][ j+1 ] == currentYPos[ 1 ]) || !(map.tilesType[ i ][ j+1 ] == currentType) || j == [ self min:map.depth p2:(camera.z*2)-2 ]-1 )
            {
                glTexCoord2f( i, -j );
                glVertex3f( i*0.5, map.yPositions[ i ][ j+1 ], (j+1)*0.5 );
                glTexCoord2f( i+1, -j );
                glVertex3f( (i+1)*0.5, map.yPositions[ i+1 ][ j+1 ], (j+1)*0.5  );
        
                currentYPos[ 0 ] = map.yPositions[ i ][ j+1 ]; // Settings Up New CurrentY
                currentYPos[ 1 ] = map.yPositions[ i+1 ][ j+1 ]; // Settings Up New CurrentY
                currentType = map.tilesType[ i ][ j+1 ]; // Setting Up Current Type Type
            }
        }
        glEnd();
    }
    
    glDisable( GL_CULL_FACE ); // Disableing Cull Facings
    
    glDisable( GL_LIGHTING );
    glDisable( GL_LIGHT0 );
}
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Optimizing CGLFlushDrawable Nick 3 3,698 Nov 27, 2006 06:48 PM
Last Post: OneSadCookie
  Optimizing rendering. jorgemonti 15 5,682 Apr 6, 2005 04:05 AM
Last Post: jorgemonti
  Optimizing for OpenGL on OS X aaronsullivan 3 3,328 Mar 22, 2005 02:36 PM
Last Post: Puzzler183
  optimizing dynamic geometry arekkusu 15 7,027 Nov 27, 2003 12:29 PM
Last Post: OneSadCookie
  optimizing OpenGL ghettotek 20 7,868 Feb 25, 2003 05:47 PM
Last Post: henryj