【问题标题】:Texture Sampler IDs not mapping to Texture Units纹理采样器 ID 未映射到纹理单元
【发布时间】:2016-11-12 16:51:06
【问题描述】:

我正在尝试在模型上使用 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之前打电话给glUseProgram吗?同样在 OpenGL 4.4+ 中,在着色器中使用 layout(binding=X) 和在代码中使用 glBindTextures 函数要容易得多。
  • @ybungalobill 我使用的是 3.3,我应该指定。而且我没有先调用使用程序,切换它们并没有改变,我将获得一些屏幕截图示例。

标签: opengl textures soil


【解决方案1】:

您的问题在于加载纹理时的调用顺序。 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);

【讨论】:

    【解决方案2】:

    我已找到解决此问题的方法。像我这样使用多个纹理时,你必须激活纹理单元,并在为采样器调用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);
    

    【讨论】:

    • 不,这不是真的。绑定完全独立于您设置统一值的时间。重要的是纹理单元的状态和程序制服,因为它们是在绘制调用时设置的。目前还不清楚您的原始代码有什么问题,但这不是解决方案。
    • 致第二个derhass:这不是真的。如果这解决了您的问题,那意味着您在某处搞砸了状态,并且由于您没有发布连贯的工作代码,我们无法指出您到底做了什么。
    • 这是一个解决方案。它不是最佳的,因为它会不断地改变纹理。但它有效。公认的解决方案更好,并提供实际推理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多