When trying to integrate CG renders into real life footage one common hurdle is to treat reflections properly. Often times in your plate you will have elements that have bright reflections (eg windows, plastic chairs, shiny tables, etc) in which your CG elements need to reflect. Rendering a simple reflection pass however often times does not really cut it
See the example below. If you were to add a usual reflection pass to it the result does not really make sense:
This is because the reflection is simply added in this case. While adding reflections is technically correct, the problem is that we already have reflections in the plate. The window behind the table has a large contribution to the specular reflection on the table. If you look at the cup on the right what is happening is that the cups reflection is blocking the highlights from the window. As the cup is neither emissive nor very bright it’s reflection is a lot darker.
We’d need to do something similar to the reflection of the CG render. A common trick is to render a separate reflection of the same element but with a constant white shader. This has several drawbacks tough:
Most renderers don’t support arbitrary utility outputs in traced results. This means the render would need to be a separate layer
–> more render layers to manage for the Lighting TD
–> longer rendering times
–> Comp has to deal with more separate renders
–> even more layers to manage if additional utility passes are requested (reflected Position, Normals, userdata, etc.)
Ideally you would have the alpha and any additional arbitrary outputs as an AOV instead of a separate render to remedy all of the drawbacks mentioned above.
I therefore wrote a simple OSL shader. This however probably only works reliably in more recent versions of Arnold. You can assign it to your set geometry and anything that will reflect in it will sample whichever shading component you specify. This supports OSL builtins (eg
N) as well as arbitrary userdata (eg
Pref). If you use
distance as a special keyword for the trace_component it will output the distance of the reflection from the current shading point, which can be used in comp to fake roughness. If the given component is not found it will reflect the
trace_color (eg to be used as an alpha for reflections).
If your set geometry contains multiple shapes you can add them to a trace set and specify that same trace set in the shader and untick
inclusive. This will allow only reflections from your anything other than the set geometry.
The shader will output rgb data which means you can pipe it into custom AOVs for example with the help of
aov_write shading nodes:
With a little bit of comp love you can get quite promising results:
You can give it a whirl by downloading the jiTraceAOVs shader from my github
Here’s a bit more indepth demo + a simple comp example:
If this post has helped you in any way you can express your gratefulness by using the Donate Button below to buy me a coffee! :)
Best explanation ever!
In my opinion, the solution should be in the shadowMatte shader itself.
In the old days of Mental Ray, the shader used to comp shadows and reflections over a backplate, had two reflection modes, either additive and substractive.
So, shadowMatte shader just do additive reflections as you said. But it should be able to do substractive reflections (effectively doing what you do in comp: substracting the object from the actual reflection and adding it afterwards).
I don’t know why they don’t add that feature to the shader, Mental Ray was able to do that many years ago, and in fact, Mr. Zap Anderson (the creator of the Mental Ray shader) was working in the Arnold team after he left Mental Images, so the technique should be the same.
great, as always. I guess I have to force my students into using this shader now.
Cheers from Leipzig.
Haha, hey Thomas! Thanks for the kind words, I’m humbled as always :)
Great explanation as always! Thank you for creating such useful VFX information big fan of your work! Happy New Year!