Shader Programming, Volume 13

The Grab Pass Technique

Sebastian Monroy
6 min readFeb 14, 2017

It’s been a while since my last article about Vertex and Fragment shaders, but I’m back at it and determined to get better at shader programming. I just had to quit my job first.

The first thing we’re going to learn in this article is how to make a shader that effectively does nothing… but in doing so we’re going to acclimate ourselves to what they call the Grab Pass technique. It’s sort of like the “Hello World” of Grab Pass shaders. Immediately after that we’re going to make a Stained Glass shader, which is pretty neat.

But why should you care about Grabbing Passes? The last time you cared about that your over-masculine father was making you try out for football despite your slender frame, fending you against your weirdly muscular teenage peers— and why would you want to stir that memory up again?

Imagine you’re trying to simulate the effect of glass or water. The transparent materials we’ve made in the past can draw over a scene just fine, but they can’t change what’s drawn underneath them. Especially for water or stained glass, it’s very important that the light passing through the material is distorted. Refraction. Grab Passes allow just that — they give us access what has already been drawn on the screen so far so we can alter it.

That’s why you care about Grabbing Passes, son. Now get out there and make your pop-pop proud.

Chapter 6.2

Fragment Shaders and Grab Passes, Using Grab Pass

For our first foray into Grab Passes, we’re going to create a material that grabs what’s rendered behind it and draws it again on the screen. Like I said, it does pretty much nothing. But it does nothing WELL. It’ll be good practice, anyhow. Let’s do it.

Go ahead and make a new shader and material to host it, then attach the material to a quad. Place the quad in front of another object so that it obscures part of the other object. Yadda yadda yadda.

Here’s what a basic Grab Pass shader looks like:

The first thing you probably noticed is line 14, where it says GrabPass {} . Previously, all of our code has been placed directly in the SubShader section. This is because our previous shaders only required a single pass. We’ll need two passes this time around, though. The first pass is the grab pass, as defined by line 14. The rest of the code is in the second pass, contained in the Pass block.

The second pass is structurally no different than the shader we made in the previous article. Vertex function vert gets the position of the vertex and then the fragment function frag gives it a color. The difference now is that the vert function also calculates another important detail: the UV data for the grab pass.

The grab pass automatically creates a texture we can refer to as _GrabTexture , as definied in line 24. To sample this texture correctly, we need its UV data. We can accomplish this using the ComputeGrabScreenPos() function, which returns the UV data so that we can use it later to sample the grab texture correctly.

Having done all that, the end result should be that our quad should display everything that is rendered behind its geometry with a slight red tinge.

Ta-da!

We did it!

I was going to end the article there… but gosh that was boring, let’s do something cool with it.

Chapter 6.3

Fragment Shaders and Grab Passes, Implementing a Glass Shader

Most glass is imperfect, its deformations distorting the light as it passes through. Now that we’ve learned about Grab Passes, we can attempt to reproduce this effect. We’ll do that by building upon our previous shader, a Vertex and Fragment shader with a Grab Pass, and changing the Grab Pass’ UV data to create the distortion.

Here’s what that looks like in code:

The heart of this effect is in the second pass’ frag function, on line 63. The normal map is unpacked and used to offset the UV data of the grab texture. This is the operation that simulates the distortion caused by the stained glass.

As simple as the effect is, it can simulate pretty realistic stained glass. Check it out:

Not bad! You can clearly see how the stained glass is distorting the image rendered behind it. As you can imagine, this effect can be quite useful. Whether it’s for simulating complex transparent surfaces or heat waves of explosions, the Grab Pass technique is robust indeed.

Now that we know a little bit about Grabbing Passes, let’s hit a home run touchdown slam dunk by making a simple 2D Water Shader.

Chapter 6.4

Implementing a Water Shader for 2D games

While the previous stained glass shader was pretty neat, the thing about it is that the distortion the glass produces is static. What if we could somehow animate that distortion. Then we’d be able to make some pretty groovy stuff, I think. Let’s go with it.

Get started by making a new shader and material. Assign the new material to a plane.

The shader looks like this:

All that’s really changed from the base Grab Pass shader is that we added a few input variables, populated a few more vertOutput struct parameters, and added a little more logic to the fragment function. Let’s go into that a little more.

The distortion variable calculated on line 78 is important. This calculation replaces the more simplistic one we did for the distortion of the Stained Glass shader. The distortion is determined by the _NoiseTexture we pass into the shader. But instead of simply sampling a static texture, we’re offsetting where we sample the _NoiseTexture by _sinT. The _sinT variable is sinusoidal and time-based, its period determined by the input parameter _Period. So essentially we’re still using a static texture, but we’re animating the method by which we sample that texture. Then we’re using that sampled value to distort the _GrabTexture.

Functionally it’s pretty similar to the Stained Glass shader, really, but the animating goes a long way. Check it out:

Cool, right? It isn’t perfect — you’ll notice some tearing on the water that looks totally unnatural — but it gets the idea across. At the very least, I expect you think Grab Pass shaders are pretty useful by now! There are a lot of things that would be impossible without being able to sample from what has been already rendered. And that’s all the Grab Pass technique does — it allows you to sample the rendered scene as if it were a texture.

Alright, that’s all I’m going to talk about for Grab Pass shaders. I’m going to skip the chapter on “Mobile Shader Adjustments” for now, so next up: Screen Effects. :)

--

--