Pregunta

I have strange problem:
I have to output a game-floor with 15x15 Elements.
Up to now, I called my function "printFloor()" in a game-loop.

This function steped through all 225 elements and according to their value, it displays a different part of a texture-File. So the CPU had to render the same 225 Textures in every loop cycle. The game-loop needed about 16-32ms for each cycle, so I now put this output in a display-list:

if(!gamefloorPrepared)  //no Display list created -> this is the first time the floor nees to
                        //be printed
{   gamefloor = glGenLists(1);

    glNewList(gamefloor,GL_COMPILE);
        for(int y=0;y<size.y;y++)
        {   for(int x=0;x<size.x;x++)
            {   printFloorElement(spielfeld[y][x],{x,y});     //see below
            }
        }
    glEndList();
    gamefloorPrepared=1;
}else
{   glCallList(gamefloor);
}

The function printFloorElement calculates the position, changes the graphic mode to "switchGraphicMode(TEXTURES);", binds the Texture and draws the texture:

glBegin(GL_QUADS);
    glTexCoord2f(spriteSize.x* spritePos.x   +halfTexelSize.x,spriteSize.y*(spritePos.y+1)-halfTexelSize.y);   glVertex2f(display.a.x,display.a.y);
    glTexCoord2f(spriteSize.x* spritePos.x   +halfTexelSize.x,spriteSize.y* spritePos.y   +halfTexelSize.y);   glVertex2f(display.a.x,display.b.y);
    glTexCoord2f(spriteSize.x*(spritePos.x+1)-halfTexelSize.x,spriteSize.y* spritePos.y   +halfTexelSize.y);   glVertex2f(display.b.x,display.b.y);
    glTexCoord2f(spriteSize.x*(spritePos.x+1)-halfTexelSize.x,spriteSize.y*(spritePos.y+1)-halfTexelSize.y);   glVertex2f(display.b.x,display.a.y);
glEnd();

The Problem: One game-loop cycle needs 60-80ms now, so its quite slower. The display-list is generated only once, I already checked that.

The "switchGraphicMode()"-Function:

void switchGraphicMode(GRAPHICMODES target)//can be "TEXTURES" or "DRAWING"
{   if(target != graphicMode)//"gaphicMode" = global Variable which shows if GL_TEXTURE_2D is currently enabled
    {   if(target==DRAWING)
        {   glDisable(GL_TEXTURE_2D);
            graphicMode=DRAWING;
        }else
        {   glEnable(GL_TEXTURE_2D);
            graphicMode=TEXTURES;
        }
    }
}

Anyone know the reason?

¿Fue útil?

Solución

glBegin()/glEnd() and displaylists are part of the deprecated "immediate mode" pipeline.

The preferred method now is to use vertex buffer objects.

The difference between these two methods is that in immediate mode, each time through the render loop, you are transferring vertex data from host memory to the GPU, even if you are using display lists (display lists are maintained on the host and not the display card).

A vertex buffer object is a memory buffer that is maintained in the memory of the display card. You set it up once, then transfer your vertex data all at once before you start rendering. Then each time through the render loop, you call specialized drawing functions that tell the display card to draw using data from that buffer, thus avoiding the need to perform costly host to display card data transfers.

Using vertex buffer objects requires a bit more set-up than immediate mode rendering, but the speed-up is well worth it. Google opengl vertex buffer objects. There should be plenty of tutorials and example code to get you started.

Otros consejos

It is hard to tell with these code snippets, but for the first step I would suggest you making advantage of batching when filling your DisplayList, which it seems you miss:

glEnable(GL_TEXTURE_2D);

if(!gamefloorPrepared)
{   gamefloor = glGenLists(1);

    glNewList(gamefloor,GL_COMPILE);
    glBegin(GL_QUADS);
        for(int y=0;y<size.y;y++)
        {   for(int x=0;x<size.x;x++)
            {   
                glTexCoord2f(spriteSize.x* spritePos.x   +halfTexelSize.x,spriteSize.y*(spritePos.y+1)-halfTexelSize.y);   glVertex2f(display.a.x,display.a.y);
                glTexCoord2f(spriteSize.x* spritePos.x   +halfTexelSize.x,spriteSize.y* spritePos.y   +halfTexelSize.y);   glVertex2f(display.a.x,display.b.y);
                glTexCoord2f(spriteSize.x*(spritePos.x+1)-halfTexelSize.x,spriteSize.y* spritePos.y   +halfTexelSize.y);   glVertex2f(display.b.x,display.b.y);
                glTexCoord2f(spriteSize.x*(spritePos.x+1)-halfTexelSize.x,spriteSize.y*(spritePos.y+1)-halfTexelSize.y);   glVertex2f(display.b.x,display.a.y);
            }
        }
    glEnd();
    glEndList();
    gamefloorPrepared=1;
}else
{  
 glCallList(gamefloor);    
}
glDisable(GL_TEXTURE_2D);

This way all of the vertex within your display list are within one GL_QUADS clause and there are no unnecessary texture_2d state changes.

P.S. Someone should add a comment about deprecated functionality ;)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top