Precomputed Env BRDF and non-metal objects

Started by
8 comments, last by Hodgman 7 years ago

Hey all!

I am looking into making my reflections ok, so I started looking at UE4 solution for pre convolved reflections.

I think I get the gist of it and I will spend more time looking at the original paper a bit more, but I have a question doubt... Looking at the code, this line confuse me. In particulár the red part (from their paper)


float3 PrefilteredColor = PrefilterEnvMap( Roughness, R );
 float2 EnvBRDF = IntegrateBRDF( Roughness, NoV ); 

return PrefilteredColor * ( SpecularColor * EnvBRDF.x + EnvBRDF.y );

So EnvBRDF is computed regardless of the receiving material metalness, which I guess is fine. The problem I have is that since the red part is not scaled by the metalness/spec color, I always get reflections (and quite strong based on my first results) even on a material with 0 metalness... is that correct? If I look at the back of a non-metal object where there is no light from the analytical source, it looks like metal... can somebody shed some light on it for me?

Thank you,

Jacques

Advertisement

"0 metalness" in UE4 corresponds to "F0 (head-on) spec intensity of 0.04", so for low roughness (mirror reflections) you should be getting specular reflections that are about 4% intensity of the environment when the view direction is the same as the surface normal. As the viewing direction becomes more "grazing" with respect to the surface normal, the fresnel effect will cause the reflection to increase to 100%. If you're not getting this behavior, then you may have a bug somewhere. One thing I've found to be really helpful for these kinds of scenarios is to build a debug tool into your engine that lets you hover your mouse over a pixel, and it will tell you the final exit radiance for the surface under that pixel. If you have this, you can verify that your specular reflections are approximately the correct intensity.

As for your non-metal object looking like metal, keep in mind that if you don't have matching diffuse lighting then every material will look metallic! This is why it's important to have matching/balanced diffuse and specular terms from your environment.

"0 metalness" in UE4 corresponds to "F0 (head-on) spec intensity of 0.04", so for low roughness (mirror reflections) you should be getting specular reflections that are about 4% intensity of the environment when the view direction is the same as the surface normal. As the viewing direction becomes more "grazing" with respect to the surface normal, the fresnel effect will cause the reflection to increase to 100%. If you're not getting this behavior, then you may have a bug somewhere. One thing I've found to be really helpful for these kinds of scenarios is to build a debug tool into your engine that lets you hover your mouse over a pixel, and it will tell you the final exit radiance for the surface under that pixel. If you have this, you can verify that your specular reflections are approximately the correct intensity.

As for your non-metal object looking like metal, keep in mind that if you don't have matching diffuse lighting then every material will look metallic! This is why it's important to have matching/balanced diffuse and specular terms from your environment.

Thanks for the reply and suggestions, I will definitively make sure the diffuse matches the specular bit :)

I will try and check precise values, but certainly, especially in the back of the object (w.r.t to light) the intensity of reflections is way higher than 4% and given the code I posted above this is to be expected, right? I mean the "specular colour/F0" is scaling only first channel of the envbrdf texture and the y channel is only scaled by the result from cubemap, regardless of the material metalness. In this case, even if non-metal meant 0, I will always get something since metalness is not taken into account when generating the envbrdf texture...

I wonder if that the above is all fine, and the y channel is always supposed to be very small but at grazing angles, hence I might have some bugs in computing such angles (and therefore I pickup always high values when I shouldn't?). That sounds plausible, right? I am not sure how possible, but I wonder if I could've some errors in computing the view vector...

To validate I was not doing something odd I literally copy-pasted the code that generates the envBRDF texture from UE presentation.

As for how I apply the reflections, I do that as a post-process pass blending on top of the already lit scene and I use the formula I posted above.

Thanks

"0 metalness" in UE4 corresponds to "F0 (head-on) spec intensity of 0.04", so for low roughness (mirror reflections) you should be getting specular reflections that are about 4% intensity of the environment when the view direction is the same as the surface normal. As the viewing direction becomes more "grazing" with respect to the surface normal, the fresnel effect will cause the reflection to increase to 100%. If you're not getting this behavior, then you may have a bug somewhere. One thing I've found to be really helpful for these kinds of scenarios is to build a debug tool into your engine that lets you hover your mouse over a pixel, and it will tell you the final exit radiance for the surface under that pixel. If you have this, you can verify that your specular reflections are approximately the correct intensity.

As for your non-metal object looking like metal, keep in mind that if you don't have matching diffuse lighting then every material will look metallic! This is why it's important to have matching/balanced diffuse and specular terms from your environment.

Thanks for the reply and suggestions, I will definitively make sure the diffuse matches the specular bit :)

