GLSL:采样器上传仅在删除未使用的采样器时有效

Posted

技术标签:

【中文标题】GLSL:采样器上传仅在删除未使用的采样器时有效【英文标题】:GLSL: sampler upload only works when unused sampler is removed 【发布时间】:2015-05-13 13:26:41 【问题描述】:

我目前正在尝试在 OpenGL 中使用帧缓冲区实现延迟着色。帧缓冲区本身工作得很好,但是当我不在着色器中使用所有统一采样器时,其中一个纹理停止工作。

这是我的片段着色器,帧缓冲区的测试演示:

#version 330 core

uniform sampler2D texCoordTex;
uniform usampler2D texIndexTex;
uniform sampler2D normalTex;
uniform sampler2D positionTex;
uniform sampler2D depthTex;

float linearizeDepth(float depth)
    float n = 0.1, f = 2000;
    return (2*n)/(f + n - depth*(f-n));


out vec4 out_Color;

uniform sampler2DArray texArray;

void main()
    ivec2 texelCoord = ivec2(gl_FragCoord.xy);
    vec2 texCoord = texelFetch(texCoordTex,texelCoord,0).xy;
    uint texIndex = texelFetch(texIndexTex,texelCoord,0).x;
    vec3 normal = texelFetch(normalTex,texelCoord,0).xyz;
    //vec3 pos = texelFetch(positionTex,texelCoord,0).xyz;
    float depth = linearizeDepth(texelFetch(depthTex,texelCoord,0).x);

    out_Color = vec4(0,0,0,1);

    if(texelCoord.x < 512)
        if(texelCoord.y < 300)
            out_Color.xyz = 0.5*normal+0.5;     
        else
            out_Color.xyz = vec3(texCoord,texIndex/50.0);       
        
    else
        if(texelCoord.y < 300)
            out_Color.xyz = texture(texArray,vec3(texCoord,texIndex)).xyz;      
        else
            out_Color.xyz = vec3(depth);        
        
    

请注意,未使用的行 vec3 pos = texelFetch(positionTex,texelCoord,0).xyz; 已被注释掉。 采样器统一上传被记录:

13/05/2015 15:11:24,317 INFO  [default] ShaderProgram::ShaderProgram: TextureUnit[ name = depthTex, unit = 1] uploaded to shader.
13/05/2015 15:11:24,317 WARN  [default] ShaderProgram::ShaderProgram: glGetError() is GL_NONE
13/05/2015 15:11:24,317 INFO  [default] ShaderProgram::ShaderProgram: TextureUnit[ name = texCoordTex, unit = 2] uploaded to shader.
13/05/2015 15:11:24,317 WARN  [default] ShaderProgram::ShaderProgram: glGetError() is GL_NONE
13/05/2015 15:11:24,317 INFO  [default] ShaderProgram::ShaderProgram: TextureUnit[ name = texIndexTex, unit = 3] uploaded to shader.
13/05/2015 15:11:24,317 WARN  [default] ShaderProgram::ShaderProgram: glGetError() is GL_NONE
13/05/2015 15:11:24,317 INFO  [default] ShaderProgram::ShaderProgram: TextureUnit[ name = normalTex, unit = 4] uploaded to shader.
13/05/2015 15:11:24,317 WARN  [default] ShaderProgram::ShaderProgram: glGetError() is GL_NONE
13/05/2015 15:11:24,317 WARN  [default] ShaderProgram::ShaderProgram: TextureUnit[ name = positionTex, unit = 0] not found in shader.
13/05/2015 15:11:24,317 WARN  [default] ShaderProgram::ShaderProgram: glGetError() is GL_NONE
13/05/2015 15:11:24,318 INFO  [default] ShaderProgram::ShaderProgram: TextureUnit[ name = texArray, unit = 5] uploaded to shader.
13/05/2015 15:11:24,318 WARN  [default] ShaderProgram::ShaderProgram: glGetError() is GL_NONE

positionTex当然是找不到的,因为shader中没有用到。

Sponza 场景的结果图像:

如果我不注释掉 vec3 pos = texelFetch(positionTex,texelCoord,0).xyz; 行,texCoordTex 将不再起作用,并且统一上传会产生 GL_INVALID_OPERATION 错误。

结果看起来像这样,因为纹理坐标为零。

日志输出显示错误:

13/05/2015 15:20:26,162 INFO  [default] ShaderProgram::ShaderProgram: TextureUnit[ name = depthTex, unit = 1] uploaded to shader.
13/05/2015 15:20:26,162 WARN  [default] ShaderProgram::ShaderProgram: glGetError() is GL_NONE
13/05/2015 15:20:26,162 INFO  [default] ShaderProgram::ShaderProgram: TextureUnit[ name = texCoordTex, unit = 2] uploaded to shader.
13/05/2015 15:20:26,162 WARN  [default] ShaderProgram::ShaderProgram: glGetError() is GL_NONE
13/05/2015 15:20:26,162 INFO  [default] ShaderProgram::ShaderProgram: TextureUnit[ name = texIndexTex, unit = 3] uploaded to shader.
13/05/2015 15:20:26,162 WARN  [default] ShaderProgram::ShaderProgram: glGetError() is GL_NONE
13/05/2015 15:20:26,162 INFO  [default] ShaderProgram::ShaderProgram: TextureUnit[ name = normalTex, unit = 4] uploaded to shader.
13/05/2015 15:20:26,162 WARN  [default] ShaderProgram::ShaderProgram: glGetError() is GL_NONE
13/05/2015 15:20:26,162 WARN  [default] ShaderProgram::ShaderProgram: TextureUnit[ name = positionTex, unit = 0] not found in shader.
13/05/2015 15:20:26,162 WARN  [default] ShaderProgram::ShaderProgram: glGetError() is GL_NONE
13/05/2015 15:20:26,162 INFO  [default] ShaderProgram::ShaderProgram: TextureUnit[ name = texArray, unit = 5] uploaded to shader.
13/05/2015 15:20:26,162 WARN  [default] ShaderProgram::ShaderProgram: glGetError() is GL_INVALID_OPERATION

是我忽略了什么还是这是驱动程序错误? 我使用的是 ATI HD 6870,我可以在 Linux 和 Windows 上重现这种行为。

【问题讨论】:

对我来说,这看起来像是您管理统一位置的问题。但是没有代码,就无法确定。 我是这么想的,但是在着色器中取消注释这一行并不会改变 cpu 端的任何内容,因为无论如何都找不到统一的位置。 @derhass 你是对的,我犯了一个错误。我已经做了多个工作项目而没有注意到我所做的错误。你可以在这里看到它:alecjacobson.com/weblog/?p=2203&cpage=1#comment-133014 【参考方案1】:

我发现了这个错误,它与着色器无关。在我的ShaderProgram 类中,我使用glGetActiveUniform 来查找有关统一变量的信息。后来我使用统一索引作为位置,但是位置必须通过调用glGetUniformLocation单独查询。该错误在this 博客文章中进行了描述。

【讨论】:

以上是关于GLSL:采样器上传仅在删除未使用的采样器时有效的主要内容,如果未能解决你的问题,请参考以下文章

测试折叠上的 CV 和欠采样

如何使用textureLod在glsl中对mip级别进行采样?

nVidia GLSL 不支持 sampler1D?

GLSL的texture2D函数

绑定 OpenGL 纹理采样器

KnockoutJS:模板未在可观察数组更改时更新(仅在添加时,在删除时有效)