gluScaleImage and 9 fps.

Moderator
Posts: 133
Joined: 2008.05
Post: #1
I'm working on a little terrain engine. I had it set up where it loaded a targa image in as a heightfield, rendered it using a repeated texture that looked like grass.

Well, now I set it up(modifying some code I found on the internet) so that it takes a 256x256 image and scales it across the entire terrain. Looks nifty, problem is what was once 60 fps is now 9. That is really bad....

Now, the code looks somewhat like this.
Code:
glNewList(terrainList,GL_COMPILE);
        glPushMatrix();
        glFrontFace(GL_CCW);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);
        
        glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        
        glEnable(GL_TEXTURE_2D);

        for(int z = 0;z<mapZ-1;z++)
        {
            for(int x = 0;x<mapX-1;x++)
            {
                LoadTile(z,x);
                glBegin(GL_TRIANGLE_STRIP);
                    glTexCoord2f(0.0, 1.0); glVertex3f(terrain[x][z+1][0],terrain[x][z+1][1],terrain[x][z+1][2]);
                    glTexCoord2f(0.0, 0.0); glVertex3f(terrain[x][z][0],terrain[x][z][1],terrain[x][z][2]);
                    glTexCoord2f(1.0, 1.0); glVertex3f(terrain[x+1][z+1][0],terrain[x+1][z+1][1],terrain[x+1][z+1][2]);
                    glTexCoord2f(1.0, 0.0); glVertex3f(terrain[x+1][z][0],terrain[x+1][z][1],terrain[x+1][z][2]);
                glEnd();
            }
        }
        glDisable(GL_DEPTH_TEST);
        glDisable(GL_CULL_FACE);
        
        glPopMatrix();
    glEndList();

When I move glBegin(GL_TRIANGLE_STRIP) and glEnd() outside of the double loop, it doesn't work, it just repeats a small portion of the picture.
Here is LoadTile:
Code:
void XTerrain::LoadTile(int row, int col)
{
    int border = 1; //switch to 0 for no border
    int level, levelWidth, levelHeight;

    levelWidth = texWidthLevel0;
    levelHeight = texHeightLevel0;
    for (level=0; level<=maxTextureLevel; ++level)
    {
    int tileWidth = levelWidth / texWidthTiles;
    int tileHeight = levelHeight / texHeightTiles;
    int skipPixels = col * tileWidth + (1 - border);
    int skipRows = row * tileHeight + (1 - border);

    glPixelStorei(GL_UNPACK_ROW_LENGTH, levelWidth+2);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, skipPixels);
    glPixelStorei(GL_UNPACK_SKIP_ROWS, skipRows);

    glTexImage2D(GL_TEXTURE_2D, level, 4,
             tileWidth + 2*border, tileHeight + 2*border,
             border, GL_RGBA, GL_UNSIGNED_BYTE, texImageLevel[level]);
    
    if (levelWidth > 1) levelWidth = levelWidth / 2;
    if (levelHeight > 1) levelHeight = levelHeight / 2;
    }

    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
}


The only problem with this code is...I'm not completly sure what it does, I just know it works real slow. Smile Any help speeding this up would be super.
Quote this message in a reply
Moderator
Posts: 437
Joined: 2002.09
Post: #2
This is code that sets up a display list "terrainList". Are you calling this code each frame? If so, you shouldn't. Just use the display list that it builds.

Measure twice, cut once, curse three or four times.
Quote this message in a reply
Mars_999
Unregistered
 
Post: #3
Make sure you check to see if you are doing what Matt said. Do not make a new display list each frame move that display list out of the rendering loop into initialization or somewhere else.

I don't know what you are doing for sure with LoadTile() but I would get rid of that and get a .tga or whatever texture loader on the net and load a .tga texture and setup that texture and Bind it once and if you decide to add in more textures you will have to either rebind the texture or use multi-texturing.

Speed up, do what I stated above, and either use vertex arrays and not immediate mode or if Mac has them use VBO's. Culling will also speed up your engine.

HTH.
Quote this message in a reply
Moderator
Posts: 608
Joined: 2002.04
Post: #4
Quote:Originally posted by Mars_999
Speed up, do what I stated above, and either use vertex arrays and not immediate mode or if Mac has them use VBO's. Culling will also speed up your engine.
I am not sure if vertex arrays would be much faster than a display list.

I am doing almost the same thing, except that I am tiling my texture. I get about 55 FPS solid on my 600 MHz G3 so it appears that your scaling of the texture is the slow down.
Quote this message in a reply
Mars_999
Unregistered
 
Post: #5
Quote:Originally posted by jabber
I am not sure if vertex arrays would be much faster than a display list.

I am doing almost the same thing, except that I am tiling my texture. I get about 55 FPS solid on my 600 MHz G3 so it appears that your scaling of the texture is the slow down.


Oh it will if you are not culling your terrain and if he is using map_x as his map size and its 256x256 like mine. Hold on the speed breaks are engaged if he is going to use immediate mode. WAY TO MUCH overhead. That is alot of function calls per frame for the CPU.

But you maybe right Jabber if he is only doing something like 32x32 immediate mode is ok to play around with.

And if I remember right vertex arrays are never to be slower than a display list but could be faster than one depending on your situation.
Quote this message in a reply
Moderator
Posts: 133
Joined: 2008.05
Post: #6
Quote:Originally posted by MattDiamond
This is code that sets up a display list "terrainList". Are you calling this code each frame? If so, you shouldn't. Just use the display list that it builds.


