OpenGL - 快速纹理四边形?

Fej*_*win 5 opengl performance

我试图在3D空间中的随机位置显示尽可能多的纹理四边形.根据我的经验到目前为止,我甚至无法显示其中的几千个而不会将fps显着低于30(我的相机移动脚本变得迟钝).

现在我正在遵循一个古老的教程.初始化OpenGL后:

glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0, 0, 0, 0);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
Run Code Online (Sandbox Code Playgroud)

我设定了观点和观点:

glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Run Code Online (Sandbox Code Playgroud)

然后我加载一些纹理:

glGenTextures(TEXTURE_COUNT, &texture[0]);
for (int i...){
    glBindTexture(GL_TEXTURE_2D, texture[i]);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    gluBuild2DMipmaps(GL_TEXTURE_2D,3,TextureImage[0]->w,TextureImage[0]->h,GL_RGB,GL_UNSIGNED_BYTE,TextureImage[0]->pixels);
}
Run Code Online (Sandbox Code Playgroud)

最后我使用以下方法绘制GL_QUADS:

glBindTexture(GL_TEXTURE_2D, q);
glTranslatef(fDistanceX,fDistanceZ,-fDistanceY); 
glBegin(GL_QUADS);
    glNormal3f(a,b,c);
    glTexCoord2f(d, e); glVertex3f(x1, y1,  z1);
    glTexCoord2f(f, g); glVertex3f(x2, y2,  z2);
    glTexCoord2f(h, k); glVertex3f(x3, y3,  z3);
    glTexCoord2f(m, n); glVertex3f(x4, y4,  z4);
glEnd();
glTranslatef(-fDistanceX,-fDistanceZ,fDistanceY);
Run Code Online (Sandbox Code Playgroud)

我发现所有代码都非常自我解释.不幸的是,据我所知,这种做事方式已被弃用.我在互联网上读了一些关于PBO和vertexArrays的模糊的东西,但我没有找到关于如何使用它们的任何教程.我甚至不知道这些物体是否适合实现我在这里尝试做的事情(屏幕上有十亿个四边形而没有滞后).也许这里的任何人都可以给我一个明确的建议,我应该用什么来达到结果呢?如果你碰巧还有一分钟的业余时间,你能不能给我一些关于如何使用这些功能的简短摘要(就像我对上面弃用的那些功能一样)?

Nic*_*las 8

也许这里的任何人都可以给我一个明确的建议,我应该用什么来达到结果呢?

结果是什么"?你还没有很好地解释你想要完成的是什么.你所说的只是你想要绘制很多纹理四边形.你想用这些纹理四边形什么?

例如,在给定相同像素数据的情况下,您似乎创建了相同的纹理,具有相同的宽度和高度.但是您将它们存储在不同的纹理对象中.OpenGL不知道它们包含相同的数据.因此,在渲染四边形时,您会花费大量时间不必要地交换纹理.

如果你只是随机抽取它们来测试性能,那么这个问题毫无意义.这样的测试毫无意义,因为它们完全是人为的.他们只测试这种人为场景,每次渲染四边形时都会改变纹理.

在不知道你想要最终呈现什么的情况下,我唯一能做的就是提供一般性能建议.按顺序(即:在执行后面的操作之前执行第一个操作):

  1. 停止改变每个四边形的纹理.您可以在同一纹理中将多个图像打包在一起,然后只使用一次glBindTexture调用即可一次渲染使用该纹理的所有四边形.四边形的纹理坐标指定它使用的纹理内的哪个图像.

  2. 停止使用glTranslate以定位每个四边形.您可以使用它来定位四边形组,但您应该自己进行数学计算四边形的顶点位置.一旦这些glTranslate调用消失,您可以在一对空间中放置多个四边形glBegin/glEnd.

  3. 假设您的四边形是静态的(模型空间中的固定位置),请考虑使用缓冲区对象来存储和渲染四边形数据.

我在互联网上读了一些关于PBO和vertexArrays的模糊的东西,但我没有找到关于如何使用它们的任何教程.

您是否尝试过OpenGL Wiki,它有很好的教程列表(以及有关OpenGL的一般信息)?为了充分披露,我确实写了其中一个.


dat*_*olf 7

我听说,在现代游戏中,毫米的多边形是实时渲染的

实际上它数以百万计.我认为你是德国人:"Milliarde"用英语翻译成"十亿".

现在我正在遵循一个古老的教程.

这是你的主要问题.当代OpenGL应用程序不使用古老的渲染方法.您正在使用立即模式,这意味着您将通过几个函数调用来提交单个顶点.这是非常低效的.现代应用程序(如游戏)可以达到高三角计数,因为它们不会浪费CPU时间来调用尽可能多的函数,它们不会浪费CPU→GPU带宽与数据流.

为了实现实时渲染的高三角形数量,必须将所有几何数据放在"快速存储器"中,即位于图形卡的RAM中.OpenGL为此提供的技术称为"顶点缓冲对象".使用VBO,您可以使用单个绘图调用(glDrawArrays,glDrawElements及其亲属)绘制大批量的几何体.

在完成几何体之后,您必须对GPU很好.如果经常切换纹理或着色器,GPU不喜欢它.切换纹理使高速缓存的内容无效,切换着色器意味着停止GPU管道,但更糟糕的是,这意味着使执行路径预测统计无效(GPU统计着色器的哪些执行路径最有可能被执行)它展示了哪些内存访问模式,这用于迭代优化着色器执行).