I will try and check precise values, but certainly, especially in the back of the object (w.r.t to light) the intensity of reflections is way higher than 4% and given the code I posted above this is to be expected, right? I mean the "specular colour/F0" is scaling only first channel of the envbrdf texture and the y channel is only scaled by the result from cubemap, regardless of the material metalness. In this case, even if non-metal meant 0, I will always get something since metalness is not taken into account when generating the envbrdf texture...

I wonder if that the above is all fine, and the y channel is always supposed to be very small but at grazing angles, hence I might have some bugs in computing such angles (and therefore I pickup always high values when I shouldn't?). That sounds plausible, right? I am not sure how possible, but I wonder if I could've some errors in computing the view vector...

To validate I was not doing something odd I literally copy-pasted the code that generates the envBRDF texture from UE presentation.

As for how I apply the reflections, I do that as a post-process pass blending on top of the already lit scene and I use the formula I posted above.

Thanks

Although, this to me looks kinda plausible for an NdotV (sorry if it doesn't... I am just starting in the field :P )

This is the sphere with NdotV

hfcC1WX.png

and this is what I get with IBL only (no analytical lights) on metalness of 0

B2NT9BD.png

HA! Nevermind, it looks like for some reason the envBRDF generated by the code on the course notes generates something that has the y axis flipped if compared to the one showed, so I forgot I added a sign flip to make it match. it now looks more like expected (with stronger response at grazing angles and overall less energy from reflections on non-,metals).

However, it s still quite strong... maybe now it's because of the balancing MJP mentioned

cut

HA! Nevermind, it looks like for some reason the envBRDF generated by the code on the course notes generates something that has the y axis flipped if compared to the one showed, so I forgot I added a sign flip to make it match. it now looks more like expected (with stronger response at grazing angles and overall less energy from reflections on non-,metals).

However, it s still quite strong... maybe now it's because of the balancing MJP mentioned

So this is now metal==1 vs metal==0

XkD6F8y.png

Does this look plausibly alright to you? (again, no analytical lights here). To me it still looks incredibly metallic :( What should I balance here, there is no other source of light but the reflections

It's like your fresnel is inverted for the top (is that the metal one?), there should be more reflection toward the edges as the angle approaches parallel and not less.

What should I balance here, there is no other source of light but the reflections

The light source is the surrounding environment - your current reflections are the specular component of that lighting. You also need the diffused reflections from the environment.

As a super quick hack, sample the bottom mip level (1x1 pixel) of your cubemap in the normal direction and use that as the diffuse component. This is wrong, but closer than nothing.

In the long run, you can use these same techniques to properly pre-convolve the environment against your diffuse BRDF. Or you can store those results in SH, etc, instead of another cubemap.

It's like your fresnel is inverted for the top (is that the metal one?), there should be more reflection toward the edges as the angle approaches parallel and not less.

The top one is the non metal one :\

What should I balance here, there is no other source of light but the reflections

The light source is the surrounding environment - your current reflections are the specular component of that lighting. You also need the diffused reflections from the environment.

As a super quick hack, sample the bottom mip level (1x1 pixel) of your cubemap in the normal direction and use that as the diffuse component. This is wrong, but closer than nothing.

In the long run, you can use these same techniques to properly pre-convolve the environment against your diffuse BRDF. Or you can store those results in SH, etc, instead of another cubemap.

I tried that, still looks pretty shiny :( ... I wrongfully generated only up to the 16x16 mip, but still..

[Top one is metalness 0, bottom one is metalness 1]

4GuNQLY.png

Ha, still that flipping causing me problems. For debug reasons I output the sampled result of envbrdf and used that as the sphere colour and immediately noticed that the green bit (shoult be at grazing angles) was at the center of the sphere... With the last mip thing it does look better than before... still feel a bit too shiny, but is clearly more plausible.

Thank you all!

Your latest pics are looking fairly plausible. Remeber that these are extremes of the surface model. We're talking about optically flat surfaces - almost flat at the molecular scale. Most surfaces are nowhere near that perfect.
Non metals can be very shiny when smooth. Make it less smooth if you want less reflections :wink:
For example, here's polished stone (non-metal):
Polished-Black-Granite-G654-Stone-Ball-S
And chrome (metal):
Chrome_ball_in_Ginza.jpg

This topic is closed to new replies.

Advertisement