BeeBeeQ has a fair amount of glass in it ranging from drinking glasses to windows.
The glass I see in games is usually handled in 3 ways. Most commonly it looks like it’s using an alpha blended material possibly with cubemap based reflections. Sometimes transparency is forgone entirely, simply rendering the glass as a highly reflective opaque surface. Games with a bit more graphics performance to spare might render the opaque geometry first to a texture then read that texture when rendering the glass surfaces, applying uv offsets to achieve some distortion. This is a nice effect but has a high(ish) performance cost, can only refract objects that are on screen and must be done for each camera, of which BeeBeeQ has up to 6 (Adrian Courrèges @ has written a great breakdown of Dooms implementation of this glass style).
BeeBeeQ is a VR game so we want to hit a constant 90fps to prevent any sickness, all glass surfaces in BeeBeeQ can be seen by the VR player and the bee’s cameras and the user can pick up glass objects to closely inspect them, it’s got to look good.
Using box projected refraction seemed like a good way to leverage Unity’s built-in Reflection Probe system, where each renderer is automatically supplied with a cubemap representation of their local environment and optionally parameters for proxy geometry box and a 2nd probe for blending, this is used to look up a reflection text from the cubemap based on the view direction vector reflected on the models normal. All that’s needed for this is to pass a world space position, a world space direction and a value for roughness, and having implemented it I think the result adds an extra level of interest that I like.
Unlike the previous post here I’m not really aiming for physically based realism, just something that looks glassy, here’s the code I used, this is worked into the vr_standard shader from Valve’s The Lab Renderer on the Asset Store but the variable names are easy to understand and the math is universal.
Custom Refraction Probes
Just to extend it a bit I added a variant with which I could pass my own cubemap and box parameters rather than Unity’s built in ones, this allows objects to refract a different probe to the one they reflect, in the image below the window is rendered as opaque geometry reflecting the garden while refracting a cubemap generated from the kitchen level, so we don’t have to load any of the kitchen geometry to have the environments feel connected.
Taking it further
I’m happy with the solution for now but there are plenty of cases where it couldn’t hurt to take it a bit further. Rather than using uniforms for the parameters a texture could be used, particularly in the case of the wine glass above the rays entering the stem and the rim of the glass would exit in a very different way to the bowl, the bowl would have a _PA_NormalInfluence value of zero since the inside and outside of the bowl glass act like shell, while the stem and rim could have a _PA_NormalInfluence value of 1 to make them feel like solid glass. The _PA_Thickness value could also be baked into a texture to get a bit more accuracy and variation. While these are both not hard to implement, generating the assets (particularly a texture for _PA_NormalInfluence) could be tricky and would add yet another texture to lookup and keep in memory