Jump to content
Wolfwood

BSDF Bonanza: GGX, Microfacets, Disney BRDF and More

Recommended Posts

I should mention, one thing that doesn't blend well is the metallic parameter.  If you have two objects one a metal the other a plastic and you do a 50% blend you are going to get some funky results.  (Not sure what a 50% metallic object even is.)  However, completely masking (100% blend) is perfectly legal.  The reason why its a float instead of a dielectric/conductor toggle is so that maps can be painted and you don't get aliasing due to the discontinuities of int 0 and int 1. 

Share this post


Link to post
Share on other sites

I should mention, one thing that doesn't blend well is the metallic parameter.  If you have two objects one a metal the other a plastic and you do a 50% blend you are going to get some funky results.  (Not sure what a 50% metallic object even is.)  However, completely masking (100% blend) is perfectly legal.  The reason why its a float instead of a dielectric/conductor toggle is so that maps can be painted and you don't get aliasing due to the discontinuities of int 0 and int 1. 

 

The following is very much IMHO :)

 

I don't think it should really always be either 1 or 0 for all materials. Well we all know this is true if the material is composed of entirely conductive or dielectric particles. What I am saying is that there is lots of stuff that are a mix of dielectric and conductor `bits`, ground down to small enough enough scales that it makes sense to model in a BSDF. In this case what the metallicity parameter does is specify the ratio of dielectric vs conductor `bits` that make up that material.

 

Our use of in-between metallicity values is pretty commonPractical example of in-between stuff are usually plastics and paints that are trying to look like metal, common in electronics, shampoo bottles, etc. Car paint is also a good example if you imagine the flakes being so small that they are indistinguishable from the plastic substrate they are suspended in (or just look at it from far enough away). 

 

In-between values also come up in metals that look a bit worn/dirty/dusty. The logic (to me!) is the same, one photon is hitting a grain of dust smaller than a pixel, the next a bit of metal...

In the end whatever looks right probably is right. These things are general purpose shaders, so since we don't have a shading model specific to every micro structure that exists, there will always be requirement for a fudge factor, and therefore a need for artist talent/observation skills when setting when these things up.

Share this post


Link to post
Share on other sites

 

In the end whatever looks right probably is right. 

 

It's time to step it up to the hitachi 3 MeV then ;)

 

Proper texture capture

 

 W020110511373809669618.jpg

Share this post


Link to post
Share on other sites

Here's a quickie vopnet material for folks to play with the disney layering. Hope it's correct :)

Cheers eetu! Just fyi, it renders black if you aren't using the namespaced otl.

Share this post


Link to post
Share on other sites

I think I may have found a problem, or maybe I'm missing something.

The returned albedo is a constant white, no matter the fresnel/reflectance settings. I expected this to return the Fresnel attenuated reflectance colour, so that we could use its inverted luminance to multiply a diffuse bsdf, and so maintain energy conservation. Bug?

 

Cheers

S

Share this post


Link to post
Share on other sites

I think I may have found a problem, or maybe I'm missing something.

Bug?

I actually have this tagged as issue #17.

Currently when in microfacet mode (ggx or gtr) F0 isn't taken into account when fetching the albedo. I actually have a fresnel aware diffuse bsdf where you wire in F0 and the diffuse takes the reflexivity of the microfacets.

PBRT takes the easy way out and instead of having an analytical solution just takes a bunch of samples of the BSDF and returns the albedo of your parameters settings.

Edited by Wolfwood

Share this post


Link to post
Share on other sites

I actually have this tagged as issue #17.

Currently when in microfacet mode (ggx or gtr) F0 isn't taken into account when fetching the albedo. I actually have a fresnel aware diffuse bsdf where you wire in F0 and the diffuse takes the reflexivity of the microfacets.

PBRT takes the easy way out and instead of having an analytical solution just takes a bunch of samples of the BSDF and returns the albedo of your parameters settings.

Hi Jim,

Do you already have a vop for that? I suppose I can hack one out of the disney BRDF vop, but would be good to have it in the package for consistency/tidyness.

 

For various reasons I can't currently just use the Disney BRDF, our parametrization was already almost identical to what they came up with, but I need the bsdf's to remain separate until the last moment, to allow our indirect lighting system to persist (necessarily), and to allow them to be conditional on things things like; are we in pcloud irradiance caching mode, is the cache in use, is sss in use (requires that Fresnel attenuation output), and a whole bunch of other practical things like thin translucency that works properly with indirect lighting, separate diffuse/spec bump, etc.

 

Basically our parameter mixer node is separate from the bsdf's, it just spits out energy conserving fresnel'ed intensities for diff, spec, coat, sss, opc. Although I know the microfacet goodness is necessarily going to blow that up into a sort of web over whole thing, I still need things separate, and so fresnel'ed albedos are critical :)

