Shader Programming, Volume 14

Screen Effects with Unity Render Textures

Sebastian Monroy
4 min readOct 12, 2017

I played around a lot with what we learned about Grab Pass shaders in the last article, but I’m ready to move on to Chapter 8 and learn something about Screen Effects!

A lot of people use shaders for the purposes of creating “screen effects”. Effects like Bloom, Motion Blur, HDR, Chromatic Aberration, depth of field, color correction, and so on and so forth. The purpose of Chapter 8 is to teach us how to utilize screen effects at a basic level. Let’s dive in.

Chapter 8.1.1

Setting up a Screen Effects System, Creating a Grayscale Screen Effect

Begin by setting up a new scene with just a camera, a directional light, and a sphere. Create a new shader and call it GrayscaleImageEffect.shader. Create a new specular material and assign it to the sphere. Also create a script called GrayscaleImageEffect.cs.

Your scene should look something like this so far:

Now that we’re all set up, let’s get started making a grayscale screen effect. :)

I’m going to spill the full GrayscaleImageEffect.cs script here and provide helpful comments in each section of the code, instead of pausing to explain each step like the book does. Feel free to ask questions in the comments if anything is unclear!

Let me just address a couple of things that might be new to you here.

First of all, the Graphics.Blit() function is one you’ll see used to implement many post-processing effects, so it’ll be useful to familiarize yourself with it now.

Blit() sets destination as the render target, sets source _MainTex property on the material, and draws a full-screen quad.

Essentially it is responsible for copying the source texture into the destination render texture with a shader. This can take some time to wrap your head around if it’s unfamiliar, but if you’re anything like me, you’ll learn best by doing, so we’ll continue.

The OnRenderImage() function is also worth pointing out. I don’t think we’ve used it yet in this series of tutorials. It’s a built-in Unity function that gives us access to the Graphics’ renderTexture. Using the Blit() function, we can then pass that renderTexture to our shader and return the processed texture to the Unity renderer.

Mull these things over for a bit because this technique is supremely useful for Screen Effects, among other things.

Anway, you can go ahead and attach the TestRenderImage.cs script to your Main Camera, but because we haven’t assigned the curShader variable you’ll get an error. Let’s make a shader for the script, shall we?

All this shader does is interpolate the base Render Image toward a given color, in this case a rgb(0.299, 0.587, 0.114) green-ish gray color, based on the inputted _LuminosityAmount.

Unfortunately, the book provides no explanation about what the

#pragma fragmentoption ARB_precision_hint_fastest

line does, but here’s some documentation I found for it, at least. My guess is that is has something to do with allowing us to use the lerp() function in the frag block, but someone please correct me if I’m wrong!

Set this shader as the curShader of our TestRenderImage.cs script, mess with the grayScaleAmount variable, and watch what happens.

And there you have it! Our first Screen Effect. How momentous!

We’ll be using this same basic structure to create more Screen Effects, too.

Like a Scene Depth effect! Let’s give that a try now.

Chapter 8.1.2

Creating a Scene Depth Screen Effect

Create a new shader called SceneDepthImageEffect.shader. It’s gonna look like this:

We’ll also need a corresponding SceneDepthImageEffect.cs script to attach to the Main Camera and give us access to the _DepthPower property of the material, just like we did with the grayscale effect. It’s pretty much functionally the same as our previous GrayscaleImageEffect.cs script, but with a few minor modifications to work with our new _DepthPower property instead of the _LuminosityAmount property.

Once you’ve disabled the old GrayscaleImageEffect.cs script, attached the new SceneDepthImageEffect.cs script, and set its curShader to the new SceneDepthImageEffect.shader shader, you’ll see this result:

(Note that I added a floor plane just to make the effect a little more obvious.)

I think I’ll wrap this article up just because it’s a good stopping point. We’ve covered the fundamental knowledge needed to create your own Screen Effect shaders and provided ourselves a good foundation for learning how to make some more advanced image effects.

In the next article, we’ll look at implementing screen effects like saturation, brightness, and contrast. If we’re lucky, we may even get to creating Photoshop-like Blend modes like the Multiply, Additive, and Screen Blend modes. :)

--

--