Refraction Shader Tutoral

This sample was again created to help out a community member with a shader issue. The OP was having trouble converting an ols XNA shader to MonoGame, so I took a copy of the shader and managed to tidy it up as best I can.

The project I created in the samples repo is CommunityPost11896.

Looking at the C# code in the draw call, we are simply rendering the texture, and the displacement map first, followed by the result of them being passed to the shader.

As you can see, we only need to pass the displacement texture to the shader, as the sprite draw call sends the other texture and puts it in register(0) for us.

So, lets look at the shader and see what it's doing.

We have a float2 DisplacementScroll, and this is used to set the direction we want to move the displacement in.

We have samplers for the sprite texture and the displacement texture to be used.

All the magic happens in the pixel shader, you can see I found an issue with the MonoGame shader compiler, the first texture MUST be sampled first, even if nothing is done with it or the following texture samples are done in the wrong order. This was in MG 3.6, so I am hoping this is fixed in MG 3.8+

So, what does it look like if we comment out that initial texture sample in the shader?

As you can see, the render is broken now, I don't know exactly why as this is occuring within the MG shader compiler I beleive.

Anyway, onto the working shader, and what it's actually doing...

So, in esence, we are reading the x and y values (Red and Green) channels from the displacement texture, offset by our DisplacementScroll value so we can scroll the displacement it's self, we can then add this to the original texcoord and use that to sample out texture and so, give a displacement effect.

Now, this code is taken from the original shader, as referenced at the top for the shader.fx file, and to be honest, I am not sure why they have done it that way. There is no need to divide the texture coords when reading the displacement texture by three and then multiplying that by .02 - .15.

Doing this will give the same effect

As you can see there are less arithmatic slots used, like this, I also think it looks less confusing, and you could also turn the * .01 into anothervariable and you could then scale the displacement by that variable.

I hope this has given you a bit more insite into this sample shader and how it does what it does. As ever, all comments are welcome :)

The samples GIT Repo can be located here

The original post can be found here.

Become a patron to

Unlock 16 exclusive posts
Be part of the community
Connect via private message