Followers 0

# where to start Physical based shading ?

## 42 posts in this topic

Where can I start learning how to shade my objects through physical based approach ? I feel lost when it comes to formulas in papers . I couldn't find any sample that does the job clearly .

2

##### Share on other sites

http://content.gpwiki.org/D3DBook:%28Lighting%29_Cook-Torrance

This is interesting! I've been looking a bit at that Cook-Torrance link, but from what I understand physical based shading is supposed to be "normalized", e.g. the amount of light reflected is less than or equal the amount of incoming light. Is the BRDF described there really normalized?

I've been thinking about how much space physical based shading requires in my G-buffer. I currently use 2 16-bit values (in addition to 3 for diffuse RGB and 2 for a packed normal); glossiness and specular intensity. According to this link, physical based shading seems to require diffuse RGB, specular RGB and a gloss value, which if specular is kept as grayscale would result in the same values that I need. Cook-Torrance on the other hand seems to work on some kind of roughness value instead and possibly some other term (something related to some incident angle?).

Frankly I'm not too interested in the math behind all this, but it'd still be really interesting to implement and see the results, and I need to understand it to some extent to be able to explain how to work with the lighting to our artists...

0

##### Share on other sites

Roughness and glossiness is usually just same term. Glossiness is just calculated with some formula from smoothness which is 1- roughness. In our material pipeline we always talk about roughness but actually artists author smoothness map instead. Usual optimization is to store just spec intensity and calculate spec color from albedo if specular intensity is higher than x.(0.2 is good choise).

1

##### Share on other sites

If you only store a monochromatic specular value you will not be able to render materials like gold or copper. Since the specular value is generally constant for a particular material, you could instead store a material id in your gbuffer and use it to look up the RGB specular value from a constant buffer.

0

##### Share on other sites

If you only store a monochromatic specular value you will not be able to render materials like gold or copper. Since the specular value is generally constant for a particular material, you could instead store a material id in your gbuffer and use it to look up the RGB specular value from a constant buffer.

Copper and gold does not pose problem because metals don't have albedo so spec color can be stored there but Gem stones and other rare materials  on other hand can cause a problems.

I solved this problem just making a rule that only metals can have colored specularity in our engine and material is concidered as metal if specular intensity is over 0.5. Basically metals have pure white intensity and only albedo channels are used for authoring but used as specular color in shader.

0

##### Share on other sites

Roughness and glossiness is usually just same term. Glossiness is just calculated with some formula from smoothness which is 1- roughness. In our material pipeline we always talk about roughness but actually artists author smoothness map instead. Usual optimization is to store just spec intensity and calculate spec color from albedo if specular intensity is higher than x.(0.2 is good choise).

I Just want to clear this up, roughness and glossiness isn't the same thing.

The reason people believe them to be the same is one part lazy work and a other part, different development apps not agreeing on a standard.

So Specular works with different maps:

intensity: This is how bright the specular is from 0-1 or 0-255, is referred to as a Specular map or intensity map, gloss map, Specular grey scale map, shininess map.

Size : This is the size of the specular spot and it ranges from 0-512 normally or 0-1, is referred to as a gloss mapshininess map, hardnnes map, Specular size map.

Color: This changes the color of a specular spot and is mainly used for gold and special paints, is referred to as a Specular color map.

Usually materials that sharply reflect light will also reflect a large amount of light ,like plastic, so specular map will be bright and the gloss map dark, this is why inverting still gives acceptable results quickly.

Polished metal and car paints reflect small sharp points of light and will have a bright specular map and a bright gloss map.

Small game engines like Unity only use reflection for metals and other highly reflective materials, meaning that thy only need to use the Specular map.

Other low reflective materials,like wood or cement, use a simple diffuse shader.

Large game engines like Unreal use all three specular maps, allowing artist to clearly show where the polished metal armour separates from the battle worn chain mail and even where a gold bracelet hangs from the hand.

-1

##### Share on other sites

Roughness and glossiness is usually just same term. Glossiness is just calculated with some formula from smoothness which is 1- roughness. In our material pipeline we always talk about roughness but actually artists author smoothness map instead. Usual optimization is to store just spec intensity and calculate spec color from albedo if specular intensity is higher than x.(0.2 is good choise).

I Just want to clear this up, roughness and glossiness isn't the same thing.

The reason people believe them to be the same is one part lazy work and a other part, different development apps not agreeing on a standard.

So Specular works with different maps:

intensity: This is how bright the specular is from 0-1 or 0-255, is referred to as a Specular map or intensity map, gloss map, Specular grey scale map, shininess map.

Size : This is the size of the specular spot and it ranges from 0-512 normally or 0-1, is referred to as a gloss mapshininess map, hardnnes map, Specular size map.

Color: This changes the color of a specular spot and is mainly used for gold and special paints, is referred to as a Specular color map.

Usually materials that sharply reflect light will also reflect a large amount of light ,like plastic, so specular map will be bright and the gloss map dark, this is why inverting still gives acceptable results quickly.

