Skip to content

Commit

Permalink
GLSL: Use linear color for blending pixels in transparent rendering.
Browse files Browse the repository at this point in the history
  • Loading branch information
jamievlin committed Feb 29, 2024
1 parent 124e85e commit ec23aa5
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 4 deletions.
18 changes: 18 additions & 0 deletions base/shaders/blend.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,21 @@ vec4 blend(vec4 outColor, vec4 color)
return mix(outColor,color,color.a);
}

const float gamma=2.2;
const float invGamma=1.0/gamma;

/**
* @brief Converts linear color (measuring photon count) to srgb (what our brain thinks
* is the brightness
* example linearToPerceptual(vec3(0.5)) is approximately vec3(0.729)
*/
vec3 linearToPerceptual(vec3 inColor)
{
// an actual 0.5 brightness (half amount of photons) would
// look brighter than what our eyes think is "half" light
return pow(inColor, vec3(invGamma));
}

void main()
{
uint pixel=uint(gl_FragCoord.y)*push.constants[1]+uint(gl_FragCoord.x);
Expand Down Expand Up @@ -159,5 +174,8 @@ void main()
}
}

vec3 perceptualColor=linearToPerceptual(outColor.rgb);
outColor = vec4(perceptualColor, outColor.a);

COUNT(pixel)=0u;
}
11 changes: 7 additions & 4 deletions base/shaders/fragment.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -287,15 +287,18 @@ void main() {
// (e.g. our 0.5 is much much brighter than what swap chain/monitor thinks 0.5 is)
// need to give the output image the color our brain perceives with the same photon count
// as the original pixel
vec3 outColorInPerceptualSpace=linearToPerceptual(outColor.rgb);
outColor=vec4(outColorInPerceptualSpace,outColor.a);
vec4 linearColor=outColor;

// outColor is our output vector, so save what we have as linear color
vec3 outColorInPerceptualSpace=linearToPerceptual(linearColor.rgb);
outColor=vec4(outColorInPerceptualSpace,linearColor.a);

#ifndef WIDTH // TODO DO NOT DO THE DEPTH COMPARISON WHEN NO TRANSPARENT OBJECTS!
uint pixel=uint(gl_FragCoord.y)*push.constants[1]+uint(gl_FragCoord.x);
#if defined(TRANSPARENT) || (!defined(HAVE_INTERLOCK) && !defined(OPAQUE))
uint element=INDEX(pixel);
uint listIndex=atomicAdd(offset[element],-1u)-1u;
fragment[listIndex]=outColor;
fragment[listIndex]=linearColor;
depth[listIndex]=gl_FragCoord.z;
#ifndef WIREFRAME
discard;
Expand All @@ -306,7 +309,7 @@ void main() {
if(opaqueDepth[pixel] == 0.0 || gl_FragCoord.z < opaqueDepth[pixel])
{
opaqueDepth[pixel]=gl_FragCoord.z;
opaqueColor[pixel]=outColor;
opaqueColor[pixel]=linearColor;
}
endInvocationInterlockARB();
#endif
Expand Down

0 comments on commit ec23aa5

Please sign in to comment.