Saturday, March 28, 2015

Graphics Blitting in Unity Part 2: Caustics

I know I promised to do something with ping pong buffers but I remembered an effect I did a few months ago to simulate caustics using a light cookie.  You might have seen some tutorials or assets on the store that do something like this.  Usually these techniques involve having a bunch of pre-baked images and cycling through them, changing the image each frame.  The issues with this technique are that the animation rate of your caustics is going to fluctuate with the frame rate of your game, and of course that you need a bunch of images taking up memory.  You also need a program to generate your pre-baked images.

If this were unreal you could set up a material as a light function and project your caustics shader with the light.  This isn't a bad way to go but you end up computing the shader for every pixel the light touches times however many lights you have projecting it.  Your source textures might be really low (512x512) but you may be running a shader on the entire screen and then some.

This leads me to a solution that I think is pretty good.  Pre-compute one frame of a caustics animation using a shader and project that image with however many lights you want.


Web Player

Asset Package

In the package there is a shader, material, and render texture, along with 3 images that the material uses to generate the caustics.  There is a script that you put on a light (or anything in your scene) that stores a specified render texture, material, and image.  In the same script file there is a static class that is what actually does the work.  The script sends the information it's holding to the static class and the static class remembers what render textures it has blitted to.  If it is told to blit to a render texture that has already been blitted to that frame it will skip over it.  This is good for if you goof and copy a light that has script on it a bunch of times, the static class will keep the duplicate scripts from blitting over each other's render textures.  Now you can use the render texture as a light cookie!  The cookie changes every frame and only gets calculated once per frame instead of once per light.

Some optimizations would be to remove caustic generators when you are not able to see them, or have a caustics manager in the scene instead of a static class attached to the generator script.  The command buffer post on Unity's blog has a package that shows how to use sort of a manager for stuff like this so check it out!

2 comments: