【问题标题】:How to speed up offscreen OpenGL rendering with large textures on Win32?如何在 Win32 上使用大纹理加速屏幕外 OpenGL 渲染?
【发布时间】:2010-07-22 17:03:15
【问题描述】:

我正在开发一些 C++ 代码,可以在两个图像之间做一些花哨的 3D 过渡效果,我认为 OpenGL 是最好的选择。

我从一个 DIB 部分开始并为 OpenGL 设置它,然后从输入图像创建两个纹理。

然后对于每一帧,我只绘制两个带有相应图像纹理的 OpenGL 四边形。 然后将 DIB 内容保存到文件中。

例如,一种效果是将两个四边形(在 3d 空间中)定位为两个广告牌,一个在另一个前面(遮挡它),然后将相机向上、向前和向下俯冲,这样您就可以看到第二个.

我的输入图像是 1024x768 左右,当四边形覆盖大部分视图时,渲染需要很长时间(100 毫秒)。如果相机很远,它会加快速度。

我尝试将每个图像四边形渲染为数百个单独的图块,但它只需要相同的时间,似乎它取决于可见纹理像素的数量。

我认为 OpenGL 每秒可以处理无数个多边形。我在这里有什么遗漏吗?

使用其他方法会更好吗?

提前谢谢...

编辑:

对于 DIB 版本,GL 字符串显示为:

供应商:微软公司 版本:1.1.0 渲染器:GDI 通用

屏幕版本显示: 供应商:ATI Technologies Inc. 版本:3.2.9756 兼容性配置文件上下文 渲染器:ATI Mobility Radeon HD 3400 系列

所以我想我将不得不使用 FBO,对于如何将渲染数据从 FBO 获取到 DIB 上,我有点困惑,是否有任何指针(双关语)?

【问题讨论】:

  • 您在什么硬件/软件上运行它?听起来像是填充率/内存带宽问题。
  • 我在笔记本电脑上进行测试,Core2 Duo 2.6 ghz,Windows 7 x64,显示适配器是 ATI Radeon 3400 系列,具有 256 MB VRAM 我刚刚编写了一个基于 GLUT 的测试应用程序来在屏幕上绘制类似的东西,并且它在可忽略的时间内渲染每一帧。问题是为什么它在 DIB 上表现如此糟糕......
  • 在您从 DIB 获得的上下文中仔细检查 OpenGL 版本/供应商。您可能遇到了软件渲染路径。
  • 是的,很可能是软件路径。

标签: c++ opengl winapi


【解决方案1】:

听起来像渲染到 DIB 会强制渲染在软件中进行。我会渲染到一个帧缓冲区对象,然后从生成的纹理中提取数据。 Gamedev.net 有一个相当不错的tutorial

但请记住,图形硬件主要面向在屏幕上绘图。捕获渲染数据通常会比显示数据慢,即使您确实让硬件进行渲染 - 尽管它仍然应该比软件渲染快很多。

编辑:Dominik Göddeke 有一个 tutorial,其中包含用于将纹理数据读回 CPU 地址空间的代码。

【讨论】:

  • 离屏 FBO 在任何合理的最新图形硬件上不应明显比屏幕缓冲区慢。
  • @Carlos:对不起,我的措辞很糟糕。渲染到 FBO 并不会(通常)变慢——但之后从纹理中读取数据通常会很慢。
  • @Jerry:如果“读取”是指 CPU 回读,那么您是对的。但是,如果您只想将这些 FBO 用作 GPU 纹理以供以后渲染,那么性能损失应该可以忽略不计(特别是如果使用具有更大纹理和视口技巧的相同 FBO)
  • @Carlos:对——当他说“然后将 DIB 内容保存到文件中”时,我认为他的意思是 CPU 回读,然后 CPU 将数据写入文件。
  • @Carlos :我确实需要获取每一帧的渲染位。这是我的客户将集成到某种视频应用程序中的模块的一部分,因此在我的代码中,我只获得 2 个 DIB 并返回 1 个带有内容的 DIB。我想我会向我的客户提出这一点,即如果打算将其编码成视频,那么性能对于这段代码真的无关紧要,即使只是简单地将其作为 BMP 转储到磁盘也比渲染过程慢得多。
【解决方案2】:

您的问题有一个问题:
您没有提供实际的渲染/纹理生成代码。

使用其他方法会更好吗?

