Wow! Thank you so much, it worked! I just multiplied the R and G channels of the world position node by the R and G channels of the inverse of the light vector, and it shears the texture accordingly!
I now have an almost fully functional caustics rendering function: it uses a custom mip function to blur the caustics and lower the intensity of the light as caustics scatter deeper into the water. It also cuts off completely at sea level. It works with a light vector blueprint, whatever normals you have, and can be applied to any object for a very nice effect. 30 instructions, plus whatever lighting model you want to use, and you can have underwater caustics almost as good as Cry Engine!
The only thing it’s missing is the shadow environment: because all this stuff gets plugged into the emissive channel, it lights up in areas that should be blocked by shadow. And since there’s no way to completely remove GGX specular rendering by height, there are some extra instructions there for specularity that doesn’t exist. I wish there was a way to access the shadow environment in the material, or build custom lighting within the material editor. Until then, this is the best that can be done to render caustics.