Fluid in a Glass

(and why you’ve been doing it wrong your whole life)

Common method vs physically accurate method

Common method vs physically accurate method

It’s hard to imagine a world without wine-glass tutorials, there are hundreds of them! Heck, I made two myself a few years ago.

But there’s a problem! We’ve been teaching (and learning) the wrong method this whole time! I know it’s a bad idea to teach complicated physics stuff in a noob tutorial, but teaching the wrong thing sounds a bit worse.

So good morning class! Today we’re going to learn about interfaces! (not that kind of interface). Open your text books to page 269 and lets find out why we’re all idiots!


This is probably the method you know – a normal model of a glass with some liquid fitting snugly inside it.

The reason why this is wrong is because it leaves a small air gap between the fluid and the glass, and the bevel of the liquid at the top is the wrong way around.

Cue interfaces:

An interface is a surface forming a common boundary among two different phases of matter, such as an insoluble solid and a liquid, two immiscible liquids, a liquid and an insoluble gas or a liquid and vacuum. [wikipedia]

The index of refraction (IOR) of water as we know it is 1.33. That of glass is about 1.5 (depending on the type). Great. so punch in those values and you should get a realistic result right? Wrong.

The IOR we put in the Glass shader is not the IOR of the medium (glass or fluid) itself, but really the IOR of that interface – the boundary between the two mediums (glass and air, or liquid and air). The calculation for this is mystical interface IOR is quite simple.  Air has an IOR of 1.0, since by definition refractive indices are relative to air, and the IOR of the interface is calculated by dividing the IOR of the medium being refracted (the glass) by the incident medium (the air).

So in the case of the air-glass interface, the IOR stays at 1.5 (1.5/1 = 1.5). However where the fluid and the glass touch, there is no air there, thus the interface is between glass and fluid. Assuming the fluid is water, the interface IOR would be 0.8 (1.33/1.5).

But here’s another problem: An IOR below 1.0 implies that light travels through this medium faster than it does through a vacuum. Although this would be a great way to imagine multi-coloured refractive FTL engines, it’s not possible*. However! in this case it simply means we need to invert this value (1/0.8 = 1.25), and to do so and remain physically accurate, invert the normals of the interface too.

So now you’re probably wondering which surface we should invert – the glass or the fluid? The answer: Neither. And both!


We need to stop thinking about this in terms of physical objects, the air the water and the glass, but rather as the interfaces between them. Instead of two materials, we need three: the glass, the surface of the water, and the glass-water interface.

You can join these three objects together, that’s not an issue, and even merge the connecting vertices of the glass and the interface. However you cannot merge the verts of the surface and the interface, and here’s why:


We need to invert the normals of the glass-water interface in order to get the IOR above 1, such that the normals are consistent with the normals of the glass, but inconsistent with the surface of the liquid. Merging the verts of that and the glass would cause shading artifacts since at the join the face normals would be opposite each other. But merging the glass and the surface is perfectly fine as their normals would be consistent.

Lastly, don’t forget about surface tension, so make the curve of the liquid’s surface concave:


It’s a bit of a strange thing to understand, so feel free to download and tear apart the blend.

Alternately, there is another method that seems to give similar results and is much simpler, however it does not allow you to use the Ray Length output for absorption:

surfacesThis image is from a VRay tutorial – the idea is to simply scale the liquid up so that there is a small area where the liquid and glass overlap, rather than leaving a gap between them. But since there is now a tiny bit of volume there, the Ray Length output will give us this overlapping volume instead of the whole fluid, so absorption doesn’t work. But if you don’t care about absorption, then by all means use this method instead. This duplicate geometry probably won’t have any noticeable impact on memory or speed.

And now for a little disclaimer: All of this is fairly new to me, so if you find that something I’ve said is incorrect, please correct me for the benefit of future readers and for myself. I could of course have told you about the last method first, but I think it’s good to understand the whole interface thing and not blindly using physical values such as IOR without knowledge of how they’re supposed to work.