|
|
|
|
|
by panic
3425 days ago
|
|
Paste this into the editor to see the difference: varying vec3 vPos;
float sRGB(float x) {
if (x <= 0.00031308)
return 12.92 * x;
else
return 1.055 * pow(x, 1./2.4) - 0.055;
}
void main() {
float v = (vPos.y + 1.) / 2.;
if (vPos.x < -0.5)
gl_FragColor = vec4(pow(v, 1./2.2)); // 2.2 Gamma
else if (vPos.x < 0.0)
gl_FragColor = vec4(sRGB(v)); // sRGB
else if (vPos.x < 0.5)
gl_FragColor = vec4(sqrt(v)); // sqrt approximation
else
gl_FragColor = vec4(v); // unadjusted
}
The sqrt() function adjusts for the output curve of your display (usually sRGB nowadays, but in the past various gamma values have been used). The strips on the left should have an approximately linear gradient between light and dark, whereas the rightmost gradient will be too dark.The question of why your display doesn't just output linear colors is more interesting. Small differences in dark colors are more easily perceived than differences in lighter colors, so it's useful to spend more encoding space on the low end. With more bits, you could use linear colors throughout, but all color data would take up proportionally more memory. It ends up more efficient to just decode from sRGB, do your computation, and encode into sRGB again each time. Modern graphics APIs can automate this sRGB coding for you by letting you specify an sRGB format for textures: each time you read from an sRGB texture, the system will decode the color into linear space, and all writes will automatically encode back into sRGB. |
|