【问题标题】:Value for a disabled attributes in a glsl shaderglsl 着色器中禁用属性的值
【发布时间】:2015-11-15 16:42:56
【问题描述】:

我正在尝试制作一个可以关闭纹理和/或着色的 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);
    }
}

【问题讨论】:

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


    【解决方案1】:

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

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

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

    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));
    }
    

    mode & 1 将是 1 或 0,因此比较 > 1 将始终为假。但是,根本不需要这种模式。如果未指定所有元素,GL 将自动将输入属性向量扩展为 (0, 0, 0, 1) 形式。这样就够用了

    in vec4 vert_position;
    // ...
    gl_Position = transform (vert_position);
    

    您可以在 glVertexAttribPointer() 调用中指定 1、2、3 或 4 个组件,它会按预期工作。成语in vec3 position; /* ... */ matrix * vec4(position, 1.0); 常用于教程中,但根本不需要。有人可能会争辩说,它使实际发生的事情更加明确。

    另外,有没有办法检查一个属性是否在 着色器代码?

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

    我想到了一个制服(可能是int)来存储标志并在着色器中测试它们,但这需要if 语句,我想我听说不推荐这样做。

    好吧,基于统一值的分支仍然会产生统一的控制流,所以这不是可能发生的最糟糕的事情。但它不会没有开销。如果值得,这取决于您场景的实际要求。使用不同的着色器并在它们之间切换可能会更好。但这一切都取决于会发生多少这样的状态切换,以及切换之间的每个着色器会做多少工作 - 以及您需要多少着色器组合。这是您应该进行基准测试/分析的内容,最好跨不同的 GL 实现。

    【讨论】:

    • 所以如果我理解正确的话,我可以在使用glVertexAttrib2(,,)(对于vec2)禁用属性时为我的属性设置一个默认值并在我的着色器中使用它?这实际上会稍微简化我的着色器。如果我有vec2 pos2vec3 pos3,将它们加在一起以产生最终的顶点位置会怎样?我会将不使用的那个设置为0,它不会影响另一个。
    • 我不明白你为什么需要pos2pos3。在您的着色器中,您永远不需要同时使用它们,因此根本不需要有两个位置属性。
    • 我想做一个可以处理2d和3d模型的shader!我可以为我的 vec2 模型使用 vec3 属性吗?
    • 好吧,没关系,我刚刚明白你对in vec4 vert_pos.. 的解释。对不起!感谢您的帮助,这对我来说非常有价值。
    猜你喜欢
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    • 2015-02-24
    • 1970-01-01
    • 2014-07-26
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多