KhronosGroup / OpenGL-Registry

OpenGL, OpenGL ES, and OpenGL ES-SC API and Extension Registry
679 stars 274 forks source link

glBlendFunc's note can be interpreted missleading #487

Closed StarStarJ closed 2 years ago

StarStarJ commented 2 years ago

https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFunc.xhtml

Incoming (source) alpha is correctly thought of as a material opacity, ranging from 1.0 ( K A ), representing complete opacity, to 0.0 (0), representing complete transparency.

But if i have fragment color like this:

vec3 RGB = ... some values;
float Alpha = 0.0; // in some cases it's 0
FragColor = vec4(RGB / Alpha, Alpha);

(Yes in my case the division makes sense)

I can't find anything in the OpenGL 3.3 spec saying that this must result in complete transparency. In fact someone's GPU produces a black pixel here, which probably can make sense if the whole calculation results in NaNs.

I know you can just use discard, But i am never sure if checks like == 0.0 are good when dealing with floating points. (also I don't know if it has performance hits, if alpha blending is enabled anyway)

If this is wrong, please quote the spec, because I really couldn't find anything.

laurie-hedge commented 2 years ago

Hi.

I can't find anything in the OpenGL 3.3 spec saying that this must result in complete transparency.

I take it your point here is that this depends upon the setup of the blend function, right? E.g. if the source function is GL_ONE, then the alpha will not have an influence on the blending? I think this section was probably written as a follow on from the previous section, which suggests using (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA). Would you find this less misleading if it were to say something like this?

Incoming (source) alpha would typically be used as a material opacity, ranging from 1.0 ( K A ), representing complete opacity, to 0.0 (0), representing complete transparency.

In fact someone's GPU produces a black pixel here, which probably can make sense if the whole calculation results in NaNs.

Yes that is expected. NaNs propagate through floating point operations. I.e. x NaN == NaN, y + NaN == NaN etc. In this case, assuming (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), your red channel would look something like `srcR 0 + dstR 1 since srcR here is NaN, you get NaN 0 + dstR * 1 == NaN`

i am never sure if checks like == 0.0 are good when dealing with floating points.

Depends where it comes from. 0.0 can be represented exactly within floating point, so comparison could be safe. However if there is a risk if rounding errors in the calculations that might result in 0, then you might be better off adding a small tolerance.

Hope that helps. Let us know if you would find the above clarification useful or can think of some better working for this so that we can update the page.

StarStarJ commented 2 years ago

First of all, thanks for the detailed reply, I know this issue is really picky, but that is also what I always liked about OpenGL, that its pretty well documented with some examples and edge cases.

Incoming (source) alpha would typically be used as a material opacity, ranging from 1.0 ( K A ), representing complete opacity, to 0.0 (0), representing complete transparency.

Indeed this wording would already be better I guess, bcs it doesn't imply anything directly. Personally I'd also have nothing against explicitly mentioning edge cases, tho I dunno, if you(the registry mantainers) have to follow some rules, e.g. by saying directly that all values must not be NaN or not generate NaNs (infinity * 0), else it's undefined behavior.

laurie-hedge commented 2 years ago

Great, I'm glad you think this would be an improvement.

Personally I'd also have nothing against explicitly mentioning edge cases, tho I dunno, if you(the registry mantainers) have to follow some rules, e.g. by saying directly that all values must not be NaN or not generate NaNs (infinity * 0), else it's undefined behavior.

Which particular edge cases were you thinking of here? If you're referring to the case where one of the inputs into the blend equation is NaN, we probably wouldn't add something specifically about that to this page, since the rules for NaNs are more or less the same throughout the API, which is to say, the results are undefined. If you had something else in mind though, let me know and I can work on adding some wording for that to the page.

StarStarJ commented 2 years ago

Thanks, then I'm fine with it, thanks for your time

laurie-hedge commented 2 years ago

Not at all, thanks for taking the time to report this to us.

@pdaniell-nv If people are happy with this clarification, can we look to get it changed in the docs?

pdaniell-nv commented 2 years ago

@oddhack, could you edit the page at https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendFunc.xhtml and modify the first sentence from the Notes section from:

Incoming (source) alpha is correctly thought of as a material opacity, ranging from 1.0 ( K A ), representing complete opacity, to 0.0 (0), representing complete transparency.

to:

Incoming (source) alpha would typically be used as a material opacity, ranging from 1.0 ( K A ), representing complete opacity, to 0.0 (0), representing complete transparency.

Thanks.