Glass surfaces are treated as opaque by shadow rays

Over the course of using the Cycles engine, I’ve constantly come across a major yet highly obvious issue. I’m not even sure if this is a bug per say, but I see no reason why it would be intentional so I’d have to assume it’s a problem that deserves discussion.

Neither GlassBSDF nor PrincipledBSDF (with transmission) count as transparent surfaces to shadow rays. This results in glass surfaces casting shadows like fully opaque objects, even when the render option for transparent shadows is enabled. In my opinion this radically compromises realism by default and is an incorrect behavior of light rays.

Thankfully a simple workaround is possible: You can pipe shadow rays into a TransparentBSDF shader using a multiplier, which can be adjusted to match the strength of the shadow to the density of the glass. While this fixes the problem and offers the desired functionality, it still requires user intervention and many artists might not even be aware that it’s needed and Cycles doesn’t do it automatically.

Here’s a render demonstrating this, as well as the node setup I used, with blend file included. All of the balls have the same shader and transmission value and roughness and opacity, only the multiplier for redirecting the shadow rays differs. As you can see, the rightmost ball has a dark shadow whereas the leftmost one has no shadow at all. I believe that by default, Blender should automatically estimate the shadow strength based on the settings of the material and achieve a similar result on its own.



shadows.blend (872 KB)

5 Likes

The only shader that is considered Transparent is the Transparent BSDF. Things like Glass and Principled are considered as Transmission. Light rays that are refracted by such shaders are considered Transmission Rays.

Glass - even perfectly clear glass - will cast shadows because it’s refracting light in other directions. Where those refractions are focused will be brighter and the other areas will be darker. There’s give and there’s take. If you have a bright focal point and no shadows, you’ve essentially generated light out of nowhere.

Those are interesting points. That underlies other issues of realism, which would indeed be the case now that I think about it. At the same time, the problem I presented is also a huge realism problem, and one that’s more visible to the naked eye. This may thus be about choosing the lesser evil, at least until a more advanced ray-tracing mechanism can be developed.

Indeed all glass casts shadows: Even the purest glass should do that, over factors like roughness or refraction. The problem here is the opacity of this shadow being incorrect. The shadow is always 100% in strength, acting the same way if an object is made out of glass or solid brick. There needs to be a way for Blender to at least estimate the effect of transparent shadows cast by glass, so its intensity can match what is expected in real life. Are there no easy calculations that can achieve this?

Turn on caustics and prepare for a long wait. There is your “easy” calculations :stuck_out_tongue:

I never deal with glass “objects” much, it’s mostly glass panes and windows where I don’t bother consider shadows - even the edge would usually be hidden from view (i.e. by a window frame). The below is not remotely accurate, but is probably how I would start faking it - only caustics can do the real thing - and my boss can’t wait for that :smiley:



With IOR 1 there will only be the glass color casting a shadow, as IOR increases the shadow area thickens and the focus point will get smaller and intensify. This is just eyeballing something, there is no real math or science going on. It doesn’t account for much, and obviously it doesn’t at all deal properly with total internal reflection or glass roughness. Also I’m using the standard glass shader for once (I never use that, but for other reasons).

Edit: I only tested it on a simple sphere, it might break completely if tested on a hollow/shelled sphere or something real like a wineglass - at which point I’d probably cave in and make a ceramic glass instead :smiley:

I already have both caustics and transparent shadows enabled: They don’t fix the excessively strong shadows. It does cause the mesh to correctly focus the light in one point, but the shadows around it are still too dark. This can be seen in the render in my first post.

That node setup looks more complicated than the solution I was looking at, though if it provides a more realistic solution I’m all for it. My point was that the user needs special material nodes to trick Cycles into respecting glass shadows.

1 Like

Its important to remember that when items are near diffuse objects in your scene, those diffuse objects act like light sources. If the item is placed near other objects the indirect light helps soften the shadow. Here is an example scene I’ve made. shadow.blend (596 KB)



No you don’t, you need special nodes to trick it into making vaguely-correct looking shadows that render much faster than the actual correct shadows it renders by default. :wink: Glass does not pass any light through in a straight line, thus it is never correct to trace shadow rays through it. Solving the caustic is the only way to get a physically correct result. In your example post, the leftmost sphere is the physically correct one, regardless of if your intuition tells you otherwise. (remember most glass objects you’re used to seeing are thin, unlike a solid glass ball!).

If you don’t want to wait around for that, use the transparency hacks.

EDIT: all this isn’t to say a transparent shadow option built-into the shader wouldn’t be nice. Honestly, I’d use it the majority of the time if there was one. But the current behavior is the physically correct one, glass blocking shadow rays is 100% intentional, it’s not a bug.

I’m guessing here, but won’t some rays entering a glass sphere go into total internal reflection and cause shadows no matter what? And others being affected by fresnel probability and cause shadows no matter what (because they bounce off instead of enter)? Try with some real glass spheres or marbles in a dim room and a flashlight and check what actually happens.

I don’t know, but I assume there will be shadows you can’t avoid, more so along the rim.

I wish I had a real glass sphere to see exactly how much of a shadow it casts. I’ve only noticed that when I put my glasses on the table in front of a strong light, the lenses do cast more of a shadow than I would expect for transparent glass. Of course that isn’t the case for windows, otherwise it would be pitch black in our homes during daytime… that’s the sort of thing Cycles has a serious issue accounting for properly.

