【问题标题】:Can OpenGL ES render textures of non base 2 dimensions?OpenGL ES 可以渲染非基本二维的纹理吗?
【发布时间】:2010-09-18 01:57:40
【问题描述】:

在我深入研究将当前的渲染系统转换为 openGL 之前,这只是一个简单的问题。我听说纹理需要以 2 为基础大小才能存储以进行渲染。这是真的?

我的应用程序的内存非常紧张,但大多数位图都不是 2 的幂。存储非 base 2 纹理会消耗更多内存吗?

【问题讨论】:

  • 二的幂!=平方。 32x64 是 2 的幂,不是平方,13x13 是平方,不是 2 的幂。
  • 好点。不过,无论哪种方式,它都必须是非二的幂。

标签: android opengl-es textures


【解决方案1】:

确实取决于 OpenGL ES 版本,OpenGL ES 1.0/1.1 有两个限制。 OpenGL ES 2.0 没有这个限制,但是它限制了两个纹理的非幂的包裹模式。

创建更大的纹理以匹配 POT 尺寸确实会浪费纹理内存。

【讨论】:

  • 那么绝对没有办法在不浪费内存的情况下用openGL渲染非幂的两个大小的位图?这很烦人。哦,好吧,很高兴我还没有开始检查我的代码。
  • 对了,你应该知道OpenGL ES和OpenGL没有同样的限制,OpenGL 2.0及更高版本直接支持NPOT纹理。
  • OpenGL ES 2.0 使用两个纹理的非幂时的环绕模式有哪些限制?
  • @dirhem 没有 mipmap,仅支持 GL_CLAMP_TO_EDGE 作为包装模式。请参阅khronos.org/opengles/sdk/docs/man/xhtml/glTexParameter.xml中的注释
【解决方案2】:

Suresh,在计算机图形学的(非常)早期(在负担得起的硬件加速之前),OpenGL 就内置了 2 的力量限制,并且出于性能原因这样做。当低级渲染代码可以被硬编码为二次幂纹理时,它会获得不错的性能提升。即使在现代 GPU 中,POT 纹理也比 NPOT 纹理快,但速度差异比以前小得多(尽管在许多 ES 设备上可能仍然很明显)。

GuyNoir,你应该做的是建立一个纹理图集。上周末我自己为自己的 Android 游戏解决了这个问题。我创建了一个名为 TextureAtlas 的类,它的构造函数调用 glTexImage2D() 来创建我选择的任何大小的大纹理(为像素值传递 null)。然后我可以调用 add(id, bitmap),它调用 glTexSubImage2D(),重复地打包较小的图像。 TextureAtlas 类跟踪较大纹理中的已用和可用空间以及存储每个位图的矩形。然后渲染代码可以调用 get(id) 来获取图集中图像的矩形(然后可以将其转换为纹理坐标)。

旁注#1:选择以各种纹理尺寸打包的最佳方式并非易事。我选择从 TextureAtlas 类中的简单逻辑开始(想想打字机 + 回车 + 换行),并确保我以最佳顺序加载图像以利用该逻辑。就我而言,那是从最小的方形图像开始,然后逐步发展到中等方形图像。然后我加载任何短+宽图像,强制 CR+LF,然后加载任何高+瘦图像。我最后加载最大的方形图像。

附注 #2:如果您需要多个纹理图集,请尝试将每个内部的图像组合在一起,将它们一起渲染,以最大限度地减少您需要切换纹理的次数(这会影响性能)。例如,在我的Android游戏中,我将所有静态棋盘元素放在一个图集中,将各种动画效果的所有帧放在第二个图集中。这样我可以绑定图集#1并在游戏板上绘制所有内容,然后我可以绑定图集#2并在其上绘制所有特效。每帧选择两个纹理非常有效。

附注 #3:如果您需要重复/镜像纹理,它们需要进入自己的纹理,并且您需要缩放它们(而不是添加黑色像素来填充边缘)。

【讨论】:

  • 是的,我考虑过类似的事情。唯一的问题是仍然存在少量浪费的内存,并且在我不断突破 24mb 界限的程序中,我需要我能获得的所有内存。
【解决方案3】:

不,它必须是 2base。但是,您可以通过在图像的顶部和/或底部添加黑条来解决此问题,然后使用纹理坐标数组来限制从图像映射纹理的位置。例如,假设您有一个 13 x 16 像素的纹理。您可以在右侧添加 3 个黑色像素,然后执行以下操作:

static const GLfloat texCoords[] = {
        0.0, 0.0,
        0.0, 13.0/16.0,
        1.0, 0.0,
        1.0, 13.0/16.0
    };

现在,您有一个 2base 图像文件,但有一个非 2base 纹理。只要确保你使用线性缩放:)

【讨论】:

  • 这里的问题是浪费纹理内存;我的申请非常迫切。
【解决方案4】:

这有点晚了,但 OpenGL ES 1/2 下通过扩展支持非幂次 2 纹理

主要的是GL_OES_texture_npot。 iOS 设备还有 GL_IMG_texture_npot 和 GL_APPLE_texture_2D_limited_npot

通过调用glGetString(GL_EXTENSIONS) 并搜索您需要的扩展来检查这些扩展。

我还建议将纹理保持为 4 的倍数,因为如果不是,某些硬件会拉伸纹理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    相关资源
    最近更新 更多