glsl着色器中已禁用属性的值

时间:2015-11-15 16:42:57

标签: opengl glsl fragment-shader vertex-shader opengl-4

我正在尝试制作一个可以关闭纹理和/或着色的glsl着色器(我希望能够为纹理着色)。我可以通过执行glDisableVertexAttribArray(x)来禁用属性,但我想知道着色器中的值是什么样的。他们会0吗?

另外,有没有办法检查着色器代码中是否启用了属性?我想到了一个制服(可能是int)来存储标志并在着色器中测试它们,但这需要if语句,我想我听说过它不推荐。

以下是我的着色器,以防您想要引用它们,我目前正在处理我正在讨论的int标志。

顶点着色器:

#version 450

layout(location=0) uniform mat4 projection_matrix;
layout(location=1) uniform mat4 view_matrix;
layout(location=2) uniform mat4 model_matrix;

// 0b0000 0000 0000 0       unused
//                   0      textures
//                    0     colors
//                     0    2d/3d
layout(location=3) uniform uint mode;

layout(location=0) in vec4 vert_tex_coord;
layout(location=1) in vec4 vert_color;
layout(location=2) in vec3 vert_2_position;
layout(location=3) in vec3 vert_3_position;

out vec4 vert_frag_color;
out vec2 vert_frag_tex_coord;

vec4 transform(vec4 v)
{
    return projection_matrix * view_matrix * model_matrix * v;
}

void main()
{
    if ((mode & 1) > 0)
    {
        gl_Position = transform(vec4(vert_3_position, 1.0));
    }
    else
    {
        gl_Position = transform(vec4(vert_2_position, 0.0, 1.0));
    }

    if ((mode & 2) > 0)
    {
        vert_frag_color = vert_color;
    }

    if ((mode) & 4) > 0)
    {
        vert_frag_tex_coord = vert_tex_coord;
    }
}

片段着色器:

#version 450

layout(location=3) uniform uint mode;

uniform sampler2D texture_0;

in vec4 vert_frag_color;
out vec2 vert_frag_tex_coord;

out vec4 frag_color;

void main()
{
    if ((mode & 2) > 1)
    {
        frag_color = vert_frag_color;
    }

    if ((mode) & 4) > 1)
    {
        frag_color = texture(texture_0, vert_frag_tex_coord);
    }
}

1 个答案:

答案 0 :(得分:4)

  

我可以通过执行glDisableVertexAttribArray(x)来禁用属性,但是   我想知道着色器中的值是什么样的。他们会吗   是0

不,实际上,"当前"每个属性的值是全局GL状态的一部分。您可以通过glVertexAttrib*()函数系列为禁用数组的每个属性设置值。只有一个小小的转折:每当你绘制一些启用了某个属性数组的东西并稍后禁用属性数组时,该属性的当前值将是 undefined ,因此你必须通过{重新指定它{1}}再次。

您的代码中的以下构造根本没有意义:

glVertexAttrib*()

if ((mode & 1) > 1) { gl_Position = transform(vec4(vert_3_position, 1.0)); } else { gl_Position = transform(vec4(vert_2_position, 0.0, 1.0)); } 将为1或0,因此比较> 1总是假的。但是,根本不需要该模式。如果未指定所有元素,GL将自动将输入属性向量扩展到表单(0,0,0,1)。所以使用

就足够了
mode & 1

您可以在in vec4 vert_position; // ... gl_Position = transform (vert_position); 调用中指定1,2,3或4个组件,它将按预期工作。成语glVertexAttribPointer()通常用于教程中,但根本不需要。可能有人认为,它会使实际情况更明确。

  

此外,有没有办法检查是否在内部启用了属性   着色器代码?

不,没有。每个属性总有一些当前值。如果它来自数组,则与着色器完全无关。

  

我想到了一个制服(可能是in vec3 position; /* ... */ matrix * vec4(position, 1.0);)来存储标志并在着色器中测试它们,但这需要int语句,我想我已经听过它了不推荐。

嗯,基于统一值的分支仍然会导致统一的控制流,因此不是最糟糕的事情。但它不会免于开销。如果值得的话,这取决于场景的实际要求。使用不同的着色器并在它们之间切换可能会更好。但这一切都取决于会发生多少个这样的状态开关,以及开关之间每个着色器的工作量 - 以及您需要多少个着色器组合。这是你应该基准/配置文件的东西,最好是不同的GL实现。