3

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

uniform sampler2D mytexture;

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

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

我会想到一个

glBindTextureToUniform(texture_id, "mytexture");

或类似的必须被调用。

4

2 回答 2

6

正如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.

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

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

于 2015-12-23T10:00:12.820 回答
4

OpenGL 有概念纹理单元,它们从0 to MAX_TEXTURE_UNIT.

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

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

换句话说,

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

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

于 2015-12-23T09:39:30.360 回答