Shader node reflection model setup inaccuracy?
There are numerous correct ways to make a glossy black surface, and an infinite number of incorrect ones. (Your odds of picking a correct one at random are near zero).
Here's one way. This is how a perfectly smooth glossy (glassy) surface appears in a furnace.
Here is one of many correct ways to make a glossy surface with idealized Lambertian diffuse reflectance, with rgb 128, 20, 20 as the diffuse color.
The appearance in a furnace is correct. But we don't often experience furnaces so it looks funky.
Just to preserve our belief in the shader, I changed the EnvSphere to use a nice HDRI and the render looks very plausible.
Before we get into studying parameters and node arrangements, it will be useful to have a way to do two different setups in the same prop.
Rotate your Ball using yRotate = 90 degrees.
Now let's make a procedural mask for the ball that will give us black (0) for the left half, and white (1) for the right half.
It should look like this.
Now we can use that 0/1 mask to give us a "control" sample and an experimental sample.
Here I used it plugged in to a Reflect node Softness parameter. So, on the left, our known "control" is still as rendered earlier, with Softness 0. The left half is still completely white as we expect.
The right half is something else though! The right half has Softness .5 because whatever you plug in is multiplied with the value, so .5 times 1 is .5.
Interestingly the ball is not white. In fact, it's not even uniform. The center is darker than the edge.
Change the experimental value to 1 and the difference is even more striking.
I measure around 150 in the center, and 192 near the edge.
I cannot explain this behavior. I presume it means that the legacy Reflect node, when running in SuperFly, is actually using one of the micro-facet reflection models, and not the simple direct sampling we're used to from FireFly.
A quick test with the HDRI shows a surface that appears very much like a diffuse reflection.
Except it's not the same. No model of diffuse reflection gets brighter at the edges - quite the opposite.
Here is a setup with a Diffuse node (rgb 150 150 150) on the left side and the Reflect node with Softness = 1 on the right side.
Observe how at the center they're very similar, but approaching the edge they differ significantly.
So we've demonstrated that with the legacy Reflect node, there is some micro-facet model in play. Could we guess that the Reflect node is actually now a "synonym" for the GlossyBsdf node in a particular setup?
Let's try it and see.
I guessed that the equivalent would be GlossyBsdf with Color white and Distribution GGX.
Looks like a match to me.
But let's try a different Distribution just to be sure.
Well - clearly it's not even slightly matching the Beckmann distribution.
I will leave it to you to experiment with other Distributions and other settings for Roughness. I tried a few and nothing was even close. I'm pretty convinced that the Reflect node is synonymous with the GlossyBsdf set to GGX.
Let's test the first two of the original posted shaders, using the furnace.
Note that because I want both setups in the same shader, I had to make a small change to replicate the first shader. Instead of plugging the diffuse into Alternate_Diffuse and the ks_microfacet into the Alternate_Specular, I did the equivalent combination using an AddClosure. I can assure you the math is the same.
The two shaders produce different responses and it is (to me anyway) obvious why this is so.
The first (top) setup let's the diffuse node run free without modulation, and modulates the ks_microfacet reflectance using the idealized Fresnel equation.
The second arrangement (bottom) uses the fresnel factors to modulate BOTH.
In terms of math, letting S denote the specular node, D the diffuse node, and F the Fresnel coefficient for reflection, we can describe the first and second like this:
First: D + FS
Second: (1-F)D + FS
See the difference? It is no surprise that the outcome differs.
As further evidence of the math, I make a small addition to the first (top) shader wherein I use the complement of the Fresnel reflection coefficient to modulate the Diffuse node.
And now, the two arrangments produce exactly the same result.
So it should be clear that the two shaders truly are now "basically the same", and they DO produce the same results.
Now up top I changed to noobalien's 3rd arrangment. This is basically the same and the image shows this.
However, and this is a very interesting point, these arrangements do differ in parameterization. The 3rd (top) arrangement offers a unique opportunity to manipulate the shader in certain ways that matter towards producing a more physically accurate shader, given that the surface is not ideally smooth, but instead has roughness.
The simpler (bottom) arrangement does not let us adjust the Fresnel equation to compensate for roughness! And that is why the 3rd (top) arrangement is "better".
This is a common theme in my shaders and a common complaint by other users who perceive my shaders as overly complicated. The complication is NECESSARY to implement variations. When you look at a particular set of values (such as roughness = 0), then it is possible to remove some nodes.
But to allow for the other billion roughness values, AND maintain physical accuracy, the four-node setup is far more flexible than the three-node setup, even though they appear to be the same.
They're only the same because they're unfinished. They are both equally WRONG at the moment, but one is easier to correct than the other.
However, we have a serious problem.
Nobody appears to know what is physically correct here.
As you noted, noobalien,
Supposedly, the roughness value should correlate to the interval between the fresnel black & white colours with grey values instead, but I can't find such reflection percentages anywhere.
Indeed. I can't find any published rules for this either. We have only a series of ever-better "plausible" theories and implementations, as well as numerous parameterizations that more or less do what artists expect them to.
I can tell you what I've used in the past, but I can also point to regimes where my roughness compensator would fall over.
But it isn't just me. I recently read a paper from Disney where they explained the latest "principled" shader and why it's better, but they still showed an impossible outcome in the furnace from what is widely considered the best shader to use by far.
This is pretty much what I used to manage the Fresnel effect for rough surfaces.
I add one more blender and I blend the Fresnel with a constant rgb 64 64 64, according to how rough the surface is.
This reduces the edge reflectance to be closer to the center reflectance.
But when the IOR changes, then the gray value has to change some more. When I want the gray to automatically track the IOR, I can actually use an equation from a few more nodes.
Here it is with no (black) diffuse in the furnace, with right-side roughness at .2
Here with roughness .5 and with the HDRI environment.
There is still some Fresnel effect, but much reduced.
Is it physically accurate? No, or at least I can't prove it. But it works well.
Here it is with red diffuse.
Note in the past I have referred to this pattern as "rough surface fresnel". I used it to make very realistic skin even in FireFly, but it was very expensive to calculate.
It found its way into EZSkin and I believe the checkbox is "Rough surface Fresnel".
One more render and then I'm going to bed.
This is using the above shader, roughness = .1 on the left, and .2 on the right.
When I got up and looked at this I realized I made a mistake in parameterization. Looking at that image I was bothered by the still-very-high amount of fresnel edge reflection with that much blur.
I forgot to add the squaring term I use on roughness and so does Disney. Without it the fresnel and blur don't go together, and the roughness number is too powerful and hard to use.
With the roughness squaring term, a test render with .1 and .3 roughness looks like this
I just woke up and intended to do .1 and .2 but that is .3. Need more coffee.
Here is .1 and .2.
I set up a comparison render here with my mat pawns. They are configured to be invisible to raytracing so the reflections are a little bit strange as they do not reflect each other, or even themselves.
Top row is using the shader above, bottom row is using Ghostship's excellent Uber 3 shader. Both are at IOR 1.45, with diffuse color 128, 20, 20.
Left to right you have roughness going from 0 to .1, .2, .3, .4, .5, .6, .7, .8, .9, and finally 1.0.
While the two shaders are clearly behaving similarly, the exact amount of rough surface fresnel reduction is slightly different. Looking this over, I judge that Ghostship's is more realistic. But I'm not basing that on anything other than looking at the top row and judging that the edge reflection looks just a little too hot in mine. I don't know the real rough surface Fresnel formula.
Same comparison, but in the furnace, with diffuse set to black. In this image you can very clearly see the behavior change for the rougher materials.