Shader Programming, Volume 15

Photoshop-like Screen Effect Shaders

Sebastian Monroy
4 min readOct 23, 2017

Chapter 8.2

Brightness, Saturation, and Contrast with Screen Effects

We’re gonna take the same process for creating Screen Effects we learned in the last article and use it to implement a Screen Effect shader that gives us control of the Brightness, Saturation, and Contrast of our scene.

Go ahead and make a test scene with a three spheres of a different color. Make a new script called BSCImageEffect.cs and a new shader called BSCImageEffect.shader and attach the script to the camera. Just like the last scene, really. I threw a skybox in there for good measure.

Anyway, here’s the shader code:

In the BrightnessSaturationContrast() function you may be unfamiliar with some of the calculations, as I was, but apparently the calculations and coefficients are based on CIE color matching functions and are pretty much industry-standard, if you believe the book. luminanceCoefficient variable stores values that give us the overall brightness of the image. We can get the overall brightness of the image by doing a dot product of the current image with these luminance coefficients. After that it’s a simple matter of using lerp functions to blend between zero saturation and maximum saturation, as well as minimum contrast and maxium contrast.

And here’s the script code to work with that shader:

Don’t forget to attach the BSCImageEffect.shader to the BSCImageEffect.cs script in the Inspector!

After all of that you should have a scene that you can manipulate like this:

Brightness, Saturation, Contrast Image Effect

Next up on our mission to recreate Photoshop in Unity (for some reason), implementing Blend modes with Screen Effects!

Chapter 8.3.1

Creating the Multiply Blend Mode with Screen Effects

Create a new script called BlendModeImageEffect.cs and shader called BlendModeImageEffect.shader. You can copy the script and shader code from the previous section to start with.

You’ll also need a texture. Here’s a grunge-y one I found:

image via https://goo.gl/34wJMk

Just import it with the Default texture type.

The shader code is as follow. Nothing crazy.

And then the C# script code is like this. Again, very similar to our last one.

We’re gonna be using this same script for all of our screen effects, so hold it close.

With that done, we can assign the screen effect script to the main camera, our screen effect shader to the script in the Inspector, and then the grunge texture to texture field of the BlendModeImageEffect component in the Inspector.

In action it looks like this:

Multiply Blend Mode

Implementing the Multiply blend mode is actually quite simple with shaders. A fragment shader is perfect for this kind of thing. A multiply blend mode is just a matter of taking each pixel from the original render texture and multiplying it with each pixel of the blend texture, as we did in line 32 of BlendModeImageEffect.shader.

Chapter 8.3.2

Creating the Add Blend Mode with Screen Effects

It’s just as easy to implement the Add blend mode too. Instead of multiplying each pixel, we just add them. So our Add blend mode shader would only differ by one line, line 32, and look like this:

If you find that nothing changes after replacing the Multiply Blend Mode shader with the Add Blend Mode shader on the BlendModeImageEffect.cs component in the Inspector, try disabling the component and re-enabling it again. That worked for me.

Add Blend Mode, BlendOpacity = 0.5

Chapter 8.3.3

Creating the Screen Blend Mode with Screen Effects

The Screen Blend mode is a little bit more mathematically intensive than the Multiply or Add blend modes, but again it’s just a matter of changing that one line in our shader again, line 32.

Looks like this!

Screen Blend Mode, BlendOpacity = 0.5

Very similar output to the previous two Blend Modes but there are definitely some differences.

Chapter 8.3.4

Creating the Overlay Blend Mode with Screen Effects

Okay, one more Blend Mode to go — the Overlay Blend Mode.

For this one we’re going to use essentially the same shader as the other Blend Modes’ but we’re going to break out the Overlay blend math into its own function, OverlayBlendMode(), on line 25.

When the Overlay function receives a pixel, it checks to see if its value is less than 0.5. If it is, we apply a modified Multiply Blend Mode to that pixel. Otherwise, we apply a modified Screen Blend Mode to the pixel. We perform this operation for every pixel in every channel, giving us RGB pixel values for our final Overlay effect.

The Overlay Blend Mode really just conditionally applies the Multiply Blend Mode or Screen Blend Mode. Easy!

Overlay Blend Mode, Blend Opacity = 1

Alright, that’s all I’ve got for you for this chapter. The next chapter is going to be about using these Screen Effects to accomplish something relevant to gameplay. Like an vintage movie screen effect. Or a night vision goggle screen effect. :)

--

--