着色器中如何引用纹理?

How are textures referenced in shaders?

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

uniform sampler2D mytexture;

我搜索了我正在使用的示例代码,但找不到任何对 mytexture 的引用;只找到激活纹理单元并将纹理绑定到之前复制到 GPU 的调用。

我的问题是,片段着色器如何知道必须通过 mytexture 引用我正在使用的 only 纹理?

我本来以为

glBindTextureToUniform(texture_id, "mytexture");

或类似的必须调用。

OpenGL 有纹理单元的概念,从 0 to MAX_TEXTURE_UNIT 开始是固定的。

  1. 首先你select活动纹理单元,使用glActiveTexture(GL_TEXTURE0)
  2. 然后将纹理绑定到活动纹理unit.usingglBindTexture(GL_TEXTURE_2D, tex);
  3. 最后,您将着色器统一值设置为引用 纹理单元而不是纹理 id,它使用绑定到该单元的任何纹理。

将纹理单元视为一个容器,统一变量使用纹理单元中的任何内容。

换句话说,

  • 您将 texture Id 绑定到 texture unit。不是直接glBindTextureToUniform

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

正如 concept3d 所提到的,映射是在纹理单元和制服之间,而不是纹理之间。造成这种差异的原因是多重纹理。

纹理单元是 OpenGL 中促进多纹理的机制。当你想在你的着色器中查找多个纹理时,你将每个纹理绑定到一个不同的纹理单元(实际上你将它绑定到单元内的一个目标)并且每个纹理都有不同的制服以在着色器中引用它们。每个纹理单元都有多个目标,如 1D、2D、3D 等。

在着色器中查找的纹理,通过制服,指的是单位。它的类型(例如 sampler2D)决定了使用的单位中的目标。映射是这样的

uniform 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|   |
                          |   +------------+   |    |   +------------+   |    |   +------------+   |
                          |         .          |    |         .          |    |         .          |
                          |         .          |    |         .          |    |         .          |
                          |         .          |    |         .          |    |         .          |
                          +--------------------+    +--------------------+    +--------------------+

这是你从图像或table等上传纹理数据到这些目标(内框)。活动单位,如果没有明确设置,默认情况下是GL_TEXTURE0.

how does the fragment shader know that the only texture I'm using has to be referred via mytexture in the fragment shader?

最好用单位ID来设置制服。如果你没有这样做并且它仍然有效,那么你依赖于你的图形驱动程序的宽容行为。它可能不适用于所有设备,甚至可能不适用于驱动程序的未来版本。我们将不得不查找规范。知道这是否被允许。