Polished metal and car paints reflect small sharp points of light and will have a bright specular map and a bright gloss map.

Small game engines like Unity only use reflection for metals and other highly reflective materials, meaning that thy only need to use the Specular map.

Other low reflective materials,like wood or cement, use a simple diffuse shader.

Large game engines like Unreal use all three specular maps, allowing artist to clearly show where the polished metal armour separates from the battle worn chain mail and even where a gold bracelet hangs from the hand.

Wikipedia and every physical based rendering source material contradict what you are saying. http://en.wikipedia.org/wiki/Gloss_(optics)#Surface_roughness

0

##### Share on other sites

http://content.gpwiki.org/D3DBook:(Lighting)_Cook-Torrance

This is interesting! I've been looking a bit at that Cook-Torrance link, but from what I understand physical based shading is supposed to be "normalized", e.g. the amount of light reflected is less than or equal the amount of incoming light. Is the BRDF described there really normalized?

To the best of my knowledge, the formula described in that book is normalized. Not all of the other BRDFs in that book are normalized though.
Note though, that the Cook Torrance code later adds the diffuse component "as is", but you need in fact to normalize that sum. A common cheap trick is to use the opposite of the fresnel argument F0:"NdotL * (cSpecular * Rs + cDiffuse * (1-f0))"

Frankly I'm not too interested in the math behind all this, but it'd still be really interesting to implement and see the results, and I need to understand it to some extent to be able to explain how to work with the lighting to our artists...

I'm afraid PBS is all about the math (tech, what you're focusing on), and feeding it with realistic values (the art).
You asked whether the Cook-T. formula was normalized, but in fact we can't know by just looking at it (unless we already know of course).
To truly check if it's normalized, you have to calculate the integral; like in this website, and like in this draft. Either that, or write a monte carlo simulation.

Either of them takes more than just 2 minutes to find out (and for some formulas it can actually be very hard even for experienced mathematicians).

Edit: Fabian Giesen's site seems to be down. I've re uploaded his PDF here.

Edited by Matias Goldberg
2

##### Share on other sites

Wikipedia and every physical based rendering source material contradict what you are saying. http://en.wikipedia.org/wiki/Gloss_(optics)#Surface_roughness

These two wiki pages refer to real world conditions, not the techniques use by real time rendering.

Specualar maps, Gloss maps and Specualar color maps, are nothing but tricks to fool the viewer.

If you would like to make shaders that can cast real specular reflections and gloss optics you will need to use ray tracing.

Even though ray tracing is now entering a era where it can be used in games it will still take time before we can bounce the huge amount of rays needed, over a surface and back at the viewer that is needed for gloss, although I am proud to say that specular is now possible even if it isn't practical.

This better explains real time specular, even if it is a bit dated: http://en.wikipedia.org/wiki/Specular_highlight

Here is a guide for materials from the artists view point: https://www.marmoset.co/toolbag/learn/materials (Good read)

I have worked for five years as a cg artist, by rule of thumb the maps are:

Specular map. intensity

Gloss map. Size (yes it should be roughness but it really only scales the specular size of the spot over the normals)

Specular color map. Color

But these names changes from software to software, so it helps to know what each does.

If any one would like to see how these maps work, you can just download a 3d modeling app and test them your self or you could just search for "How do specular and gloss maps work."

-1

##### Share on other sites

Let me see if I have understood this correctly. To implement Cook-Torrance I need to:

1. Modify my G-buffer to store specular intensity (AKA ref_at_norm_incidence in the article) and a roughness value.

2. Normalize the function by multiplying the diffuse term by (1 - (specular intensity AKA ref_at_norm_incidence)).

3. Bathe in the glory of physical based shading.

My bet is that this is 100x easier to tweak to realistic results compared to my current lighting.

Edited by theagentd
1

##### Share on other sites

Sorry to double post, but a simple "yes" or "no" is all I need... ._.

0

##### Share on other sites

Yes.

Though even Phong or Blinn-phong (the typical specular formulas) both stored intensity and roughness values in the g-buffer too (often called spec-mask / just "specular" and spec-power / spec-exponent).

1

##### Share on other sites

But from what I've undersood the specular power is actually the inverse of roughness, since a roughness value of 0 would correspond to a very high gloss value (over 100 at least or something?). You're right that the change in the G-buffer isn't much of a change though.

0

##### Share on other sites

I was in the same situation recently, after reading a lot of paper I wanted to implement physically based shading.

I'll just add one link to the ones provided above : http://graphicrants.blogspot.ca/2013/08/specular-brdf-reference.html

There is a lot of cook torrance specular variations, I found it very helpfull.

If you want to see an actual implementation you can dive in the Unreal Engine 4 source code, you'll found those equations, and the parameters used.

Before implementing PBS in my (tiled) deferred engine I made a very simple forward viewer, to test the inputs I'll want to store on the GBuffer. If you want to look at it, you can download it here: http://www.alexandre-pestana.com/physically-based-rendering-viewer/