I'm not sure what you mean. I create the list and each frame it calls glCallList(terrainList); Are you thinking that I'm setting up the list and then just rewriting the code in my draw function? I'm not _that_ dumb. Smile

As for what you are suggesting...if I bind a texture, it's going to repeat this texture across each triangle strip and the whole thing will be one texture. I am displaying a picture that is 256x256 over an entire terrain, so if the terrain were flat it would look exactly like the picture file if you viewed it in photoshop.

And yes, the terrain is 32x32 and the map scale is 10.

LoadTile takes a chunk of an image file and uses that as the texture for that one triangle strip.
Quote this message in a reply
Mars_999
Unregistered
 
Post: #7
Quote:Originally posted by LongJumper
I'm not sure what you mean. I create the list and each frame it calls glCallList(terrainList); Are you thinking that I'm setting up the list and then just rewriting the code in my draw function? I'm not _that_ dumb. Smile

As for what you are suggesting...if I bind a texture, it's going to repeat this texture across each triangle strip and the whole thing will be one texture. I am displaying a picture that is 256x256 over an entire terrain, so if the terrain were flat it would look exactly like the picture file if you viewed it in photoshop.

And yes, the terrain is 32x32 and the map scale is 10.

LoadTile takes a chunk of an image file and uses that as the texture for that one triangle strip.


Unless I am missing something you aren't stretching the image across your 32x32 map. You are tiling it. Your texture coordinates are 0.0 and 1.0.

Also you might want to disable texturing at the end of that display list as it stands you are trying to enable texturing each time its called
Quote this message in a reply
chainsawmcgraw
Unregistered
 
Post: #8
**Warning: I'm a newbie, so take my advice with a grain of salt**

It appears like you're calling glTexImage2d every frame and multiple times in that frame (within loadTile). It is my understanding that glTexImage2d sends the texture data to the opengl context. Doing this multiple times during every frame may cause some slowdown (if I understand glTexImage2d) and it may be better to initialize some texture objects at the beginning, and then reference them every frame.

And just so I'm clear: Is any of what I'm saying correct? Wacko
Quote this message in a reply
Moderator
Posts: 437
Joined: 2002.09
Post: #9
Quote:Originally posted by chainsawmcgraw
**Warning: I'm a newbie, so take my advice with a grain of salt**

It appears like you're calling glTexImage2d every frame and multiple times in that frame (within loadTile). It is my understanding that glTexImage2d sends the texture data to the opengl context. Doing this multiple times during every frame may cause some slowdown (if I understand glTexImage2d) and it may be better to initialize some texture objects at the beginning, and then reference them every frame.

And just so I'm clear: Is any of what I'm saying correct? Wacko


Longjumper assures us that LoadTile is not being called every frame. So what you say would only be true if the _loading_ of the texture was itself stored in the display list, but display lists don't store that step, just the operations involving the texture object itself.

As Mars says, this should all be doable with only one texture object, simply by setting the texture coords properly for each vertex.

I also recommend running it through a profiler. Unfortunately, display lists tend to hide the details of what's going on, but at least Longjumper could verify that most of the time is being spent in the display list and not somewhere else.

Possibly Longjumper is running into a "slow path" conditions with the display list. Might want to search Apple's opengl mailing list archives; people there sometimes discuss specific cases that cause sudden slowdowns, usually because they disable hardware acceleration.

What version of MacOS you are running? What video card?

Measure twice, cut once, curse three or four times.
Quote this message in a reply
chainsawmcgraw
Unregistered
 
Post: #10
I see. So display lists only take into account gl commands. My bad. Blush
Quote this message in a reply
Mars_999
Unregistered
 
Post: #11
Quote:Originally posted by chainsawmcgraw
I see. So display lists only take into account gl commands. My bad. Blush


And to top that off only certain OpenGL commands. Good to see you around chainsaw when did you break away from IMG??Wow
Quote this message in a reply
Member
Posts: 269
Joined: 2005.04
Post: #12
I'll bet you anything that the slowdown is being caused by LoadTile. Breaking up a large single texture into multiple little textures like that is a bad idea. Just bind the texture once before you enter the for loops, remove the call to LoadTile, and fix the texture coordinates in the glTexCoord2f calls.

Also, display lists and vertex arrays are about equal in speed in X.2. However, if you use vertex arrays then you can use VAR extension (GL_APPLE_vertex_array_range) which is a huge speedup if your card supports it. My fps jumped from 70 to 125 after I implemented VAR.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #13
Display lists on 10.2 use VAR if able... in my experience, they're very much the fast path. On 10.1, display lists are slow and there is no VAR...

Straight vertex arrays are a huge step up on immediate mode for speed, but they're very slow compared to what's possible.
Quote this message in a reply
Member
Posts: 269
Joined: 2005.04
Post: #14
As long as we're on VAR and vertex array extensions...

Is ARB_vertex_buffer_object in Panther? Isn't it supposed to be the bee's knees on the PC side as far as vertex arrays go?
Quote this message in a reply
Mars_999
Unregistered
 
Post: #15
Quote:Originally posted by Bachus
As long as we're on VAR and vertex array extensions...

Is ARB_vertex_buffer_object in Panther? Isn't it supposed to be the bee's knees on the PC side as far as vertex arrays go?


I am using VBO's on my PC. I have used both vertex arrays and VBO for the same engine. In my experience VBO's are faster.
Quote this message in a reply
Post Reply