Daemon
Daemon copied to clipboard
WIP: implement colorspace support (sRGB, etc.)
The purpose of this change is to achieve linear blending, this is a continuation of:
- https://github.com/DaemonEngine/Daemon/pull/1034
Some context:
- Everything should be displayed in sRGB space.
- Everything should be computed in linear space.
Textures are in sRGB space, lightmaps are usually in linear space. So the computation for applying a lightmap on a texture and rendering it is:
convertToSRGB( convertFromSRGB( texture ) * light )
Q3map2 has a trick to also store lightmaps in sRGB space, this makes possible to bias the storage and allocate more precision to some wanted values (makes black less banded if I'm right). When this Q3map2 option is used, the computation for applying a lightmap on a texture and rendering it is:
convertToSRGB( convertFromSRGB( texture ) * convertFromSRGB( light ) )
OpenGL provides features to store images while saying if they are in linear or sRGB space, when using those features, OpenGL would automatically convert the colors to linear space when sampling them, and convert them back to sRGB when displaying.
I still want to start with a fully explicit implementation where we do the conversions ourselves, because it makes easier to control what is happening at every step with our current engine design. It's very unlikely that our engine works with graphics card that don't support sRGB image OpenGL formats (even my 23 years old Radeon 2700 Pro supports it if I'm right). Though, our engine design may not makes it easy to use an implicit OpenGL implementation because of its current design:
- When we load a light style light map, we may not know yet it's a lightmap so we may not know yet in which format it is when we need to know it (when uploading it to GPU).
- When we load an image we may not know yet what kind of image it is, for example a normal map is always in linear space, but some legacy shader keywords make possible to load and upload first the image to GPU memory, then tell if it is a normal map or not only after the OpenGL format is already selected.
There can be other shortcomings like that, but also, there can be things that require some in-engine conversions. For example the rgbgen colors are assumed to be in sRGB space, because if people copy the RGB values from a color picker in an image editor like GIMP or Photoshop, those values are in sRGB. So we need to convert those colors back to linear in the C++ engine code.
Migrating to OpenGL sRGB features is something we can postpone for the future, it will reduce the amount of GLSL code and may limit precision loss (so, more performance and less color imprecision), but we don't require that to get a viable product. And we better want to get proper colorspace management as soon as possible.
My effort to achieve proper colorspace management is now 6 years old.
@sweet235 wrote today in chat:
<Sweet> since almost a year, i cannot decide on what specularity to use for the atcshd texture package <Sweet> because there is always a change coming up
So we better merge this as soon as possible.
Once this is merged, there would not be strong changes to expect. For example if one day we implement HDR rendering, this will not change the colorspace neither the blend computations, it will just add more precision.
This effort is also required (but not enough) to get true PBR.
It is assumed that once this is merged, the light computation formulæ will be stable (except for PBR which is still work-in-progress).