Sign in to follow this  
parroteye

Precomputed Env BRDF and non-metal objects

Recommended Posts

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

Edited by parroteye

Share this post


Link to post
Share on other sites

"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.

Share this post


Link to post
Share on other sites

"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

Edited by parroteye

Share this post


Link to post
Share on other sites

 

"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

Edited by parroteye

Share this post


Link to post
Share on other sites

 

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

Edited by parroteye

Share this post


Link to post
Share on other sites

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.

Edited by Frenetic Pony

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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

Edited by parroteye

Share this post


Link to post
Share on other sites

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!

Edited by parroteye

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this