Help with Overlay Blending in shader. What does operator < do on half4 to half?

Hi there,

I’m trying to write a shader that blends like the Overlay blend mode in Photoshop.

The formula is this…
6935845--814762--upload_2021-3-15_11-29-54.png

Example shader code shows the following…

half4 OverlayBlend( half4 a, half4 b )
{
       half4 r = a < .5 ? 2.0 * a * b :  1.0 - 2.0 * ( 1.0 - a ) * ( 1.0 - b );
       r.a = b.a;                  
       return r;
}

But I’m getting very odd results.

What does is a < .5 doing? This is a < operator on a half4 comparing it to a half.
I can’t find work out how to find documentation on this.

Thanks.

Well, first that line in question is a ternary. In the line var foo = qux ? bar : baz;, if qux is true, then foo = bar, else foo = baz. But for that to work the part before the ? has to be evaluated as a boolean. In this case, it has to test if a is less than .5. When doing operations like this to a vector value, like half4, each component is operated on separately. So in a simple example:

float4 foo = float4(0.0, 0.3, 0.6, 1.0);
float4 bar = foo > 0.5 ? 1.0 : 0.0;

is equivalent to:

float4 foo = float4(0.0, 0.3, 0.6, 1.0);
float4 bar;
bar.r = foo.r > 0.5 ? 1.0 : 0.0;
bar.g = foo.g > 0.5 ? 1.0 : 0.0;
bar.b = foo.b > 0.5 ? 1.0 : 0.0;
bar.a = foo.a > 0.5 ? 1.0 : 0.0;

So, back to the issue of getting “odd results”. I suspect the issue you’re having has nothing to do with the above function, and more to do with linear vs gamma color spaces. Photoshop does all of it’s blends in gamma space, but if your Unity project is using linear color space, then the color values your shader is working with is linear space color values, which won’t look the same when blended with an overlay.

You can either change your project to gamma space, or you can convert the values to gamma space in the shader to do the conversion and back to linear to output.

1 Like

Thanks so much @bgolus . That’s a very clear answer!