Traditionally, having a dielectric object enclosed inside another dielectric object (like a liquid inside a glass) is a complex geometric situation due to the difficulty in defining the surface that delimits those mediums. As the liquid fills the entire volume leaving no gap, that surface limit becomes geometrically difficult to define with polygons. The typical approaches to this situation, and that don't produce a correct result, are:
model the liquid body to have coinciding faces with the glass body (with their polygons in exactly the same coordinates). In this case the render process has errors in precision as, at each point, half of the rays will evaluate a glass surface (ignoring the liquid) and the other half will evaluate only a liquid face. This is not what happens in a real situation (see picture below).
model the liquid body slightly smaller than the glass to avoid those coinciding faces. In this case the small "air" gap in between will not produce the typical TIR (Total Internal Reflection) effect that is visible in these situations, making the result visually different than what is expected.
model the liquid body bigger than the glass, invading its volume. With this approach the invading volume will be assumed to be composed by a mix of glass and liquid materials, also causing an incorrect result.
Modeling the glass and liquid bodies with coinciding faces produces precision errors in the coinciding walls
In fact, no approach involving two coexisting surfaces (the glass and the liquid walls) will produce a correct result. The real situation is more complex, it doesn't have two surfaces but one single limit surface that behaves like either glass or liquid depending on the direction of the incoming ray. And as this behaviour depends on the direction of the incident ray, it can not be recreated with a back-face material either.
So far, the only way to overcome this situation and produce a correct result was the "infinitesimal gap" that is explained in this page: Tips and Tricks: Liquid in a glass.
This method involves the liquid body being completely enclosed in the glass body, which doesn't have inner walls where the liquid exists. This way there is only one single wall, instead of two, to define the limit area between the glass and the liquid medium. The method also involves a third material - glass exit material - over the liquid upper surface to provide the correct order for the rays exiting the glass medium in certain directions.
This method has the disadvantage that makes the model setups very complex, less flexible and not suitable for animations.
The "infinitesimal gap" method was the only way to ensure every ray enters and exits the mediums in the correct order
The best way to overcome this situation is by using the nested dielectics approach. Using this approach, two dielectric bodies can overlap and the render engine can automatically "boolean" them in render time and remove the surplus volume leaving just one single polygon wall, and assign the proper material for that single wall depending on the direction of the incident ray.
This method works by putting the two dielectric materials in contact by priority order that you can define, indicating that when those dielectric bodies overlap, the renderer will automatically fill the overlapping volume only with the material of your choice.
The Nested Priority value is defined in the material basis and is set in the Global Properties level. The lower this value, the higher its priority, meaning that where a body with priority 0 and a body with priority 1 overlaps, the overlapping volume will be filled only with the priority 0 material.
The nested priority value is only taken into account when one material intersects another; when this happens, the position in the queue of priorities determines which material prevails over the other. So Maxwell will understand that in the intersecting volume, only the material with higher priority exists, generating the right index of refraction in the contact wall and disregarding the lower priority material in that volume. You can think that this works a bit like boolean operations where the material with lower priority (higher number) is removed in the intersecting volume.
Setting the Nested Priority parameter of a dielectric material on the Global Properties level
In our liquid inside a glass example, the liquid can now be modeled slightly bigger, invading the glass body, and setting the glass priority to 0 and the liquid priority to 1 (or any value higher than the one assigned to the glass). This way the overlapping volume will be filled by only glass, the liquid wall will be removed, and the remaining walls will later properly get either the glass or the liquid material depending on the ray direction.
By nesting the dielectric objects and assigning the correct priorities, the objects setup becomes easier allowing overlapping (left).
In render time, the overlapping liquid volume gets automatically removed, leaving one single face and the materials properly assigned with respect to each ray direction (right)
What if we add some ice cubes?
If we want to throw some ice cubes into the liquid, we will end up with the a similar situation: inside the ice cubes' volume there exists at first two different materials coexisting (liquid and ice), which is not what would happen in the real world, where only ice fills that space. In this case we need to assign a higher priority (lower value) to the ice and a lower priority (higher value) to the liquid.
The priority assignment in this example should be:
glass material: priority 0 (0>2: where glass and liquid overlaps, glass remains)
liquid material: priority 2
ice material: priority 1 (1>2: where ice and liquid overlaps, ice remains)
This way, the liquid gets "booleanized and removed" by the rest.
Values are set to establish the proper order when they overlap (the material with lower priority value remains) but the numerical value itself is irrelevant (setting 0 and 1 for two dielectric materials produces the same result as setting them to 7 and 11).
Using Nested Dielectrics to make cavities or bubbles
If you use the Nested Dielectrics feature with a material that simulates air, you will find it very easy to create bubbles or cavities into other objects. The idea behind this is generating a very transparent material and set it before in the nested priority queue (lower number) than the main object (higher nested priority number).
You can get something like these bubbles inside a cube (click on the image to see it larger):
In this case, the bubbles material has Nd = 1 and transmittance almost full white (254,255,255), attenuation distance is set to 999m and roughness = 0. If the transmittance is set to white it would create what we call a ghost material and it won't work in this case.
Nested Priority is set to:
Bubbles = 0
Main geometry = 1
This way, the geometry of the bubbles gets subtracted from the main one.
Here is the scene in case you want to play with it: Bubble.zip