Page MenuHome

Add support for baking diffuse roughness in Cycles

Authored by Matt Heimlich (m9105826) on Mar 27 2018, 1:04 AM.



Roughness baking previously defaulted to 1.0 for all diffuse materials. This patch allows the baker to bake the correct roughness values for Oren-Nayar and Principled Diffuse BSDFs, and sets diffuse with a roughness of 0 to bake down to the correct value rather than defaulting to 1.

Diff Detail

rB Blender

Event Timeline

Brecht Van Lommel (brecht) requested changes to this revision.EditedMar 27 2018, 1:30 AM

If we're going to support this then we need separate bsdf_get_roughness_squared() functions for baking, and for denoising and transparent alpha. Otherwise the denoiser will assume diffuse BSDFs with roughness 0 to be sharp specular reflections. I suggest to add a bsdf_get_specular_roughness_squared() for the latter that has the existing code, and then use bsdf_get_roughness_squared() to also include diffuse.

However this won't work well when using it outside the Principled BSDF I think. For the Principled BSDF we know that the diffuse and specular roughness is matched, but for other shader setups we can't assume it. If you mix a diffuse BSDF (roughness 0) and microfacet BSDF (roughness 1) with Fresnel, the result will be a roughness value near 0. That doesn't really make sense to me?


I don't think this should be squared twice, when creating the Principled BSDF we square the microfacet roughness, but not the diffuse one?

In any case you should test if the render is identical before and after baking (plugging in the baked image into roughness instead of what was baked).

472–473 ↗(On Diff #10243)

For comparing if type is equal to one specific BSDF type it's not needed to add a macro here. It doesn't really simplify anything.

This revision now requires changes to proceed.Mar 27 2018, 1:30 AM

That is indeed what needs to be done to get the correct roughness value to the bake as confirmed by Lukas (or as close as we can get with all of those floating point ops, a node value of 0.1 ends up at around 0.109ish here in the bake)

472–473 ↗(On Diff #10243)

No problem, I noticed that there was one for Transparent == Transparent there already and figured it was a design choice to put all of the comparisons here. I'll pull those out since I know there are memory concerns here.


If you're baking to a byte image rounding to a value like 0.109 could happen, for a float image it should pretty exact though.

This code can be written more compactly as sqr(sqr(bsdf->roughness)) also.

Indeed, this won't work nicely for view-dependent effects like Fresnel or Facing values, but then again these aren't really effects that should be baked in the first place IMO, and those effects can't be used for PBR baking anyway, which is where I envision roughness baking having the most utility. What is the behavior today if you bake diffuse/glossy when mixing this way. In any case, I think that the benefits of being able to bake all roughness values outweigh the potential confusion over the corner cases.

Made requested changes

It's not about Fresnel or Facing, but any node setup that includes a Diffuse BSDF where you don't use the same roughness as Glossy BSDFs. I don't think that's a corner case, maybe a better heuristic can be found to deal with that.

Like only using the diffuse roughness if there is no specular BSDF or something, although that could lead to discontinuities in the baked image.

Can you provide an example of where that's an issue? In a quick test it seems to work as expected, expected average roughness of the two materials mixed by weight is returned to the baked texture.

The roughness of a diffuse BSDF and microfacet BSDF have a very different meaning. In the Disney BRDF they happen to be coupled, but I believe mostly to keep the number of parameters low.

So for BSDF setups where they are not coupled, averaging the diffuse and microfacet BSDF will not give a useful result, you won't be able to reproduce anything like the original. We can't really detect this well, so I guess we can live with current behavior.

I'll do some further fixes and simplifications and commit.


!sc->type == is wrong, it should be sc->type !=.

Fixes and simpler code with same result.

This revision is now accepted and ready to land.Mar 28 2018, 11:43 PM
This revision was automatically updated to reflect the committed changes.

How about to render roughness pass?

Sometimes I make my textures through render passes over composer with orthographic camera and background set to white and missing Roughness pass.

Maybe writing the wrong thread..