GLSL忽略片段着色器中的统一布尔比较?

GLSL ignoring uniform bool comparison in fragment shader?

我正在尝试比较 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;
}

为什么统一的 bool 比较在片段着色器中永远不起作用?我什至设法从 GLSL 获得了统一值,并且解析阶段似乎工作得非常好——这几乎就像 GLSL 拒绝 将其用于比较,从而返回一个 NULL 纹理样本创建黑屏效果。有什么想法吗?

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

在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 明确指出:

It is not allowed to have variables of different sampler types pointing to the same texture image unit within a program object. This situation can only be detected at the next rendering command issued which triggers shader invocations, and an INVALID_OPERATION error will then be generated.

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