【问题标题】:OpenGL Texture UsageOpenGL 纹理使用
【发布时间】:2015-07-30 00:15:43
【问题描述】:

所以最近我开始阅读 OpenGL wiki 文章。这就是我对here 中描述的 OpenGL 纹理的描绘方式。不过,有几点还不清楚。

以下陈述是真、假还是依赖?

  1. 不可能将两个纹理绑定到同一个纹理单元。
  2. 不可能将两个采样器绑定到同一个纹理单元。
  3. 不可能将一个纹理绑定到两个不同的纹理单元。
  4. 不可能将一个采样器绑定到两个不同的纹理单元。
  5. 应用程序有责任明确将什么采样器类型传递给什么统一变量。
  6. 着色器程序有责任确保将采样器作为统一变量的正确类型。
  7. 纹理单元的数量足够大。让加载到应用程序的每个网格占用尽可能多的纹理单元。
  8. 某些采样器参数与纹理参数重复。它们将覆盖纹理参数设置。
  9. 某些采样器参数与着色器程序中的采样器描述重复。着色器程序的描述将覆盖采样器参数。

【问题讨论】:

    标签: c++ opengl


    【解决方案1】:

    我将在下面阅读您的陈述。有时我会与OpenGL 4.5 core profile specification 的引用争论。这些都不是 GL 4.5 特有的,我只是选择它,因为那是最新版本。

    1.将两个纹理绑定到同一个纹理单元是 不可能。

    如果我说“假”,那可能会产生误导。确切的说法是“将两个纹理绑定到同一纹理单元的同一目标是不可能的”。从技术上讲,您可以说,将 2D 纹理和 3D 纹理绑定到同一个单元。但是你不能在同一个绘图调用中使用。请注意,这是一个动态错误条件,取决于您将采样器制服设置为什么值。引用自 GL 规范的第 7.10 节“采样器”:

    不允许有不同采样器类型的变量 指向程序对象内的相同纹理图像单元。这 只能在下一个渲染命令发出时检测到这种情况 触发着色器调用,INVALID_OPERATION 错误将 然后生成。

    因此,当您实际尝试使用该着色器绘制某些东西(或以其他方式触发着色器调用)时,GL 将立即检测到此错误情况,同时您将其配置为两个采样器制服引用同一单元的不同目标。但这不是之前的错误。如果您暂时将两个制服设置为相同的值,但不尝试在该状态下进行绘制,则不会产生错误。

    2。将两个采样器绑定到同一个纹理单元是不可能的。

    您的意思可能是 Sampler Objects(与 GLSL 中的“采样器”类型相反),所以这是真的。

    3.将一个纹理绑定到两个不同的纹理单元是不可能的。

    错误。您可以将相同的纹理对象绑定到尽可能多的可用单元。然而,这是一个相当无用的操作。在固定功能管道的时代,有一些使用有限的极端情况。例如,我看到有人绑定相同的纹理两次并使用寄存器组合器将两者相乘,因为他需要一些平方运算。但是,使用着色器,您可以对纹理进行一次采样,然后对结果做任何您想做的事情,因此真的没有用例了。

    4.将一个采样器绑定到两个不同的纹理单元是不可能的。

    错误。单个采样器对象可以被多个纹理单元引用。您可以为您需要的每个采样状态创建一个采样器对象,无需创建多余的。

    5.应用程序有责任明确将什么采样器类型传递给什么统一变量。

    6.确保将采样器作为统一变量的正确类型是着色器程序的责任。

    我不确定你在这里问什么。着色器中的采样器变量选择纹理目标,并且还必须匹配您要使用的纹理对象的内部数据(即对于isamplerusampler,您将需要未标准化的整数纹理格式,否则结果未定义) .

    但我不知道“将什么采样器类型传递给什么统一变量”在这里应该是什么意思。就 GL 客户端而言,不透明采样器制服只是可以设置为要使用的纹理单元的索引的东西,并且可以通过glUniform1i 等以整数形式完成。没有“采样器类型”传递给统一变量。

    7.纹理单元的数量足够大。让加载到应用程序的每个网格占用尽可能多的纹理单元。

    一般情况下不会。 GL 4.5 规范要求的GL_MAX_TEXTURE_IMAGE_UNITS(它定义了片段着色器可以访问多少个不同的纹理单元)只有 16 个。(每个 shder 阶段都有单独的限制,所以有 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITSGL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 等等. 在当前规范中,它们都必须至少为 16。)

    通常,您必须在两次绘制调用之间切换纹理。使用array texturestexture atlasses 可能会进一步减少必要的状态切换次数(并最终减少绘图调用)。

    非常现代的 GPU 也支持GL_ARB_bindless_texture,它完全绕过了“纹理单元”层的间接性,并允许着色器通过一些不透明的句柄直接引用纹理对象(这基本上归结为引用下面的一些虚拟 GPU 内存地址引擎盖)。但是,该功能还不是 OpenGL 标准的一部分。

    8.一些采样器参数是纹理参数的副本。它们将覆盖纹理参数设置。

    是的。传统上,GL 中没有单独的采样器对象。相反,过滤或环绕模式等采样器状态是纹理对象本身的一部分。但现代硬件不以这种方式运行,因此采样器对象 API 已作为 GL_ARB_sampler_objects 扩展(现在是 GL 的核心功能)引入。如果采样器对象绑定到纹理单元,则其设置将覆盖纹理对象中存在的采样器状态。

    9.一些采样器参数与着色器程序中的采样器描述重复。着色器程序的描述将覆盖采样器参数。

    我不确定你的意思。着色器程序定义了哪些“采样器描述”?只有统一的声明和可能通过layout(binding=...) 进行的初始化。但是,这只是初始值。客户端可以通过将统一设置为另一个值来随时更新它,因此这并不是真正“覆盖”任何东西。但我不确定你是不是这个意思。

    【讨论】:

    • 感谢您的回答。我没有在 glsl 中区分采样器对象和采样器。着色器“程序的描述”是指着色器类型(sampler1D,sampler2D,sampler3D,...),因为我认为应用程序将设置采样器在将其传递给着色器程序之前将在纹理单元中查看的目标,并将其存储为范围。我猜那是错的?着色器对象仅引用纹理单元,“使用哪个目标”仅由 glsl 提供给该采样器的类型(sampler1D,..)决定。方向正确吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 2013-08-31
    相关资源
    最近更新 更多