Yeah, the issue with windows is that the glass is so thin it doesn’t noticeably refract in most situations. So while tracing shadow rays through it is technically wrong, the result ends up looking more correct. Some renderers have a built in “architectural glass” shader which is just transparency and reflections, no refractions. You can duplicate this in Cycles by using a fresnel node to blend between glossy and transparent shaders:


This probably could be a checkbox on the Glass BSDF…

For IOR 1.5, the setup above would give backfacing IOR 0.5 (1.5 - 1 = 0.5). I think the correct would be backfacing IOR 0.6667 (1 / 1.5 = 0.6667). So basically, backfacing to choose (color mix node) between IOR and 1/IOR, fed into a fresnel. At least that’s the setup I’m using in my own architectural glass materials. Let me know if I’m wrong.

Also, “your glasses” are probably made of highly-refractive plastic – at least my Coke-bottles are. Go to a craft store and buy an actual glass sphere. (Or be a cheap-skate and just look at it in the store.)

when talking about window glass, remember that exposure plays a big role in how brightness is perceived. open your window and take off the screen. you will see just how dark glass is.

i have a window that the sun shines straight through, you can see the shadow darken as the glass swings open.

EDIT:
WARNING: removing the screen from an open window is dangerous. use caution! most screens are not designed to fully prevent falling out a window.:eek:

Damn it! I have a sliding door :slight_smile: But yeah, I would expect it too. Not only because rays has to travel through more (slightly absorbtant) material, but also because as the door opens, the rays faces more and more grazing angles and will tend to reflect more than enter the glass (and hence cause a darker shadow).

This IS a problem. It don’t give transparent shadows even with IOR of 1, that has no refraction. (They a bit transparent if they VERY close to the surface.)

What i have notices is that Beckmann and Multiscatter GGX have this problem, while Sharp and GGX do not. Try switching. ( Don’t seem to work in every version?..)

I still consider this one of the biggest limitations in Cycles at the moment, including for the PrincipledBSDF shader which is meant to be physically accurate: If you create glass you must still manually mix Principled with a Transparent shader using “Is Shadow Ray” as the factor, otherwise you get shadows which clearly make no sense.

Caustics do little to solve this: They do add some additional light which passes through the glass, but in most cases still allow perfectly transparent glass to cast shadows that shouldn’t be there.

A solution would seem having the engine do this automatically based on the value of the Transmission parameter. However I assume that’s not the most physically accurate solution.

1 Like

This is by all means a caustics issue. Using caustics is the most accurate, but it relies on ridiculous amounts of samples. The Transparent shader with isShadow ray isn’t a great hack, as there are no trace of fresnel in the shadows. I use 1-(Layer Weight/Facing → Power 5 → Add 0.05) to control the color of the shadow. The math is very close to real fresnel for IOR 1.55 glass, and I don’t have to worry about backfacing faces for the simple one sided sheet glass I use. It doesn’t look good for thick glass, but for windows I can live with just doubling the effect to account for energy lost to internal reflections. But, I always use single sided anyways. It’s a hack, it’s a decent hack for it’s purpose, but it’s still a hack and not realistic compared to high sample count caustics. May need to employ some other tricks for the edges as well on solid (but flat) glass, but normally for me these are hidden so not something I have to worry about.

1 Like

When it comes to thicker glass objects, like say a glass statue, the current behavior can be acceptable; The glass is still casting too many shadows but you can say it’s dense so that makes sense.

The main problem is that even a thin glass panel that’s part of a window will cause little light to come through. I’m sure people who do architecture can confirm this: Make a hole in the wall for your window and exterior lighting comes in just fine… put in the glass plane for that window however, suddenly the room gets surprisingly dark. In real life the glass of a common window will barely cast a visible shadow at all, you need to look carefully to even tell it’s there.

Of course I could only test with a reasonable number of samples: You can still barely go over 1000 without the render taking hours on end, and even then you need a denoiser for good results. I am curious now if at a hypothetical one million samples the result would be different… if someone has access to NASA’s computers they can probably test that :slight_smile:

A glass statue with varying thickness is a completely different beast compared to a glass window. Here is the setup I’m using, on a single flat plane completely avoiding the refraction/glass shader (no portal used, and internal lights would be reflected in it for night shots):


On the left preview - Pure standalone transparency.
On the right render - Fake fresnel doing some darkening at glancing angles.
Even with the sunlight at this extreme angle, it still lets through sunlight, but it is visibly darker. At more normal angles, this difference becomes less. Glass is also fully white here, normally I’d use something like 0.8-0.9. Note that the “fake fresnel effect” is doubled. Normal glass has a thickness, so entry interface and exit interface, where the inside interfaces can “trap” light in total internal reflections, meaning less transparency. So real glass would likely become even less transparent at glancing angles than what I’m doing here despite exaggerating. Also I’m not bothering with multiple diminished reflections through multiple solids of glass like would be the case in a modern window. Nobody notices nor cares about this level of realism.

Here is the difference between real fresnel and fake fresnel simulating IOR of 1.55, about average for glass:


Real fresnel on the left, fake fresnel on the right. Can you even see the difference? I’m using standard view transform to see the raw data better. If you want real fresnel for something like this, you’ll have to do a 1/IOR for backfacing faces to achieve similar results. If not, the backface will show up as Snell’s window.

This seems to be a lot more accurate than what I remember from last time I tested. Perhaps the caustics algorithm has been improved since, or only certain glass meshes cause excessive shadows? Or you might simply need a whole lot of samples for the result to be fully correct.