All that stuff is wrapped up into a neat vop UI, similar to surface model but nice UI/behaviour like disney. This vop outputs a struct containing the bsdf's which we can either plug into a shader blender or into our custom indirect lighting system that works in raytrace mode (or bypassed when in pbr). The unpacked bsdf's go into corresponding customized indirect lighting vops (for per component sample/scope/maxdist control and irr cache lookup comparability), speaking of which I have been getting results more or less twice as fast as PBR that are visually identical apart from less noise, but that's a future thread where I hope to convince more to get on the bandwagon and push for per component sample control (indirect decoupling is not enough), like Arnold ;) 

Share this post


Link to post
Share on other sites

this thread makes my day :)

 

i would never understand the theory behind...but the disney brdf together with the mixer seems to be very artist friendly shader...

 

THANKS!

Share this post


Link to post
Share on other sites

The following is very much IMHO :)

I don't think it should really always be either 1 or 0 for all materials. Well we all know this is true if the material is composed of entirely conductive or dielectric particles. What I am saying is that there is lots of stuff that are a mix of dielectric and conductor `bits`, ground down to small enough enough scales that it makes sense to model in a BSDF. In this case what the metallicity parameter does is specify the ratio of dielectric vs conductor `bits` that make up that material.

Indeed. From a pure physical pov it doesn't make sense but from a artistic or approximation pov it makes perfect sense. The disney brdf is a reference implementation of what was described in the paper. There are some aspects I love very much about it. Parameter values between 0 and 1 but unclamped, along with having a small number of parameters. Its obvious that a lot of time and thought went into its design. But of course there are also some things I don't, for example I dislike the remapping of the roughness masking term that happens under the hood. If nothing else it serves as a wonderful starting place for discussions about PBR shader interfaces. Internally we'll definitely be making some modifications. :)

Edited by Wolfwood

Share this post


Link to post
Share on other sites

 

Do you already have a vop for that? I suppose I can hack one out of the disney BRDF vop, but would be good to have it in the package for consistency/tidyness.

 

Ya I do, I just stripped it out of the release cause I needed to make some examples for it first.  I'll try to update the OTL tonight with a couple of mods based on the above comments.

Share this post


Link to post
Share on other sites

Indeed. From a pure physical pov it doesn't make sense but from a artistic or approximation pov it makes perfect sense. The disney brdf is a reference implementation of what was described in the paper. There are some aspects I love very much about it. Parameter values between 0 and 1 but unclamped, along with having a small number of parameters. Its obvious that a lot of time and thought went into its design. But of course there are also some things I don't, for example I dislike the remapping of the roughness masking term that happens under the hood. If nothing else it serves as a wonderful starting place for discussions about PBR shader interfaces. Internally we'll definitely be making some modifications. :)

Yip the Disney BRDF is great, I love the simplicity of it, yes it could be a bit more flexible(Houdini like) in terms of control, but like you say, it makes for a great discussion about the current surface model.

thanks again for these! :)

 

Share this post


Link to post
Share on other sites

Just as a heads up we've come across a Houdini (LLVM) bug when using the Disney mixer with varying values.  If you see a crash that looks like-

VEX_LLowering::createInputRegister(llvm::MachineFunction&, llvm::MachineBasicBlock&, UT_AssocArray<llvm::Value const*, unsigned int>&, llvm::Value const*) <libHoudiniUT.so>
VEX_LLowering::lowerToMachineCode(llvm::MachineFunction&) <libHoudiniUT.so>
VEX_LLowering::runOnMachineFunction(llvm::MachineFunction&) <libHoudiniUT.so>
llvm::FPPassManager::runOnFunction(llvm::Function&) <libHoudiniUT.so>
llvm::FunctionPassManagerImpl::run(llvm::Function&) <libHoudiniUT.so>
llvm::FunctionPassManager::run(llvm::Function&) <libHoudiniUT.so>
VEX_LModule::codeGen(VEX_SymbolTable&, UT_Array<VEX_Word>&, UT_StringArray&, VEX_SymbolTable const&, VEX_NativeModule*, _IO_FILE*, int) const <libHoudiniUT.so>
VEX_Code::codeGen(VEX_LModule const&, VEX_SymbolTable const&, VEX_ErrorLog&) <libHoudiniUT.so>
VEX_Assemble::getAutoFoldedCode(VEX_SymbolTable const&, VEX_AssembleParms const&, VEX_ErrorLog&, bool) <libHoudiniUT.so>
VEX_Assemble::getAutoFoldedCode(int, char const* const*, VEX_AssembleParms const&, VEX_ErrorLog&, bool) <libHoudiniUT.so>

it's probably the same one.  I've tracked down exactly what part of the source is causing the crash and have a workaround that I'll push out tonight or tomorrow.  The bug has been reported to SESI and hopefully they'll fix it on their end too.

Share this post


Link to post
Share on other sites

ahh I my Houdini was crashing constantly yesterday while trying test the disney mixer, I didn't take much note of the console errors though..I will try again when I get a moment, or just wait for a update then try again :)

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

×