GLSL, default value for output color

2019-09-07 02:27发布

Which is the default value for the output color in GLSL in case you dont set it?

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

Is it (0, 0, 0, 1)?

Ps: that code belongs to the old GL, trying to use it with the GL3, I get the following error

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

I am right to suppose that in the old GL, the implicit cast was allowed?

This is the fragment shader of the front to back depth peeling example of Nvidia, you can find the code here, org.jogl.demos.dualdepthpeeling\org.jogl.demos.dualdepthpeeling\src\demos\dualDepthPeeling\shaders\front_peeling_final_fragment.glsl

2条回答
Lonely孤独者°
2楼-- · 2019-09-07 02:59

With regard to the default fragment shader output: There is no default and the result is undefined if you don't set one. See other answers.


I notice you have a texture, and sampling an 'unbound'/incomplete texture is different [1][2]. There is a default, but in practice I would not rely on this for all drivers!:

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). [↱]


There's also a uniform value which may not be set either. These remain constant for the entire draw call, and like samplers, also have a default (although this is more of an "initial" value).

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


But what actually happens when you don't set a fragment colour?

Being undefined in the spec means (0, 0, 0, 1) is a valid value and may in fact be the one you get. If a GL implementation (such as the one Nvidia or ATI provide with their driver + hardware) were to make this the consistent returned value, the generated shader code needs to set a default value or catch the case when you don't set one. This just adds overhead. It's faster to do nothing instead.

The shader must still return a value though, and what ever value is in the register/s for your fragment shader thread gets returned. This is uninitialized data (from the point of view of your shader program). Just like uninitialized memory in a CPU program, the value could be anything, generally depending on what was there beforehand. It's not uncommon for this to be all zeroes, or even something pretty consistent depending on the previous task the GPU was doing (i.e. another shader you run). Although I've found uninitialized values in the fragment shader quite commonly presents as flickering and can make patterns like this:

nvidia rasterizer pattern

查看更多
别忘想泡老子
3楼-- · 2019-09-07 03:11

If you don't assign values to fragment shader outputs, the result is undefined. From the OpenGL 3.3 spec, section 3.9.2 "Shader Execution", page 190:

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

The corresponding GLSL spec confirms this. In section 4.3 "Storage Qualifiers", page 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.

And then in section 4.6.3 "Outputs", page 31:

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

On the second part of the question, I don't believe there ever was a GLSL version where an implicit cast from vec4 to a vec3 was legal. Some compilers may not have given an error, but they should have.

查看更多
登录 后发表回答