GLSL,输出颜色的默认值

GLSL, default value for output color

如果您不设置,GLSL 中输出颜色的默认值是多少?

#version 330

uniform sampler2DRect colorTex;
uniform vec3 backgroundColor;

out vec4 outputColor;

void main(void)
{
    vec4 frontColor = texture(colorTex, gl_FragCoord.xy);
    outputColor.rgb = frontColor + backgroundColor * frontColor.a;
}

是 (0, 0, 0, 1) 吗?

Ps: 该代码属于旧 GL,尝试将其与 GL3 一起使用,出现以下错误

error C7011: implicit cast from "vec4" to "vec3"

我认为在旧 GL 中允许隐式转换是正确的?

这是Nvidia的front to back depth peeling example的fragment shader,可以找到代码here, org.jogl.demos.dualdepthpeeling\org.jogl.demos。 dualdepthpeeling\src\demos\dualDepthPeeling\shaders\front_peeling_final_fragment.glsl

如果您不为片段着色器输出赋值,则结果是未定义的。来自 OpenGL 3.3 规范,第 3.9.2 节 "Shader Execution",第 190 页:

Any colors, or color components, associated with a fragment that are not written by the fragment shader are undefined.

相应的 GLSL 规范证实了这一点。在第 4.3 节 "Storage Qualifiers",第 28 页:

Global variables without storage qualifiers that are not initialized in their declaration or by the application will not be initialized by OpenGL, but rather will enter main() with undefined values.

然后在第 4.6.3 节 "Outputs",第 31 页:

Output variables must be declared at global scope. During shader execution they will behave as normal unqualified global variables.

关于问题的第二部分,我认为从 vec4vec3 的隐式转换是合法的 GLSL 版本是不存在的。有些编译器可能没有报错,但应该报错。

关于默认片段着色器输出: 没有默认值,如果不设置,结果为 undefined。查看其他答案。


我注意到你有一个 纹理 ,并且采样一个 'unbound'/不完整的纹理是不同的 [1][2]默认值,但实际上我不会对所有驱动程序都依赖它!:

If a fragment shader uses a sampler which associated texture object is not complete, as defined in section 3.8.10, the texture image unit will return (R, G, B, A) = (0, 0, 0, 1). [↱]


还有一个 uniform 值也不能设置。这些在整个绘制调用中保持不变,并且像采样器一样,也有一个默认值(尽管这更像是一个 "initial" 值)。

As a result of a successful link operation, all active user-defined uniform variables belonging to program will be initialized to 0 [↱]


但是如果不设置片段颜色,实际上会发生什么?

在规范中未定义意味着 (0, 0, 0, 1) 是一个有效值,实际上可能就是您得到的值。如果 GL 实现(例如 Nvidia 或 ATI 提供的驱动程序 + 硬件)要使其成为一致的 returned 值,则生成的着色器代码需要设置默认值或在您不这样做时捕获这种情况'设置一个。这只会增加开销。什么都不做反而更快。

尽管着色器仍必须 return 一个值,但片段着色器线程的 register/s 中的任何值都会得到 returned。这是未初始化的数据(从着色器程序的角度来看)。就像 CPU 程序中的未初始化内存一样,该值可以是任何值,通常取决于事先存在的内容。全为零的情况并不少见,或者甚至是非常一致的东西,具体取决于 GPU 之前执行的任务(即另一个着色器 运行)。虽然我发现片段着色器中未初始化的值很常见地呈现为闪烁并且可以制作这样的模式: