Cycles - Volume Refraction shader

This is something I’ve been wanting to get to the developers to for ages. I’m primarily making this thread in hopes that one might see it, and also to link to it in case I find anyone in the #blendercoders IRC channel. Thoughts from anyone are appreciated however!

I wish to ask for what’s hopefully a simple yet effective addition to Cycles, which would make currently inaccessible effects possible to do natively in a realistic fashion: Implementing a volume refraction shader. Either by allowing the existing Refraction BSDF to work on the Volume material output, or by defining a new Volume Refraction shader if that is a better approach.

Suggested functionality: When a ray passes through a volume affected by this shader, its trajectory is bent, just like Glass BSDF or Refraction BSDF does for surfaces. Optionally, an IOR value may let users define the probability and / or angle at which rays have their course modified, whereas a Roughness value adjusts how blurry the view gets through such a volume… the two ideally operate in an independent way so that refraction and blur can work without one another.

Purpose 1: The most important practical use of this shader is proper heat haze, emulating the air deformations we see above hot ovens / jet engines / roads during summer days. As a workaround, this is already possible to do with render nodes, by rendering your volume as a black & white mask on a different render pass then plugging it into the Vector input of a Displace node through which the main render is passed. However this is just a workaround that so happens to work: It leads to quality loss due to smudging and stretching the render result, causes empty spaces if the transformation of the mask warps near an edge, is much less realistic compared to the ray actually traveling a different trajectory, and might ultimately be slower depending on what calculations are implied.

Purpose 2: This would allow a greater level of detail for objects such as crystals, diamonds, gems, ice crystals, and other types of rough glass. You can already design realistic crystals in Cycles, by customizing the IOR and Roughness of a Glass BSDF or Refraction BSDF, causing different spots to refract or blur in different amounts. However you can’t differentiate such spots volumetrically inside the crystal itself, and can’t create rough blurry strands or inner glass pieces that have a different refraction angle from others. This can of course be worked around by adding smaller meshes inside the main crystal and giving them different materials, but this technique will cause sharp edges and is less correct and flexible compared to volumes in many cases.

As of now, you can base the IOR value on the output of the layer weight node (facing output). That in combination with a curve node should give a nice heat-signature effect on round objects without noticeable edges.

Another way is you map the IOR according to the output of the ray length output (lightpath node). You can combine it with the above technique to get the correct fading (but with the addition of stronger refraction in thicker geometry).

As for having an actual refraction volume, I may have read that that there might be a possible issue in ensuring it renders nice and fast (though perhaps a basic refraction volume with power and roughness inputs could be doable).


No roughness for refractions?
It really is an important part missing from Glass & such. How come?
Been faking it since start but every time i hate the results… i simply am not able faking it to look real. :frowning:

I’m still very interested in seeing a resolution to this issue. There is still no way to do heat haze or atmospheric refraction using rays in Cycles, which is a huge missing feature in my opinion! Is there no way to get this to the attention of the Blender devs?

I remember that when I brought it up with the developers on the mailing list months ago, I was told that a technical solution is hard. Something about knowing when a ray enters a volume but not when it exits it, thus it’s harder to calculate the depth. Come on though: Absorption and Scatter have a way of working out, I’m sure one exists here too! I for one am content with just diffracting the angle of the ray a little based on the density at that location… how can that not work, or be too difficult to implement?