tutorial 11 explanation of srgb
mikedilger opened this issue · 2 comments
The explanation of srgb in tutorial 11 is wrong. Rather than write a PR, since you'll probably want to edit the precise wording, I'm just going to write what I believe it should say, approximately:
EDIT: I've corrected myself below.
We've been using Rgba8UnormSrgb
for all our textures. Srgb
is a non-linear color space. It is ideal for monitors because human color perception isn't linear either and Srgb
was designed to match the quirkiness of our human color perception.
But Srgb
is an inappropriate color space for data that must be operated on mathematically. Such data should be in a linear (not gamma-corrected) color space. When a GPU samples a texture with Srgb in the name, it converts the data from non-linear gamma-corrected Srgb to a linear non-gamma-corrected color space first so that you can do math on it (and it does the opposite conversion if you write back to the texture).
Normal maps are already stored in a linear format. So we should be specifying the linear space for the texture so it doesn't do an inappropriate conversion when we read from it.
We need to specify Rgba8Unorm
when we create the texture. Let's add an is_normal_map
method to our Texture
struct.
On a related note, because you chose an sRGB (non-linear gamma-corrected) render target (surface), if you find a device that doesn't offer one (like Chromium!) you will be outputting linear data, the texture won't convert it automatically, and it will be displayed on the monitor in linear (which monitors do not expect, it will appear too dark).
EDIT: I stand corrected about chromium, see next note below
I find it easier to select a non-sRGB (linear, not-gamma-corrected) render target (more guaranteed to find one of those, plus blending is done in a linear space, etc), and then do the sRGB gamma correction as the very last step in the fragment shader.
The other option is to tell the fragment shader whether to do it or not via a Uniform (I suppose).
This problem appears in tutorial 4 as well. Furthermore, in the example of the magenta pentagon, it should say that the RGB values are (0.5, 0.5, 0.5), corresponding to sRGB values of (188, 188, 188). The explanation there swaps the terms RGB and sRGB, in both the explanation and the formula (which should be rgb_color = ((srgb_color / 255 + 0.055) / 1.055) ^ 2.4
. It would be better to point out that the CSS rgb
function actually takes sRGB values.
Additionally, some platforms (such as chromium) will report only supporting linear textures such as bgra8-unorm
, and expect a texture with that format, but display the actual colours as if it's an sRGB texture (this is to be bug-compatible with CSS alpha blending). The proper way to handle this is to create an sRGB view of that texture, which will perform the necessary conversion and allow the use of actual (non-s) RGB vertex colours just like native does.