我有个奇怪的问题:
我必须输出一个15x15元素的游戏地板。
到目前为止,我在游戏循环中调用了我的函数"printFloor()“。
此函数遍历所有225个元素,并根据它们的值显示纹理文件的不同部分。因此CPU必须在每个循环周期中渲染相同的225个纹理。游戏循环每个周期大约需要16-32ms,所以我现在把这个输出放在一个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);
}函数printFloorElement计算位置,将图形模式更改为"switchGraphicMode(TEXTURES);",绑定纹理并绘制纹理:
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();问题:一个游戏循环周期现在需要60-80ms,所以它相当慢。display-list只生成一次,我已经检查过了。
"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;
}
}
}有人知道原因吗?
发布于 2012-11-13 14:47:41
glBegin()、/glEnd()和displaylists是过时的“立即模式”管道的一部分。
现在首选的方法是使用顶点缓冲区对象。
这两种方法之间的区别在于,在即时模式下,每次通过渲染循环,都会将顶点数据从主机内存传输到GPU,即使您使用的是显示列表(显示列表维护在主机上,而不是显示卡上)。
顶点缓冲器对象是在显示卡的存储器中维护的存储器缓冲器。只需设置一次,然后在开始渲染之前一次性传输所有顶点数据。然后,每次通过渲染循环,调用专门的绘图函数,这些函数告诉显示卡使用该缓冲区中的数据进行绘制,从而避免了执行昂贵的主机来传输显示卡数据的需要。
使用顶点缓冲区对象需要比即时模式渲染更多的设置,但加速是非常值得的。Google opengl顶点缓冲区对象。应该有大量的教程和示例代码来帮助您入门。
发布于 2012-11-12 17:18:49
使用这些代码片段很难判断,但对于第一步,我建议您在填充DisplayList时利用批处理,这似乎是您遗漏的:
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);这样,显示列表中的所有顶点都在一个GL_QUADS子句中,并且没有不必要的texture_2d状态更改。
附注:有人应该添加关于弃用功能的评论;)
https://stackoverflow.com/questions/13339427
复制相似问题