您可以做的最简单的事情是确保您的纹理大小等于 2 的幂。 IE。而不是 1024x768 使用 1024x1024,并且只使用该纹理的一部分。说明:尽管大多数现代硬件都支持非 pow2 纹理,但它们有时被视为“特殊情况”,使用此类纹理可能会在某些硬件上产生性能下降。

我认为 OpenGL 每秒可以处理无数个多边形。我在这里有什么遗漏吗?

是的,你错过了一件重要的事情。限制 GPU 性能的因素很少:
1. 系统内存到视频内存的传输速率(可能不是您的情况 - 仅适用于动态纹理\几何,当数据每帧都发生变化时)。
2. 计算成本。 (如果你编写一个计算量很大的着色器,它会很慢)。
3. 填充率(程序每秒可以在屏幕上放置多少像素),AFAIK 取决于现代 GPU 上的内存速度。
4. 顶点处理速率(不是你的情况)——GPU 每秒可以处理多少个顶点。
5. 纹理读取率(GPU 每秒可以读取多少纹素),在现代 GPU 上取决于 GPU 内存速度。
6.纹理读取缓存(不是您的情况)-即在片段着色器中,如果坐标彼此非常接近(即每次读取中几乎相同的纹素),您可以每个像素读取数百次纹理而性能下降很小(即每次读取中几乎相同的纹素)-因为结果被缓存.但是,如果您尝试为每个像素访问 100 个随机定位的纹素,性能将会显着下降。

所有这些特性都取决于硬件。

即,根据某些硬件,您可能每帧可以渲染 1500000 个多边形(如果它们占用少量屏幕空间),但如果每个多边形填满整个屏幕,您可以使用 alpha 使 fps 达到 100 个多边形- 混合并具有高度详细的纹理。

如果您仔细考虑一下,您可能会注意到有很多显卡可以绘制风景,但是当您进行帧缓冲效果(如模糊、HDR 等)时,fps 会下降。

此外,如果您有内置 GPU,则纹理表面的性能可能会下降。当我在以前的主板上炸 PCIEE 插槽时,我不得不使用内置 GPU(NVidia 6800 或其他东西)。结果并不令人愉快。虽然 GPU 支持着色器模型 3.0 并且可以使用计算量相对较大的着色器,但每次屏幕上有纹理对象时,fps 都会迅速下降。显然是因为内置 GPU 将部分系统内存用作显存,而“普通”GPU 内存和系统内存中的传输速率不同。

【讨论】:

  • 您不需要调整纹理的大小。 2 的幂仅适用于宽度,高度无关紧要,因为纹素被寻址为 (x + y * width),如果宽度是 2 的幂,则它变为 (x + (y
  • @Skizz:“2 的幂只真正适用于宽度,高度无关紧要”这是我第一次听到这样的事情(适用于实际硬件)。那么,你能用实际的 GPU 制造商、微软或 openGL 文档中的话来支持你的论点吗?不要忘记纹理坐标会环绕,而对于 pow2 坐标,环绕更容易。
  • 是的,我尝试了各种纹理标志,但使用 glTexImage2D 而不是 gluBuild2DMipmaps,渲染效果确实有 1.5 倍到 2 倍的差异。此外,gluBuild2DMipmaps 调用每一帧的成本非常高(因为我的输入图像是动态变化的)。也许是因为它通过缩放图像创建了几个 mipmap? glTexImage2D 大约快 30 倍,尽管我知道结果看起来不如 gluBuild2DMipmaps,但我可以接受。
  • @rep_movsd:OpenGL 从 1.4 版开始支持自动生成 mipmap。 “glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE);”。见opengl.org/sdk/docs/man/xhtml/glTexParameter.xml
  • @Skizz:“更大的纹理需要更多的内存带宽和更多的 RAM 页面,这意味着渲染速度更慢”这是不正确的。虽然更多的带宽会减慢渲染速度,但更多的 RAM 页面根本不会影响渲染速度。在游戏开发中,通常建议使用大纹理“图集”——包含多个较小纹理(例如 1024 128x128 纹理)的巨大纹理(4096x4096 或更大)。地图集的目的是避免调用与 CPU 相关的函数并使对象“批量”(以加快速度)。 ...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-24
  • 1970-01-01
  • 2014-03-18
  • 1970-01-01
  • 2012-08-22
  • 1970-01-01
  • 2018-10-08
相关资源
最近更新 更多