If you want to make something invisible to a certain ray type in Blender/Cycles, most people do things like this:
STOP DOING THAT.
You are making Cycles waste time doing worthless calculations. Instead, go over to the object tab, and use these instead:
Unchecking “camera” there will produce the exact same result (the object is invisible when viewed directly, but otherwise appears normally), but it goes about it differently. The shader node setup tells Cycles when evaluating the material, figure out the current ray type, and if it’s camera, choose the second input on the mix shader. This is a transparent BSDF node at full white, so the ray passes unchanged.
Ray vis does it a much more efficient way: it just tells Cycles “if the current ray is a camera ray, don’t even bother checking if you hit this object, just assume you didn’t”. This is important, as it allows us to filter out the object while doing intersection tests (render nerd speak for “checking to see what the ray hit”). Even better, it allows us to avoid running the shader at all, much less realizing the result was a transparent BSDF and having to continue the path and do the whole thing over on the next object we hit.
It gets worse though. The light path shader includes a transparent BSDF, thus, it enables transparent shadows. Realtime engines and rasterizers have taught too many people to think alpha maps are their friends. But raytracers are different: to them alpha maps are evil, because they create a horrible effect called transparent shadows. Raytrace shadows are computed by tracing a path from the shading point (that’s where the initial ray landed) out to a lamp, and seeing if anything blocks the path. If something is there, the object is “in shadow” and the lamp contributes nothing. If it has a clear shot, it is not in shadow, and the lamp contributes at full strength. Simple.
Transparent shadows crap all over that simplicity. They cause the shadow ray test to return bullshit like “the ray might be blocked, or maybe it isn’t”. The only way to find out is to to run the shader (which we didn’t even have to do in the first place for opaque shadows!) and figure out what the actual opacity is at the point on the object we hit, then trace another ray from this point to see if we were actually blocked entirely by something else and we did all this for nothing (lolz). God help you if that “something else” is also transparent, then we have to do this shit all over again.
Needless to say, that wastes a lot of time. And now you know why that “transparent shadows” box is in the material options. Unchecking that tells Cycles “I know this mat has a transparent BSDF, but just ignore that and do opaque shadows anyway”. Because that can save a lot of time if no one is going to notice an object is casting solid shadows.
Now, sometimes we don’t have a choice, (alpha maps have their uses), but in the case of 100% transparency to a particular ray type, we do. We can just turn off ray visibility for that type, and have a simple shader with no transparency.
Just to compare, I set up this scene. The cube is invisible to camera rays:
Regardless of if we use ray visibility or the light-path shader, the result is the same. But the render times aren’t:
- Diffuse-only shader, camera ray visibility disabled: 1.73sec
- Diffuse/transparent mix by “is camera ray”, camera ray visibility enabled: 2.28sec
- Diffuse/transparent mix by “is camera ray”, camera ray visibility enabled, but “transparent shadows” disabled: 2.10sec
This is obviously a worst-case scenario, but you can see the impact of the extra calculations. 30% longer to render the exact same image! Using the same setup with transparent shadows disabled (still the same result, because light path “is camera ray” will never evaluate to 1 for a shadow ray) is only 2.1 sec. That’s means about 35% of that penalty wasn’t even due to our extra shader stuff, it was due to the useless enabling of transparent shadows.
So there we have it. Ray visibility is your friend.
“But wait!” you might be saying, “I need to do some ray-switching for a bunch of objects with this one material! Light path is a lot easier in this case!”
Python to the rescue. This will disable camera visibility on all selected objects (select one object, then use “select > linked > material” to grab all objects with your mat):
import bpy for obj in bpy.context.selected_objects: bpy.context.scene.objects.active = obj bpy.context.object.cycles_visibility.camera = False
If you need to flip a different ray visibility switch, you can just change that last line. This version will turn on transmission visibility:
import bpy for obj in bpy.context.selected_objects: bpy.context.scene.objects.active = obj bpy.context.object.cycles_visibility.transmission = True
The python names for the 6 switches are: