So I've seen a lot of posts regarding physically based rendering around lately, and one of the things I commonly see discussed is "metalness" and how to use it appropriately. Firstly I'd like to preface this post with my own personal opinion. I do not like the metallic workflow, I believe that there are too many semantics associated with a word that ends in "ness" and I find that it is fairly difficult to teach it's intended use. I'd also like to preface this post with an understanding that I am not an academic graphics programmer, I did not come up with these concepts and there may be flaws in this post. I would hope that this sparks a discussion.
That being said lets jump in.
Metalness is a rendering optimization. Full stop. There is no real life property "metalness." The metallic workflow is intended to be more intuitive for artists to use. It also allows us to "pack" a mask into a pass in the renderer enabling us to effectively drop the need of a full RGB pass for specularity.
In order to understand what a "metallic value" is first we have to understand why it exists. We can fairly easily split up real life materials into two categories, dielectric materials (substances that are insulators) and non dielectric materials (those that conduct electricity). Effectively this separate materials into metallic and non metallic categories.
Here's where we start to make assumptions. The index of refraction (in simple terms reflectivity) of dielectric materials tends to be around 1.33 - 2.0, this is about a 15% variance. But when you look at that in terms of an 8 bit sRGB texture (0-255) that's not a lot of value change. Therefore we can make a fair assumption that most dielectrics can be represented by a sRGB value of 56 out of 255, or a linear value of 4%. (That magic number everyone talks about.) With that assumption we can typically optimize out of the equation - for dielectrics - the need for a texture map to define that value.
We also know that most non-dielectric materials, occupy the sRGB range of 155-255. Thats a fair amount of space that can also have RGB (color) values, so we know we need a more precise value (maybe a texture map). We now make another assumption, most perfect metals have a nominal diffuse value, so we can optimize that out of the equation as well using a value of 0 for metallic diffuse.
What do those optimizations mean? Well okay, we know we can remove the need for a diffuse value for metals and use our non metallics space on the albedo texture for specularity. We can also remove the need for a texture map to define non metallic reflectance. But, we need a way to define the interpolation between what is going to use full RGB specularity for metals and what is going to use that magic 4% reflectance for non metals.
So now enters the "metallic map." We use this texture, which is stored in a multi use GBuffer with one channel, as a per pixel interpolator to inform the shader where to make those optimizations.
_________________________________________________________________________ So Chris? why can't we use this as a greyscale value shouldn't we use all the tools we have available to use? Yes. That's fine to do if your studio/project/TA allows it. But keep in mind you are using the renderer in an unintended way.
Why is that "bad?" Well, the purpose of PBR is to have more consistent and predictable results using real life as a reference. By adjusting this value to be outside the typical range (greyscale) you create an predictably unpredictable result.
Can you explain that to me? Yes I can try. The shader is purely making a linear interpolation between A and B based on C. The result of which is being what is fed to the lighting calculation.
C represents our metallic variable, A represents our Albedo and B represents our Specularity on our base color texture map. This allows us to use the same texture as two inputs using an interpolator value. If we use C as a binary value its effectively just a switch in the shader between areas that use the base color map as Albedo and areas that use the base color map as Specularity. If we use C as a greyscale value we end up with a non exclusive mix between the two. (I explain the math in images below)
When you use a grey value for metallness you end up mixing the GBuffers together. No longer is your base color map used explicitly for specular or explicitly for albedo. You end up mathematically using the same texture to define two values, both of which do not represent what the actual texture looks like.
So why does that actually matter? Well first, you are not representing the final value that reaches the lighting calculation in any texture or explicit value, you've mixed them together with no idea what the actual value that's being fed to the renderer is. Next there is an excellent possibility that you are feeding the renderer non plausible reflectance values between 56 and 155 in sRGB resulting in "frosty" looking materials. Where the ratio of diffuse light to specular light is non plausible. Can I get some pictures? Yes. I have tried to recreate this problem in Substance designer where I have recreated the math behind the Metallic Workflow optimizations using a Spec/Gloss material.
Here is a standard non metallic material. It has an albedo value of 255 and a specularity of 4% reflectivity.
Here is the same set of values using full metallic. The material now uses a spec value of 255 and a base color of 0 or black.
What happens when I use the same set of values but a metallic value of 50%?
So if you take a look at the base color and specularity these do not represent my input textures or values any longer. In fact if I was expecting to get middle grey in the specularity but it's actually a value of 33%. (The actual math behind this is a linear interpolation between 56 and 255 using an x value of 127 which results in a value 155. That is then converted to linear space for a value of 0.3278).
This is what I was referring to as predictably unpredictable, I do not know what explicitly is being fed to the renderer as it is not coming from a texture map or a value that I set.
So finally I discussed above having values that were out of range of physical specular values. So I've put together a black and white gradient that I will use to illustrate my point. I've also set up a pixel validator that will turn red when it detects specular values that are out of range.
That's a lot of red. Those areas will not produce expected lighting results as you've created a diffuse/specular value that isn't grounded in any informed way.
I see some areas that are not red does that mean I can use some of the metalness value? Not really no, this illustrates only the inaccurate values for this particular material in other materials it may be less, it may be more. Chris, what does this all even mean? Well, this is the way that I personally explain to artists why using greyscale metallic values results in unexpected results and I encourage them to find the right look within the parameters. PBR is about having a consistent look.