Finally got around tweaking the shader and writing something about it. Also updated the sample usage:
So, this kind of mirage is happens due a difference in the temperature of air layers.
If you’re interested in the mechanics behind it Wikipedia will tell you all about it. What I can tell is that I’m striving for a physically realistic depiction of it, not a physically accurate one. I don’t think it’s even possible to reproduce this phenomenon in Blender at the moment; any approach will need to use some tricks to fake it—smoke and mirrors. Well… mirror and mirror:
I did it with two planes, one behind the camera to capture what it’s seeing, another behind everything to reflect the reflection of the first plane back to the camera.
If you set them up with the right constraints you can make them always face each other and lock positions and rotations with the camera so you don’t have to do this manually. But making sure they don’t fall out of sync with the camera is just the start.
Simply placing two reflective planes facing each other won’t work because you’d see the back of the scene in the second one. You need to reposition the reflection in a way the real one gets occluded by the scene and only the reflection of the reflection appears. This can be done with normals.
I was most successful using the Incoming output of the Geometry node for this task. Here’s what the manual has to say about it:
Incoming: Vector pointing towards the point the shading point is
being viewed from.
Once you have a vector input always pointing to the camera it gets easier. A Mapping node can be used to reposition it, even rotate it and flip it so it shows what you need.
The shader of the plane receiving this reflection is more complex. Superior mirages seems to always display at least an upside-down reflection over the object, often appearing as an inverted projection underneath a not inverted second projection. They’re also pretty dynamic, being made of heated air.
To do this I blended a regular and an inverted reflection and used a noise node to create the air distortion.
The ending result is pretty convincing, and may be more than enough depending on your needs. There are a couple of limitations though I simply don’t have the energy to sort out. The first one is the deformation caused by the Incoming normal:
Depending on the angle it’s possible to straighten that arc with changing the rotation in the Mapping of the camera plane. It’ll, however, deform any reflections far from the center of the image. Another limitation is not being able to compress and stretch parts of the reflection at will to better reproduce the distortions seen in a real mirage. The faked mirage may also seen a bit faded out under some circumstances, but that can be fixed by using an array modifier to duplicate the plane.
Another serious limitation is accidentally catching the reflection of everything above the “horizon line”, so setup your scene with this in mind; and the final one is about HDRIs: if you’re not careful things get weird!
You can grab the demo above (minus HDRI) to play with the nodes here: DEMO_superior_mirage.blend (164.9 KB) .
Let me know if you figure your way around the limitations!