纹理在着色器中是如何引用的?

3

快速的OpenGL新手问题。我在我的片段着色器中有这行代码:

uniform sampler2D mytexture;

我检索了我正在使用的示例代码,并没有找到任何有关“mytexture”的参考;只发现调用了激活纹理单元并将先前复制到GPU的纹理绑定到它的调用。
我的问题是,片段着色器如何知道我使用的唯一纹理必须通过mytexture来引用?
我原以为一个
glBindTextureToUniform(texture_id, "mytexture");

或类似的东西必须被调用。


1
不完全是同一个问题,但这个链接涵盖了非常相似(甚至更多)的内容:https://dev59.com/44zda4cB1Zd3GeqPjDHx。 - Reto Koradi
2个回答

7
映射是在纹理单元和统一变量之间进行的,而不是纹理本身,正如concept3d所提到的。这种差异的原因是多重纹理。
纹理单元是OpenGL中用于实现多重纹理的机制。当您想要在着色器中查找多个纹理时,将每个纹理绑定到不同的纹理单元(实际上将其绑定到单元内的目标)并为每个纹理单元设置不同的统一变量以在着色器中引用它们。每个纹理单元都有多个目标,如1D、2D、3D等。
在着色器中查找的纹理通过统一变量引用单元。它的类型(例如sampler2D)决定了使用的单元中的目标。以下是映射方式:
统一变量sampler2D mytexture; | | | | | +--->GL_TEXTURE0 / UNIT 0 GL_TEXTURE1 / UNIT 1 GL_TEXTURE2 / UNIT 2 | +--------------------+ +--------------------+ +--------------------+ | | +------------+ | | +------------+ | | +------------+ | | | | TEXTURE_1D | | | | TEXTURE_1D | | | | TEXTURE_1D | | | | +------------+ | | +------------+ | | +------------+ | | | +------------+ | | +------------+ | | +------------+ | +---------------->| TEXTURE_2D | | | | TEXTURE_2D | | | | TEXTURE_2D | | | +------------+ | | +------------+ | | +------------+ | | +------------+ | | +------------+ | | +------------+ | | | TEXTURE_3D | | | | TEXTURE_3D | | | | TEXTURE_3D | | | +------------+ | | +------------+ | | +------------+ | | +------------+ | | +------------+ | | +------------+ | | |TEX_1D_ARRAY| | | |TEX_1D_ARRAY| | | |TEX_1D_ARRAY| | | +------------+ | | +------------+ | | +------------+ | | . | | . | | . | | . | | . | | . | | . | | . | | . | +--------------------+ +--------------------+ +--------------------+

这些目标(内部框)是从图像或表格等处上传纹理数据的地方。如果没有显式设置,活动单元默认为GL_TEXTURE0

片段着色器如何知道我使用的唯一纹理必须通过我的纹理在片段着色器中引用?

最好使用单元ID设置统一变量。如果您没有这样做,但它仍然有效,则取决于您的图形驱动程序的宽容行为。它可能无法在所有设备上工作,甚至无法在驱动程序的未来版本上工作。我们将不得不查找规范以了解是否允许此操作。


3
谢谢!我使用 Emacs 中的 artist-mode 画的。 - legends2k

5

OpenGL有一个叫做纹理单元的概念,它们从0到MAX_TEXTURE_UNIT固定存在。

  1. 首先,使用glActiveTexture(GL_TEXTURE0)选择活动纹理单元。
  2. 然后,将纹理绑定到活动纹理单元,使用glBindTexture(GL_TEXTURE_2D, tex);
  3. 最后,设置着色器uniform变量值以引用纹理单元而不是纹理id,它将使用绑定到该单元的任何纹理。

将纹理单元视为容器,uniform变量使用位于纹理单元中的内容。

换句话说,

  • 纹理id绑定到纹理单元。不要直接使用glBindTextureToUniform

  • 将uniform变量设置为纹理单元的值,它将引用绑定到该单元的任何纹理。


为第三点点赞;这是许多初学者的绊脚石。 - legends2k

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接