Comment by jiggawatts

5 years ago

This is in the same category of error as most programmers thinking that sRGB uses a linear light model. They try to do arithmetic like blending or blurring on the raw image data this inevitably does the wrong thing.

Similarly, most non-AAA game engines ignore the sRGB tone curve and treat all inputs and outputs as if they were linear, which results in unexpected brightness shifts in textures.

Up until very recently, Blender used linear light internally, but output that as sRGB without converting it to the appropriate gamma curve. There's guide after guide online on how to fix Blender by using "filmic" mode, which should be renamed to "not broken" mode.

Same thing as the colour picker in image editors like mspaint or Photoshop. They all have the same rainbow picker that has very visible discontinuities in the colour gradients, like a rippled curtain. It should be smooth, and it is, if using a perception-based colour model instead of linear light output straight to an sRGB monitor without any kind of colour correction.

This kind of thing has been going on for decades, and will continue for decades more. Programming is still a growth industry, so the average developer is inexperienced and doesn't know about these subtleties.

I think more people are aware of gamma correction now.

The best way to do that, if you are using shaders, is to have "fragColor.xyz = pow(col,vec3(1./2.2))"* on your last line. If it looks bad, look elsewhere, you are not allowed to touch that last line. The opposite should be done just after reading textures, if they aren't already linear.

*: sRGB actually has a weird transfer function, but it is closely approximated by a gamma of 2.2

  • For OpenGL, it will perform conversions automatically when sampling from texture with SRGB type, and opposite when writing to SRGB rendertarget (on desktop GL_FRAMEBUFFER_SRGB also needs to be enabled). I guess other APIs have similiar features.

  • This doesn't work for alpha blending since even if you output the color in the right space, the GPU might do blending in sRGB space and mess things up.

    Best is to properly declare the target framebuffer as sRGB (if it is) and output linear colors while letting the GPU deal with it.

    • There be dragons. First, you're assuming the target display device is sRGB! There's a decent chance it isn't these days.

      Second, this will prevent HDR.

      Most games render to a linear HDR target surface with a very wide dynamic range, and then will tonemap it to the display gamut as the final step. This was common as far back as Valve's Half Life game. I think even the first one did something along these lines!

      This is especially important for modern engines that are used by AAA games. E.g. Unreal engine and all similar engines are commonly used for XBox and Playstation games where the output display is a wide-gamut HDR television, not an SDR sRGB computer monitor.

I thought Blender did convert to the sRGB gamma properly, the problem without “filmic” is that the highlights clip so badly without a roll off that lighting becomes very difficult and encourages bad workarounds.

I think Elite Dangerous Odyssey recently had this problem. Any ice planet at release was literally blowing out the sun in terms of brightness a thousand fold or so it seemed.

Could you provide good documentation about such thing?