2

我试图通过将我的纹理组合成数组纹理来优化我的代码(我意识到我不能使用纹理图集,因为大多数纹理都是重复的(在地面等))。我在 PyGame 和 PyOpenGL 工作,我以前从未使用过着色器。是否可以将单个阵列纹理与glBindTexture(GL_TEXTURE_2D_ARRAY, texname)并使用 3d 纹理坐标或其他东西来访问不同的图层?没有着色器甚至可能吗?

目前,我使用此函数为每个纹理调用 glDrawArrays:

def DRAW(im, array):
    glBindTexture(GL_TEXTURE_2D,im)
    glTexCoordPointer(2, GL_FLOAT, 32, array)
    glNormalPointer(GL_FLOAT, 32, array[2:])
    glVertexPointer(3, GL_FLOAT, 32, array[5:])
    glDrawArrays(GL_QUADS,0,len(array)/8)
4

2 回答 2

4

没有着色器就不能使用纹理数组。它们从来都不是固定功能管道的一部分。GL中没有GL_TEXTURE_2D_ARRAY启用位

固定功能片段处理在OpenGL 4.5 兼容性配置文件规范的第 16 节中指定。. 第 16.2 节规定:

阵列和多重采样纹理仅受着色器支持,可能无法用于固定功能纹理。

在原始的GL_EXT_texture_array扩展中,您会发现以下语句:

(2) 固定功能片段处理是否应该支持纹理数组?

已解决:否;人们认为这不值得付出努力。通过允许应用程序启用或禁用TEXTURE_1D_ARRAY_EXTTEXTURE_2D_ARRAY_EXT.

请注意,对于固定功能片段处理,具有阴影映射的二维数组纹理的纹理查找会出现问题。鉴于所有纹理查找都是投影的,总共需要五个坐标分量(s、t、层、深度、q)。

(3) 如果支持固定函数,在投影纹理查找中层数(T 或 R)是否应该除以 Q?

已解决:不需要在此扩展程序中解决,但这将是一个问题。在某些情况下,应用程序可能需要除法(处理 R 或多或少像 S/T);可能还有其他不需要这种划分的情况。许多开发者不会在意,甚至可能不知道 Q 坐标的用途!默认值 1.0 允许不关心投影查找的应用程序简单地忽略该事实。

对于可编程片段着色,应用程序可以使用任何一种方式对其进行编码并使用非投影查找。就投影查找除以 Q 在 OpenGL 硬件上“免费”或“便宜”而言,编译器可能能够识别计算坐标中的投影模式并适当地生成代码。

当数组纹理被提升为 OpenGL 核心功能时,这并没有改变。

于 2015-06-27T16:00:21.617 回答
3

正如@derhass 回答中的规范引用所示,没有着色器不支持数组纹理。

但是,您可以使用 3D 纹理来做几乎相同的事情。您将每个纹理存储在 3D 纹理层中。然后像往常一样使用前 2 个纹理坐标来确定纹理图像中的位置。第 3 个纹理坐标用于选择 3D 纹理中的图层。

要将图像加载到 3D 纹理中,请使用glTexSubImage3D(). 例如,假设您的纹理大小为 512x512,并且您想要加载纹理索引 20:

glTexSubImage3D(GL_TEXTURE_3D, 0,
    0, 0, 20, 512, 512, 1,
    GL_RGBA, GL_UNSIGNED_BYTE, data);

唯一稍微棘手的部分是正确计算第三个纹理坐标,因为纹理坐标是标准化的浮点数。特别是如果你使用线性采样,你必须准确地击中图层的中心,否则你会得到混合图像。

如果您n的 3D 纹理中有图层,则图层的纹理坐标为k

(k + 0.5f) / n

例如,使用n = 44 层的结果纹理坐标将是:

0.125f
0.375f
0.625f
0.875f

请注意这些值是如何按 0.25f 间隔的,如您所料,并在间隔内对称放置[0.0f, 1.0f]

使用 3D 纹理的一个缺点是它们的尺寸限制较小。使用这种方法,请确保您不超过MAX_3D_TEXTURE_SIZE.

我会鼓励你学习使用着色器。起初它可能看起来有点吓人,因为对于非常简单的用例来说,它肯定需要更多的工作。但是你会发现,一旦你掌握了窍门,当你的功能变得更复杂时,它们实际上会让事情变得更容易。编写 GLSL 代码来做你想做的事情通常要简单得多,而不是试图弄清楚如何正确设置几十个状态值来获得所需的结果。当然,着色器允许您实现在固定管道中根本不可能实现的功能。

于 2015-06-27T17:02:02.830 回答