Jump to content

  • Log In with Google      Sign In   
  • Create Account

Questions about physically based shading

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
7 replies to this topic

#1   Members   -  Reputation: 1438


Posted 03 November 2012 - 01:00 PM

I've got a few questions that I'd love to get some insight on.

1. When using a normalized brdf how do you tweak(?) the intensity of the specular highlight. Isn't the point of this to get a result which is <= 1 ?
Which also brings up another question. Considering the normalization factor for a phong brdf: (SpecularPower + 2) / (2 * PI) and not using any geometry or fresnel term the specular would always be 'blazingly' bright (and a lot higher than 1). Also wouldn't multiplying the result with some value aka specular intensity value afterwards distort from the original idea of normalizing it ? If that's true how do you control the intensity of this specular ?

2. When trying to make a metallic looking material, how would you create the diffuse and specular map for it considering its real life behavior. You can't just use a black diffuse map and only use a specular to make the entire object lit can you ? At least it didn't work for me. Wouldn't the rest of the object be completely black (if no ambient term was there) ? Also this might be more of an artist's problem but if you'd use the fresnel reflectance color of a material F(0°) e.g. a stonewall which probably would have a very low color how would I create such a specular map without loosing detail. Because lowering the maximum brightness of this map to 0.02 (for example) makes it almost entirely black and all its details will be lost.

Edited by lipsryme, 03 November 2012 - 04:30 PM.

#2   Moderators   -  Reputation: 18019


Posted 03 November 2012 - 04:35 PM

1. The point of "normalization" with regards to a BRDF is to ensure that the energy being reflected off a surface (radiant exitance) is less than or equal to the amount of energy that's hitting the surface (irradiance). If that inequality isn't true you've violated energy conservation, and it will possible for a surface to "gain" energy. Now keep in mind that doesn't mean that the energy reflecting off the surface has to be less than or equal to the intensity of an analytical light source, which seems to what you're thinking. The radiant exitance is calclulated by integrating the exit radiance for all possible viewing directions about the hemisphere surrounding a point's surface normal. When you calculate the specular reflection for a surface in a shader, you're just calculating the radiance for one possible viewing direction. So for instance if you have a directional light of intensity 1.0 that's pointing straight at a surface, the resulting irradiance is equal to 1.0 * N dot L, which is 1.0. With a normalized specular term you will actually get values that are way higher than 1.0 for certain viewing directions, however for most viewing directions you will get a much lower values. But if it's properly normalized, you should end up with a value less than 1.0 if you were to integrate the specular result for all possible viewing directions.

If you're not familiar with this yet, I would suggest reading the relevant sections of Real-Time Rendering, 3rd edition and Physically-Based Rendering. There's Principles of Digital Image Synthesis (which is free), which has an overview of radiometry and the relevant integrals in chapter 13.

2. Real metallic surfaces don't have a "diffuse" response to light. Their response is purely specular, although it may require multiple specular lobes to properly approximate the real-world response. To render this sort of material and have it look good, you really need to include specular reflections from the entire environment and not just from analytically light sources. Otherwise it will just be black with a few highlights, which doesn't look very metallic. Typically games will use reflection probes stored as cubemaps to approximate environment reflections, perhaps pre-convolved with a kernel that's meant to approximate the specular BRDF. For low-intensity specular values, you may want to consider rescaling the texture value in your shader. So for instance if you were to multiply by 0.04, then you specular intensity of 0.02 would be represented by a texture value of 0.5 and you'd have a lot of precision available for small variations.

Edited by MJP, 03 November 2012 - 04:40 PM.

#3   Moderators   -  Reputation: 49099


Posted 03 November 2012 - 07:00 PM

1) total output must be <= total input. In most equations, 1.0 means 100% of the input energy, which may be more than "1 unit" of energy.

The specular intensity, or "specular mask" is a different physical property, unrelated to BRDF normalization - it's based on the material's Index Of Refraction, which determines what percentage of light is reflected (specular) vs refracted (diffuse). For non-metals, this value is generally always below about 0.18 (which is the value for diamond).

Keep in mind that most real-world non-metals do absorb a large amount of light energy as heat, and so emit much less than the input energy.

2) Yes, pure metals should have black albedo and very bright spec-masks (80-99%). If you put such an object in a black void with a single spotlight, it would appear black except for a small highlight. The real world has GI though, so objects are 'lit' from every angle, creating a zillion highlights all over the object. As above, a cheap way to fill out your lighting like this is to use a cube-map to store environment lighting.

As for authoring dark textures, in my engine, I multiply non-metal spec-mask values by 5, so that white = 20% spec.

#4   Members   -  Reputation: 1438


Posted 04 November 2012 - 09:19 AM

Thanks for the input. So if I understand correctly the specular will always be very faint but only strongly visible at glazing angles ? I've already implemented such a Fresnel term in my brdf which is why I was wondering because it displays a very low value in relation to my rather strong diffuse.
I'm also using a kind of "artificial" light intensity which makes this term stand out even more, am I wrong in doing so ? (I do this to produce a strong light source e.g. direct sunlight).

// Incident irradiance
float4 Ei = _LightColor * _LightIntensity;

// Lambert
float3 kd = NdotL;
Lr.rgb += (kd / PI) * Ei;

@texture value rescaling
So I would create a specular map like usual but scale this down inside the shader to match the material's fresnel color ?

Edited by lipsryme, 04 November 2012 - 12:16 PM.

#5   Moderators   -  Reputation: 18019


Posted 04 November 2012 - 06:09 PM

Well not necessarily at just grazing angles, but for whatever viewing angles that cause your specular BRDF to produce a higher intensity. If you're using a physically-based BRDF the specular should be quite bright relative to the diffuse contribution, even for materials with a low specular response at F(0). Here's a picture showing a surface with F(0) = 0.05 with a Beckmann NDF with a nearly head-on angle, and another picture showing the response at a grazing angle:



Using a light intensity should be totally fine, as long as you use the same intensity for your diffuse and your specular.

Edited by MJP, 04 November 2012 - 06:10 PM.

#6   Members   -  Reputation: 1818


Posted 04 November 2012 - 07:59 PM

For extra credit, implement energy conservation between the diffuse and specular terms by subtracting the reflectance at normal incidence (i.e. your spec mask texture) from the diffuse albedo (i.e. your diffuse texture)

This is not the same as removing the calculated specular value from the diffuse-- that's just accounting for stuff bounced toward the eye. We're actually after stuff reflected in *all directions.*
clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.

#7   Members   -  Reputation: 1438


Posted 05 November 2012 - 06:47 AM

I'm currently doing something like "final diffuse term *= 1.0f - F;" is that correct ? Although I'm having a hard time seeing a difference there Posted Image

Sebastien Lagarde (here: http://seblagarde.wo...-lighting-mode/) is talking about using a specular color texture that only contains the constant fresnel reflectance color at F(0°) and a separate gloss map which is a monochrome texture containing the (what was before in the specMap) details of the specular highlighting.
So if this is a constant RGB value I'm wondering why even use a texture for this if you could just set this for each material in the engine. And inside the shader would I then use this monochrome gloss texture as the specular power ? This feels like a waste of resources to me or am I missing something ?

Edited by lipsryme, 05 November 2012 - 01:29 PM.

#8   Crossbones+   -  Reputation: 13062


Posted 05 November 2012 - 12:13 PM

I found those articles very helpful (in fact, more helpful than anything I've come across so far) though you need some math knowledge. Perhaps you'd like to take a look at them:


“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.