我有这个 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 VertexMaterial material
不会被改变。
但实际上,颜色开始闪烁
当这个函数被注释掉时:
void main()
{
VertexMaterial material;
InitMaterial(material);
{
//ExecuteVertexMaterial(material);
v_color = material.color;
}
gl_Position = a_position;
}
或者执行
InitMaterial
函数:
void ExecuteVertexMaterial(out VertexMaterial material)
{
InitMaterial(material);
}
它按预期工作:
这是为什么呢?有没有办法让
ExecuteVertexMaterial()
函数为空?
根据这篇文章
声明为
的参数不会由调用者初始化其值。函数会修改参数,函数执行完成后,会将参数的值复制到用户调用函数时指定的变量中。请注意,被调用函数开始时参数的初始值是未定义的,就像简单地创建了一个局部变量一样。out
这意味着,如果将
material
传递给函数 ExecuteVertexMaterial(out VertexMaterial material)
,则 material
的初始值为 undefined
。该函数的作用是正确设置该输出参数。就你而言,它不会这样做。所以它会用 material
覆盖 undefined
的值。
本文还解释了
in
和 inout
关键字。
声明为
的参数意味着在调用函数时,赋予该参数的值将被复制到该参数中。然后,该函数可能会根据需要修改该参数,但这些更改不会影响调用代码。in
声明结合了两者。参数的值将由用户提供的值初始化,并输出其最终值inout
总之,您应该将参数声明为
inout
,以将已定义的值传递给函数并能够另外更改它。如果您不想通过引用更改它,则将这些参数声明为 in
就足够了。