【问题标题】:GLSL ignoring uniform bool comparison in fragment shader?GLSL忽略片段着色器中的统一布尔比较?
【发布时间】:2018-05-27 01:01:14
【问题描述】:

我正在尝试比较 GLSL 中的统一布尔 (type_2d),以便输出两种采样器类型之一 - sampler2D 和 samplerCube。这纯粹用于区分立方体贴图(天空盒、反射立方体贴图数据等)和 sampler2d(反照率贴图、法线贴图等)。

我尝试过与整数、浮点数和布尔值进行比较,但是帧缓冲区总是采用黑屏。

请记住,如果我在“main”中硬编码 bool 值,例如“type_2d = false”而不使用统一分配,而不是解析来自 C++ 的统一值。

这里是“GBuffer.f”代码:

#version 420 core

layout(location = 0) out vec3 gPosition;    // Position texel colour
layout(location = 1) out vec3 gNormal;  // Normal texel colour
layout(location = 2) out vec4 gAlbedo;  // Albedo texel colour

in vec3 _texcoord;  
in vec3 _normal;
in vec3 _frag_pos;

uniform bool        type_2d;

uniform sampler2D   albedo;     // Albedo and specular map
uniform samplerCube cubemap;    // Skybox cubemap

vec4 final_colour;

void main()
{

    gPosition = _frag_pos;
    gNormal = normalize(_normal);

    if (type_2d)
    {
        final_colour.rgb = texture(albedo, _texcoord.st).rgb;
        final_colour.a = texture(albedo, _texcoord.st).a;   // Emission
    }
    else
    {
        final_colour.rgb = texture(cubemap, _texcoord).rgb;
        final_colour.a = texture(cubemap, _texcoord).a;
    }

    gAlbedo.rgba = final_colour;
}

为什么统一布尔比较在片段着色器中永远不起作用?我什至设法从 GLSL 获得了统一的值,解析阶段似乎工作得非常好——就好像 GLSL 拒绝 使用它进行比较,从而返回一个 NULL 纹理样本创建一个黑屏影响。有什么想法吗?

【问题讨论】:

  • 对我来说,这看起来就像你只是搞砸了统一分配或纹理单元管理。当然,如果没有 MCVE,这只是完全的猜测。仅仅重新创建之前因缺乏 MCVE 而被搁置的相同问题不会让您有任何收获。
  • 奇怪的是,当调用 glActiveTexture(GL_TEXTURE1) 并将纹理 id 绑定为 glUniform1i(texture, 1) 时,它起作用了!但是 glActiveTexture(GL_TEXTURE0) 没有。
  • 我看不出有什么奇怪的地方。
  • 你只是糊涂了。统一的位置与纹理单元无关。目前尚不清楚您到底在做什么,但我的猜测是您只是尝试从同一纹理单元的两个不同目标中采样,根据规范,这根本是不允许的
  • @William: "默认情况下 GL_TEXTURE0 肯定会绑定到第一个统一位置" 只是偶然; all 制服的默认值为 0。

标签: c++ opengl boolean glsl uniform


【解决方案1】:

在 OpenGL 中,单个纹理单元有多个针对不同纹理类型的绑定目标,例如 GL_TEXTURE_1DGL_TEXTURE_2DGL_TEXTURE_BUFFERGL_TEXTURE_CUBE_MAP。所以从技术上讲,您可以将多个纹理绑定到一个单元。

默认情况下,GL_TEXTURE0 是活动纹理单元,所有制服都初始化为0,包括采样器制服。因此,如果您将glBindTexture() 一个 2D 纹理和一个立方体贴图结合起来,您最终会得到这样的结果。

然而,尽管在 GL 中完全允许同时将几种不同的纹理类型绑定到单个单元,但您可以从 一个 特定纹理目标sample每个单元的。 OpenGL 4.6 core profile specification, Section "7.11 Samplers", page 155 明确声明:

不允许有不同采样器类型的变量指向 程序对象中的相同纹理图像单元。 这种情况只能在下一个触发着色器调用的渲染命令时检测到, 然后会生成INVALID_OPERATION 错误。

因此,即使您使用制服在两个路径之间切换,从技术上讲,您的程序对象也会激活两个采样器制服,并且如果不将它们设置为从不同的纹理单元进行采样,您最终会进入禁区。

【讨论】:

    【解决方案2】:

    出于某种奇怪的原因,我不得不设置 glActoveTexture(GL_TEXTURE1);和 glUniform1i(id, 1);用于渲染立方体贴图纹理(即使我在几何 paas 之前没有调用 GL_TEXTURE0)。由于采样器类型,我猜立方体贴图纹理需要额外的偏移值?想不出其他原因。

    【讨论】:

      猜你喜欢
      • 2017-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-26
      • 2020-03-03
      • 2020-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多