纹理采样器 ID 未映射到纹理单元

Texture Sampler IDs not mapping to Texture Units

我正在尝试在一个模型上使用 3 个纹理。我正在使用 SOIL 加载图像并将它们绑定到纹理单元 1、2 和 3。但是由于某种原因,当我将采样器 1、2 和 3 绑定到我的着色器时,1 生成绑定到 GL_TEXTURE2 的图像而 2 和 3 生成绑定到 GL_TEXTURE3 的图像。我在这里遗漏了一些简单的东西吗?

定义:

GLenum baseTextureUnitID = GL_TEXTURE1;
GLenum filterTextureUnitID = GL_TEXTURE2;
GLenum accentTextureUnitID = GL_TEXTURE3;
GLuint baseTextureSamplerValue = 1;
GLuint filterTextureSamplerValue = 2;
GLuint accentTextureSamplerValue = 3;

正在加载图像:

baseTextureID = SOIL_load_OGL_texture(baseImageFile,
    SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
glActiveTexture(baseTextureUnitID);
glBindTexture(GL_TEXTURE_2D, baseTextureID);

filterTextureID = SOIL_load_OGL_texture(filterImageFile,
    SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
glActiveTexture(filterTextureUnitID);
glBindTexture(GL_TEXTURE_2D, filterTextureID);

accentTextureID = SOIL_load_OGL_texture(accentImageFile,
    SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
glActiveTexture(accentTextureUnitID);
glBindTexture(GL_TEXTURE_2D, accentTextureID);

获取统一位置:

baseTextureSamplerID = glGetUniformLocation(shaderProgram, "baseTex");
filterTextureSamplerID = glGetUniformLocation(shaderProgram, "filterTex");
accentTextureSamplerID = glGetUniformLocation(shaderProgram, "accentTex");

设置制服:

glUniform1i(baseTextureSamplerID, baseTextureSamplerValue);
glUniform1i(filterTextureSamplerID, filterTextureSamplerValue);
glUniform1i(accentTextureSamplerID, accentTextureSamplerValue);

现在,如果我从 baseTex 采样,我会得到滤镜图像,而 filterTex 和 accentTex 采样器会生成重音图像

我找到了解决这个问题的方法。当像我这样使用多个纹理时,你必须激活纹理单元,并在为采样器调用glUniform1i之前再次绑定纹理。

设置制服时,正确的格式是:

glActiveTexture(baseTextureUnitID);
glBindTexture(GL_TEXTURE_2D, baseTextureID);
glUniform1i(baseTextureSamplerID, baseTextureSamplerValue);

glActiveTexture(filterTextureUnitID);
glBindTexture(GL_TEXTURE_2D, filterTextureID);
glUniform1i(filterTextureSamplerID, filterTextureSamplerValue);

glActiveTexture(accentTextureUnitID);
glBindTexture(GL_TEXTURE_2D, accentTextureID);
glUniform1i(accentTextureSamplerID, accentTextureSamplerValue);

您的问题在于加载纹理时的调用顺序。 SOIL_load_OGL_texture() 将更改您当前的纹理绑定。它必须这样做,因为它需要绑定新创建的纹理,以便它可以将数据加载到其中。

想象一下您的代码序列中发生了什么:

glActiveTexture(baseTextureUnitID);
glBindTexture(GL_TEXTURE_2D, baseTextureID);

此时,baseTextureID 已绑定到预期的纹理单元。但是下一行是:

filterTextureID = SOIL_load_OGL_texture(filterImageFile, ...);

在此调用中,新创建的纹理将绑定到当前纹理单元,这是您计划用于基础纹理的单元。这就是您在加载所有纹理结束时绑定错误纹理的原因。

解决这个问题很容易。只需更改图像加载代码中的调用顺序,先加载所有纹理,然后建立所有绑定:

baseTextureID = SOIL_load_OGL_texture(baseImageFile,
    SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
filterTextureID = SOIL_load_OGL_texture(filterImageFile,
    SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);
accentTextureID = SOIL_load_OGL_texture(accentImageFile,
    SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y);

glActiveTexture(baseTextureUnitID);
glBindTexture(GL_TEXTURE_2D, baseTextureID);

glActiveTexture(filterTextureUnitID);
glBindTexture(GL_TEXTURE_2D, filterTextureID);

glActiveTexture(accentTextureUnitID);
glBindTexture(GL_TEXTURE_2D, accentTextureID);