It's very basic, but it allows me to test textures and parameters. I didn't release the source code yet (I need to clean some import mess before), but you have access to the pixel shader, so maybe you'll find that helpfull. You can also modify the shader and dynamically recompile it by pressing "Alt Gr". But if it does not compile I think the viewer will miserably crash (I use this feature for development, with breakpoints to relaunch compilation in case of error).

As I said, I'm discovering PBS, so it may still be some mistakes in my implementation. If you found one, I would be happy to know !

I've made a new version of the viewer, where I implemented all the specular variations found in the blog post from Brian Karis, I think I'll upload it tonight or tomorrow.

1

##### Share on other sites

Thank you very much! I've converted the Cook-Torrance shader to GLSL and I believe I have it working. I'm not quite sure if the result is correct though. In my opinion the fresnel effect is way too strong. Here are my results with a specular intensity of 0.0 and a roughness value of 0.5.

Result:

Specular only:

Is this really the correct result? Despite the specular intensity being 0, I get a huge amount of specular reflection when the view angle is high. The "problematic" line is

float fresnel = specularIntensity + (1.0 - specularIntensity) * pow(1.0 - VdotH, 5.0f);


which basically causes the specular intensity to approach 1.0 when VdotH approaches 0 regardless of what the original specular intensity was. Is this really correct? It looks very different from how I am used to. For example, I attempted to reproduce these results in real life using a plain white A4 paper and a lamp, and the specular intensity was pretty much negligable. Perhaps I was just using a too low roughness value (0.5), since a roughness value of >1 produces very good "papery" result.

0

##### Share on other sites

you can change your line by this one who gives better perf for the same result :

float fresnel = specularIntensity + ( 1.0f - specularIntensity ) * exp2( (-5.55473f * VdotH - 6.98316f) * VdotH );
Edited by Alundra
0

##### Share on other sites

you can change your line by this one who gives better perf for the same result :

float fresnel = specularIntensity + ( 1.0f - specularIntensity ) * exp2( (-5.55473f * VdotH - 6.98316f) * VdotH );

Same or similar?

0

##### Share on other sites
This is the specular highlight only. The diffuse term has been removed.

float specularIntensity = 0.03;
float roughnessValue = 1;

float fresnel = specularIntensity;

float fresnel = specularIntensity + (1.0 - specularIntensity) * pow(1.0 - VdotH, 5.0f);

float fresnel = specularIntensity + (1.0f - specularIntensity) * exp2((-5.55473f * VdotH - 6.98316f) * VdotH);

Increasing roughness to 3 gives me more acceptable results, but this just looks really weird.

EDIT: The images were in incorrect order!!! >_<

0

##### Share on other sites

you can change your line by this one who gives better perf for the same result :

float fresnel = specularIntensity + ( 1.0f - specularIntensity ) * exp2( (-5.55473f * VdotH - 6.98316f) * VdotH );

Same or similar?

As you can see, same result for better perf.

0

##### Share on other sites

Thank you very much! I've converted the Cook-Torrance shader to GLSL and I believe I have it working. I'm not quite sure if the result is correct though. In my opinion the fresnel effect is way too strong. Here are my results with a specular intensity of 0.0 and a roughness value of 0.5.

Is this really the correct result? Despite the specular intensity being 0, I get a huge amount of specular reflection when the view angle is high. The "problematic" line is

float fresnel = specularIntensity + (1.0 - specularIntensity) * pow(1.0 - VdotH, 5.0f);


which basically causes the specular intensity to approach 1.0 when VdotH approaches 0 regardless of what the original specular intensity was. Is this really correct?

It is correcet, but ultimately can appear incorrect because there's other factors unaccounted for.

In your specular function you've got a few different sub-components --

D - the specular distribution (pow(NdotH, specPower), etc) this represents the statistical chance that there will be micro-surfaces perfectly aligned in such a way to allow light to be specularly reflected between the light source and viewer.

F - the Fresnel function. At glancing angles, a higher proportion of light is reflected rather than refracted. At a 90º angle, all light is reflected.

G - the geometry, or shadowing/masking function. This part deals with the fact that on rough surfaces, the surface will actually self-shadow at a microscopic level. Even though at 90º Fresnel says that 100% of the light will be reflected, a large amount of this light will actually be blocked by the microscopic bumps that are in the surface.

In a fully realistic BRDF, the G function will help to cancel out the F function, so that a rough surface does not actually appear 100% reflective at glancing angles (but a smooth surface will). So your problem is likely that your current G function is not realistic enough.

Many games deal with this with some very simple hacks, which aren't quite physically correct, but work well enough.

e.g. you can try a hack as simple as:

float fresnel = specularIntensity + (1.0 - specularIntensity) * pow(1.0 - VdotH, 5.0f) * smoothness;

This is basically just disabling Fresnel when smoothness=0, and leaving it as usual when smoothness=1.

2

##### Share on other sites

Quick question related to this: If you switch over to PBR, what is the likelihood that you'll be able to use your decade-old art assets? From back when textures weren't just albedo, and artists tweaked material settings like "diffuse color" and "ambient color" to make the model look "right"?

0

## Create an account

Register a new account