Heat & haze effect (or simply heat haze which seems to be more proper term even though the first one is more frequently used in regards to RT graphics) is the effect caused by the difference in air temperatures along the view vector. As the light from the object travels to the observer it is reflected and refracted differently by those different medias (reflection is of course caused by particles present in the air). If the air moves slightly (you know warm air travels up and cooler travels down) it can cause shimmering of some objects in the distance. Of course it is only visual impression. This effect can be noticed above hot ground (especially asphalt or scorched desert sand which can cause appearance of mirages) in summer when air seems to float just above it.
The same effect can be well seen if there are big differences in temperatures, eg. fire is hot but the air several meters from it is much cooler. However internal workings are exactly the same.
Although these are same phenomena the implementation of each of them is slightly different. Both can be done as the post-process effects though. This time I'll describe distance heat haze only.
What we need for implementation of it is Z-buffer contents. Besides the easiest thing would be to simply displace texture coordinates for reading from the current scene texture.
The effect is applied starting at some given distance. Think for it for a while. Whenever you see it on the photos, in the movies or in the real world it doesn't start very near the observer but rather further away. It's because close to the observer the differences between temperatures of air are very small so there are not many different medias through which the light rays travel. So these rays aren't refracted that much (each medium refracts it on its own).
Also this effect is stronger near the ground where air is hotter due to closeness of warm objects so what we have to do is to weaken it along y axis (from maximum strength to 0). Besides what makes it stronger is temperature. We can assume that the hotter the object, the brighter it is. So we just have to calculate luminance of the pixel and multiply final effect by it. It all makes strength attribute used below.
So finally we can use sine and cosine functions to apply the effect using time as input. To give some variation we add some random data to it (position is good for that and we can read it from Z-buffer).
texCoord = strength * float2(sin(timer + position.x), 0.25f * cos(timer + position.z)) * maximumHaze;
Note that the movement along the x axis is stronger. For me it seems this makes the effect more realistic. maximumHaze is the maximum displacement value and strength is computed as mentioned above. texCoord is then used to sample frame buffer. We return this read colour as the final one.
Here are the results. Note the effect is very subtle but improves the quality of the terrain renderer and realism. Compression makes it even more subtle but in the first few seconds (especially when watching 480p version) you should be able to notice it quite easily.
It will be available in a few days from now in the repository with a lot of other useful changes.
Huh, it's one of "see for 10 minutes to find 5 differences" videos ;)
ReplyDeleteBTW heat haze can also be interesting if implemented with additional texture with texcoords mods (perlin-like), it's nice with steam from pipes etc
About texture - you're right. I'm using it even here ;) As for the 5 differences... that's right too :) I mean when run on PC missing this effect is hard but Youtube compression degrades the quality so much it's hard to notice... does anyone know of a service which doesn't compress that much?
ReplyDeleteMaybe try Dailymotion or Vimeo, as far as I remember they allow HD uploads.
ReplyDeleteNice! I've never seen heat haze effect implemented for the ground in any game. The concept of using pixel brightness is very clever. But as for calculating displacement vector, I'd rather use some texture instead of sine function.
ReplyDeleteThx Reg, I use both sine and texture but probably good texture would be enough (I just couldn't get the results right this way so I had to improve it somehow).
ReplyDelete