【问题标题】:OpenGL - Fast Textured Quads?OpenGL - 快速纹理四边形?
【发布时间】:2011-10-02 13:36:12
【问题描述】:

我试图在 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);

我设置视点和视角:

glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

然后我加载一些纹理:

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);
}

最后我使用以下方法绘制了我的 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);

我发现所有这些代码都非常自我解释。不幸的是,据我所知,这种做事方式已被弃用。我在互联网上阅读了一些关于 PBO 和 vertexArrays 的模糊内容,但我没有找到任何关于如何使用它们的教程。我什至不知道这些对象是否适合实现我在这里尝试做的事情(屏幕上的十亿个四边形没有延迟)。也许这里的任何人都可以给我一个明确的建议,我应该使用什么来实现结果?如果您碰巧还有一分钟的空闲时间,您能否简要介绍一下这些功能的使用方式(就像我对上面已弃用的功能所做的那样)?

【问题讨论】:

  • 您可以考虑学习显示列表和顶点缓冲区对象。
  • @AlexandreC。那些不会有帮助的。他的问题是状态变化,缓冲区对象和显示列表无法修复。

标签: performance opengl


【解决方案1】:

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

什么是“结果”?你没有很好地解释你想要完成的究竟是什么。您所说的只是您正在尝试绘制许多带纹理的四边形。你想用那些带纹理的四边形做什么

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

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

在不知道您最终要渲染什么的情况下,我唯一能做的就是提供一般性能建议。按顺序(即:先做后做):

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

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

  3. 假设您的四边形是静态的(模型空间中的固定位置),请考虑使用buffer object 来存储和render with 您的四边形数据。

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

您是否尝试过OpenGL Wiki,它有一个pretty good list of tutorials(以及关于OpenGL 的一般信息)?为了充分披露,我确实写了其中一个。

【讨论】:

  • 哇!使用不同的图像区域在一张图片中存储多个纹理的想法是惊人的!会试试的。
  • 另外,正如您建议摆脱 glTranslate 的那样,似乎任何功能都应尽可能由 CPU 处理,以便 GPU 只需要自己进行渲染?
  • 非常感谢您提供的教程列表!没有直接在谷歌上找到它们,而且 OpenGL wiki 对于没有经验的搜索者来说是巨大而深奥的......
  • @Fejwin:摆脱glTranslate 更多的是这样您就不必为每个四边形做glBegin/glEnd。您可以在单个 glBegin/glEnd 调用中渲染多个四边形。此外,在 Wiki 上有一个“入门”页面,直接从 wiki 的主页链接。它有我链接到的教程列表。所以并不难找到。
  • 哦,好的,现在我明白了!我想知道 - 我的性能问题是否集中在我展示的最后一段代码(实际显示的四边形),还是我在初始化中也使用了一些不推荐使用的函数?或者可能是我加载(和存储)纹理的方式已经过时了?有什么要改变的吗?
【解决方案2】:

我听说,在现代游戏中,数以百万计的多边形是实时渲染的

实际上数以百万计。我猜你是德国人:“Milliarde”用英语翻译成“Billion”。

现在我正在学习一个古老的教程。

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

要达到实时渲染的三角形数量,您必须将所有几何数据放在“快速内存”中,即显卡的 RAM 中。 OpenGL 为此提供的技术称为“顶点缓冲区对象”。使用 VBO,您可以使用单个绘图调用(glDrawArrays、glDrawElements 及其亲属)绘制大量几何图形。

在消除几何图形后,您必须对 GPU 友好。如果您经常切换纹理或着色器,GPU 不喜欢它。切换纹理会使缓存的内容无效,切换着色器意味着停止 GPU 管道,但更糟糕的是,它意味着执行路径预测统计信息无效(GPU 统计着色器的哪些执行路径最有可能被执行以及它表现出的内存访问模式,这用于迭代优化着色器执行)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多