GLSL渲染的纹理比纹理单元更多

时间:2014-05-25 02:33:31

标签: opengl glsl

假设你加载了一个有25个纹理的3d模型,但是你有8个纹理单位的限制。渲染所有纹理的最简单/最快捷的方法是什么。我认为会像... ...

1)加载纹理 2)将纹理纹理绑定到着色器纹理单元 3)渲染 4)循环到2)直到所有纹理渲染

我理解绑定是一个代价高昂的过程,所以不确定是否有更好的方法或者我的理论是否正确......

3 个答案:

答案 0 :(得分:4)

如果所有(或至少一些)纹理具有相同的大小,则可以使用数组纹理。您可以使用以下命令创建它们:

glTexImage3D(GL_TEXTURE_2D_ARRAY, ...);

depth参数将用于3D纹理,您传入数组中的纹理数量(也就是"图层"),并且对于最后一个参数始终为NULL,如果您只想分配内存。如果您使用OpenGL 4.2或更高版本,您还可以使用glTexStorage3D()来分配纹理内存。

然后,您可以使用glTexSubImage3D(GL_TEXTURE_2D_ARRAY, ...)存储数组中每个纹理的数据。

在着色器中,对类型纹理使用类型为sampler2DArray的变量,并使用3个纹理坐标对其进行采样,其中第3个"坐标为"确定采样哪个图层,对应于数组中的索引。

有时采用的完全不同的方法是使用更大的2D纹理,并将每个实际纹理存储为更大纹理的一部分。然后,您可以使用相应的纹理坐标范围控制对哪些纹理进行采样。假如你在一个纹理中存储了4个相同大小的纹理,宽度和高度都是两倍,你可以用范围内的纹理坐标(0 .. 0.5,0.0 .. 0.5)对第一个纹理进行采样,第二个纹理用(0.0 .. 0.5,0.5 .. 1.0),第三个(0.5 .. 1.0,0.0 .. 0.5),第四个(0.5 .. 1.0,0.5 .. 1.0)。这种方法通常称为"纹理图集"。

答案 1 :(得分:1)

这个答案是对Reto Koradi回答的旁注,我认为他的回答更为相关。但是,我想用真正的现代GPU添加GL_ARB_bindless_texture 它允许你使用尽可能多的纹理,你可以完全绕过任何GL"纹理单元"。

目前,此扩展程序不是核心OpenGL的一部分,并且仅在NVidia GPU上支持,因为" Kepler"自从" Graphics Core Next"架构。

答案 2 :(得分:1)

由于您正在讨论glsl,我认为值得指出的是纹理图像单元的数量实际上与您可以在传递中应用的离散纹理的数量分开。

例如,GL 3.3保证48个TIU(管道中每个阶段16个)......这48个单元允许您有足够的位置来绑定纹理,以便您可以使用一组16 不同的 Vertex,Geometry和Fragment着色器中的纹理。这样做 ,但是,这意味着您可以在片段着色器中对48种不同的纹理进行采样。

在着色器调用中可以采样的纹理数量存在每阶段限制(16 最小,并且它可能与每个阶段的限制不同)。还有一个适用于每个阶段的总限制(GL 3.3中的48 最小)。因此,虽然您可以在任何给定时间绑定 48个不同的纹理,但您仍然需要将您的绘图分成3个传递来实际应用所有48个。