In the real world, light refracts and reflects when it hits the boundary between two dielectric (i.e. transparent) media which have a different index of refraction (IOR). For example, in the following glass of liquid, light refracts at the various boundaries between the air, glass, liquid and ice.
Creating such a scene in a renderer is typically accomplished by modelling the glass and water as closed meshes (filled with constant IOR material) which are either flush, intersect, or have an air-gap. Or in some renderers, one has to explicitly model each interface where the IOR changes, flagged with the IOR on each side. Manually breaking the scene up like this into separate interfaces where the IOR jumps is very inconvenient. Also, modelling geometry as flush or air-gapped produces various artefacts.
So the approach taken in Arnold (and many other renderers) is to use nested dielectrics, which means the scene is modelled by making the dielectric objects overlap, and in the areas of space where they overlap, the material is resolved into one of the overlapping dielectrics via a priority system. This correctly tracks how the IOR changes as the rays refract leading to realistic renders.
Why priorities are neededGlass of water exampleTo clarify these notions, let's use a glass of water as an example. This involves four transparent media (that is the glass, the water, the ice, and the surrounding air), which are all dielectrics defined by an index of refraction (or IOR). Of course, other non-dielectric media may exist in the scene, such as the metal table on which the glass sits.
At the boundaries between the dielectric media, the IOR in general jumps from one value to another as the ray transmits through the interface. On rendering this object the ray reflects or transmits at each dielectric boundary, and the Fresnel factor and refraction direction at each surface is determined by the ratio of the IORs on each side of the boundary. So how do we set this up in a renderer? First, a couple of approaches which Arnold doesn't use, to compare. Explicit IOR jumps One approach as mentioned above is to explicitly model the various interfaces, specifying for each the IORs on the exterior and interior side (as depicted below). This would involve breaking up the object into separate meshes for each interface, or tagging faces somehow. While this is a correct approach which some renderers take, it's obviously very inconvenient for an artist to have to do this, especially if the geometry is complex and/or animated. Air gapping or flush interfaces Another approach is to model closed meshes with well-defined IORs and put air-gaps between them so they don't touch or overlap, as below. This is perhaps slightly more convenient than breaking up the model by interface but unfortunately isn't physically correct as it generates inter-reflections in the air gaps. Another bad approach is to model the surfaces as exactly flush, which introduces numerical imprecision issues.
|
dielectric_priority (found under transmission of standard_surface) is an integer (default 0) which can be positive or negative, where higher priority numbers override lower priorities. So for example, if glass with priority 2 overlaps water with priority 1, then in the overlap region, only the glass survives. Negative priorities are allowed, so, for example, a priority 0 object would override priority -1 (as it may be convenient to use negative priorities sometimes to specify a lower priority medium than the default 0). |
Some other renderers have a lower number mean an effectively higher priority. We think this is unnecessarily confusing, so instead higher number corresponds to a higher priority, which overrides the lower number. |
The most basic effect of the priorities is illustrated by these overlapping glass spheres with an interior scattering medium:
Note that for dielectrics with internal absorbing or scattering media, transmission_depth needs to be set. For example, see the orange juice example below. |
If equal priority dielectrics overlap, then their internal properties merge, i.e. the IORs average and the internal volumetric media are mixed (thus if two equivalent dielectrics with equal priority overlap, they effectively are merged). |
There is a global switch to disable nested dielectrics called dielectric_priorities. Dielectric priority disabled can be read as "no priority". In this case, the surface is never removed and the surface ignores any surrounding dielectric in which it may be embedded, treating the exterior as a vacuum. This functions as an unphysical mode (legacy) which preserves the look of scenes prior to the introduction of IOR tracking, and which also may be faster to render than if tracking is enabled.
|
In the case of a glass of whisky, we expand the whisky mesh to overlap the surrounding glass and give the whisky a lower priority than glass. The whisky boundary within the glass then functions merely as a "proxy" mesh which indicates the presence of the lower priority whisky. We also give the whisky a lower priority than the ice, so the ice displaces the whisky. For example with the priorities shown, this defines the correct IOR at every point in space.
Liquid (1) has a lower dielectric_priority than the ice and bubbles (2). Glass (3) has the highest priority. |
As mentioned, low priority "false" interfaces are cut away and effectively light passes through them undisturbed. Consequently, any shading parameters such as roughness take effect only at the real interfaces. However, not all shading parameters are completely ignored on the false interfaces – the shader parameters which define the interior of the dielectric medium are still taken into account as rays enter the dielectric medium (as the standard_surface shader also allows specification of an internal scattering medium "embedded" in the dielectric). These are the following:
standard_surface shader parameters which determine the interior properties of nested dielectrics are:
|
Setting these parameters on the water in the example above means that the interior of the water will be assigned these properties, even though the water interface inside the glass is false.
For example, if we want to render a glass of orange juice (see example below), the liquid mesh overlapping the glass mesh is low priority but it is necessary to set both transmission_color to orange and to set the transmission_depth in order to specify that the Beer's law absorption in the interior "bulk" of the juice is orange coloured (plus some optional transmission_scatter):
|
Note however that any purely surface properties such as roughness (textured or constant), will only take effect if applied to the real boundaries which remain after priority resolution. |
Parameters of the standard_surface shader which do not control the interior properties of the dielectric medium will be ignored if applied to the false interfaces of low priority objects. For example, in the glass of orange juice example if we set zero transmission_depth (which is the default), the transmission_color functions then only as a surface tint, which as it occurs on the false boundary of the juice inside the glass, is ignored in the interior "bulk" of the juice leading to an incorrect look:
Bubble renderingRendering of bubbles (in glass, say) should be achieved by giving the bubble geometry a higher priority than the glass and the IOR of the bubble interior (e.g. specular_IOR = 1.0, for air). In the example below, specular_IOR has been set correctly for both glass: 1.5 and air bubbles: 1. The dielectric_priority is set to 1 for the glass, and 2 for the air bubbles.
|
Rendering realistic reflections and refractions in complicated geometry may require a high ray depth due to the large number of internal reflections which can occur.
Ensure that the specular/transmission/total ray depths are high enough, otherwise, the liquid/glass may appear dark.
|
Note that increasing specular_ray_depth can dramatically increase render times. |