You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何空ExecuteVertexMaterial函数会改变GLSL顶点着色器输出结果?

GLSL空函数导致颜色闪烁的问题及解决

我编写了如下GLSL顶点着色器:

layout(location = 0) in vec4 a_position;
layout(location = 1) in vec4 a_color;

layout(location = 0) out vec4 v_color;

struct VertexMaterial
{
    vec4 color;
};

void InitMaterial(out VertexMaterial material)
{
    material.color = a_color;
}

void ExecuteVertexMaterial(out VertexMaterial material)
{
}

void main()
{
    VertexMaterial material;
    InitMaterial(material);

    {
        ExecuteVertexMaterial(material);
        v_color = material.color;
    }

    gl_Position = a_position;
}

原本以为ExecuteVertexMaterial是空函数,不会修改out类型的material参数,但实际运行时出现颜色闪烁现象。

当注释掉该函数调用后,着色器恢复正常:

void main()
{
    VertexMaterial material;
    InitMaterial(material);

    {
        //ExecuteVertexMaterial(material);
        v_color = material.color;
    }

    gl_Position = a_position;
}

或者让ExecuteVertexMaterial内部调用InitMaterial,也能正常工作:

void ExecuteVertexMaterial(out VertexMaterial material)
{
    InitMaterial(material);
}

问题原因

核心是误解了GLSL中out参数的行为规则:

  • out类型是纯输出参数,函数调用时传入变量的原有值会被完全忽略,进入函数后参数处于未初始化状态;
  • GLSL要求所有out参数必须在函数内部被完整赋值,空函数没有对material的成员赋值,导致material变成未定义的垃圾值,最终v_color读取到不确定的颜色数据,引发闪烁。

能否保留空的ExecuteVertexMaterial函数?

可以,但要修正参数类型或遵守out参数的规范:

  • 推荐方案:改用inout参数:如果希望函数可以读取并可选修改material,将参数类型改为inout,这样空函数不会改变原有变量的值:
    void ExecuteVertexMaterial(inout VertexMaterial material)
    {
    }
    
  • 如果坚持用out参数:必须在函数内给material赋值,比如设置默认值或重新初始化:
    void ExecuteVertexMaterial(out VertexMaterial material)
    {
        // 赋值默认颜色或重新调用初始化函数
        material.color = vec4(1.0);
        // 或者 InitMaterial(material);
    }
    

内容的提问来源于stack exchange,提问作者Shout

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 14:28:42