Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Out-of-range floating-point color values #549

Open
SunSerega opened this issue Oct 31, 2022 · 6 comments
Open

Out-of-range floating-point color values #549

SunSerega opened this issue Oct 31, 2022 · 6 comments

Comments

@SunSerega
Copy link
Contributor

SunSerega commented Oct 31, 2022

This comment has a file that mentions all the cases I found but with links to related spec/extension.


void ClearColor( float r, float g, float b, float a );

sets the clear value for fixed-point and floating-point color buffers. The specified
components are stored as floating-point values. [1]

So nothing is said about values, not in the [0; 1] range.

Description

glClearColor specifies the red, green, blue, and alpha values used by glClear to clear the color buffers. Values specified by glClearColor are clamped to the range [0,1]. [2]

But in HTML pages for the same spec version, they are clamped?


Even more confusing in the case of glColor4f:

Versions of the Color and SecondaryColor commands that take floating-point
values accept values nominally between 0.0 and 1.0. 0.0 corresponds to the minimum while 1.0 corresponds to the maximum (machine dependent) value that a
component may take on in the framebuffer (see section 2.14 on colors and coloring). Values outside [0, 1] are not clamped. [3]

Now it's explicitly not clamped. But then Microsoft walks in and:

Neither floating-point nor signed integer values are clamped to the range [0,1] before the current color is updated. However, color components are clamped to this range before they are interpolated or written into a color buffer. [4]

Well, isn't this an implementation detail? (I mean when the clamping is done, as long as before interpolation)
And OpenGL API is supposed to only care about the apparent behavior...


Generally, from a few experiences with old OpenGL I remember - all the floating point color values seemed to be clamped.
So it was quite a revelation to learn, for some functions none of the original .pdf specs define how out-of-range color values should behave.

I would understand if glClearColor with out-of-range values was implementation defined...
But since glColor4f is explicitly said to not be clamped, I expect a line between two points with colors (2.0; 2.0; 2.0) and (0.0; 0.0; 0.0) to have a fully white point in the middle and descend to full black towards the second point.
However, what I observe is a gradient starting at the first point - as if values passed to glColor4f are in fact clamped to be (1.0; 1.0; 1.0).

@NogginBops
Copy link
Contributor

NogginBops commented Oct 31, 2022

This is from page 524 (546 in the pdf):

Unsigned normalized fixed-point and signed normalized fixed-point RGBA
color buffers are cleared to color values derived by clamping each component of the
clear color to the range [0, 1] or [−1, 1] respectively, then converting the (possibly
sRGB converted and/or dithered) color to fixed-point using equations 2.3 or 2.4,
respectively. The result of clearing integer color buffers is undefined.

Doesn't say anything about non-normalized color buffers, which would imply they are not clamped.
This is also the behavior I observe in my applications, normalized formats get clamped to [0, 1] while non-normalized formats use the floats without clamping.

@gnl21
Copy link
Contributor

gnl21 commented Nov 9, 2022

I agree with @NogginBops, this is how I would expect my implementation to behave. Values are clamped only when they reach the framebuffer and only if the framebuffer is in a normalised format (so can't represent the input colours). If you have a floating-point colour buffer then clears and rendering results will just write out-of-range values without clamping them.

I expect a line between two points with colors (2.0; 2.0; 2.0) and (0.0; 0.0; 0.0) to have a fully white point in the middle and descend to full black towards the second point. However, what I observe is a gradient starting at the first point

I agree with your expectation here, although if you're using floating-point framebuffers then how they are interpreted by the underlying window system is not defined by GL.

@SunSerega
Copy link
Contributor Author

Ok, so basically clamping I see is a behavior of the default windows framebuffer implementation.
In other words [4] is correct because that's what Microsoft says about its own code, but [2] is wrong because it's different from original PDF?

And, as I understand, [1] and [3] behave the same, but are described differently in PDF:
[3] promises the values will not be clamped, but in the end, it is effectively implementation-defined; meanwhile
[1] doesn't say anything, which at least isn't wrong, but... No less confusing.

@gnl21
Copy link
Contributor

gnl21 commented Nov 9, 2022

Ok, so basically clamping I see is a behavior of the default windows framebuffer implementation.

Not necessarily the default windows framebuffer, but rather a behaviour of all GL framebuffers. If the framebuffer is stored in a normalised format then it can only represent values in the range [0, 1], so all values that are stored into that kind of buffer are in the range [0, 1] by definition, so GL clamps those writes. This isn't implementation dependent but it is format dependent. I think this is what MS are trying to describe in [4], but since it's information about some other command, not the one being specified, is imprecise and has ended up confusing.

[1] and [3] are consistent, but in [1] it is assumed that if no clamp is mentioned then no clamp is done. Given the profusion of different descriptions here (and the fact that I think the behaviour may have changed from older GL versions, maybe), this does seem quite confusing. [2] seems just to be wrong, I think.

@pdaniell-nv
Copy link
Contributor

Yeah [2] is definitely wrong, and should be updated to match the OpenGL specs. Clamping at the glClearColor time was removed in OpenGL 3.0.

@pdaniell-nv
Copy link
Contributor

@SunSerega would you want to create a PR to fix the refpage at https://github.com/KhronosGroup/OpenGL-Refpages/blob/main/gl4/glClearColor.xml?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants
@NogginBops @pdaniell-nv @gnl21 @SunSerega and others