top coat unsupported modes

Issue #1069 resolved
Alessandro Padovani created an issue

daz studio 4.15.0.0.30, blender 3.2.0, diffeomorphic 1.6.2.1051

This is related to #1060 #1065 #29 #577.

I see when there’s a top coat mode that is not supported the importer doesn’t import any topcoat. It would be better to reverse to a 0.5 reflectivity instead so at least the user gets the top coat color then he can fix things by hand if needed.

The actual supported modes are reflectivity and fresnel, while weighted and custom curve are not supported.

Test scene included topcoat.duf

Comments (44)

  1. Alessandro Padovani reporter

    As for commit 54ff8b9, I see the imported top coat factor is 0.5.

    If we reverse to a 0.5 reflectivity then the factor should be 0.025 for iray weight = 1. That is, we use the equations for the reflectivity mode.

    Fac = 0.05 * Top Coat Weight * Reflectivity

  2. Alessandro Padovani reporter

    The “custom curve” mode is reversed to a 0.5 reflectivity as intended.

    The “weighted“ mode is not imported, we can reverse to a 0.5 reflectivity as well. Then will see what I can do to better support the various top coat modes and parameters but will be another discussion.

  3. Alessandro Padovani reporter

    Commit 35f3867 is good as for reversing to a 0.5 reflectivity.

    But the top coat bump is not good. In iray depending on the bump mode we can have a bump or a normal map, same as the 4-layer uber in #1070. So we can’t embed a bump node in the daz top coat group because it could be a normal map instead. But we can plug a texture in the normal input if the top coat gets a bump or a normal map. Same as we do with the other groups there’s no need to embed the bump map.

  4. Midnight Arrow

    Just going by the Uber shader public documentation, I can tell these are simple aliases for MDL’s weighted_layer, fresnel_layer, and custom_curve_layer. We already discussed the custom curve, the Schlick Approximation, in #1075. You can find the public API in the MDL specs. https://raytracing-docs.nvidia.com/mdl/specification/MDL_spec_1.7.2_17Jan2022.pdf

    Weighted: uses the top coat weight as the mix input directly.

    Fresnel: uses accurate fresnel according to IOR.

    Custom Curve: uses Schlick fresnel according to curve 0 and curve 90 (normal and grazing angle). Also provides the exponent, which is why I recommended to expose it from the Schlick node group.

  5. Alessandro Padovani reporter

    Yes that is also specified in the daz docs that are (unusually) good in this case. But your input on schlick was extremely useful anyway. I’m testing schlick with the variuos daz groups to prepare a good description for Thomas. Then I’ll fix the top coat too I hope. Thank you again.

    And of course if you want to fix the top coat group yourself, or any material group, please go ahead. Then I could help with testing.

    http://docs.daz3d.com/doku.php/public/software/dazstudio/4/referenceguide/interface/panes/surfaces/shaders/iray_uber_shader/start

  6. Thomas Larsson repo owner

    The last commit puts bump and normal map nodes outside the top coat group. It actually simplified the code so I guess something is right.

    I’m not sure how to deal with base bump and normals though. Currently I ignore them if there is a top coat normal, since the normal map node has no normal input. And if there is a top coat bump node I link the base normal into it, thus skipping any base bump. Does that make sense?

  7. Alessandro Padovani reporter

    Ideally I would have guessed the top coat is independent with its own bump layer. But I see that iray mixes the base and top coat bumps so yes your idea is correct. Then to mix the normal maps you can use overlays see #406.

    Test scene included topcoat-bump.duf. I used a couple textures from https://3dtextures.me

    edit. To save time below it’s how the implementation of the test scene should come out. Please note that the fresnel is wrong but this is expected until hopefully I’ll fix it together with the other top coat modes with help by Midnight.

    edit. note. important. Please note that there’s a flaw in the overlay chain when any normal map strength > 1. In this case the chain needs to be normalized and the normal map node will get the maximum strength. This is probably to be fixed in #406 too if we can have strength > 1.

    So in our test scene we have:

    • top coat bump = 2
    • base bump = 0.2

    That becomes:

    • normal map strength = 2 (max value from the list of maps)
    • top coat overlay = 2/2 = 1
    • base overlay = 0.2/2 = 0.1

  8. Thomas Larsson repo owner

    The test file now comes in correctly. However, I am still unsure how to mix height maps. Currently I just plug in the base bump output into the normal input of the top coat bump node. That is one way to mix them but perhaps there are better ones.

    In the pbrskin case the top coat bump node uses the base bump texture, with a modified strength. Only the base normal map is linked to the top coat bump node.

  9. Alessandro Padovani reporter

    Commit 82baa2c is good for the normal maps.

    But doesn’t mix the bump maps right. I included another test scene topcoat-bump-2.duf, that uses a bump map instead of a normal map for the base bump, and below it’s how it should come. I tested the four cases.

    note. This is for uber, didn’t test pbrskin yet.

    • base normal + top coat normal (ok)
    • base bump + top coat bump (ok)
    • base bump + top coat normal (not good, see below)
    • base normal + top coat bump (ok)

  10. Alessandro Padovani reporter

    Commit 3bf57f8 works fine.

    Will keep this open to progress with pbrskin and topcoat modes. Though pbrskin is another shader so should probably deserve its own discussion.

  11. Alessandro Padovani reporter

    As another step we may add anisotropy. This is the same as #786.

    Below it’s the setup and the equations. Please note that the principled shader doesn’t support a separate anisotropy for the top coat. So in this case we may add a daz top coat group to the principled shader as we do with the other extra features. The single principled option will not support the top coat anisotropy.

    Test scene included topcoat-anisotropy.duf

    # anisotropic bsdf, works fine for low roughness
    distribution = shirley
    roughness = top coat roughness
    anisotropy = top coat anisotropy
    rotation = 1 - top coat rotations
    

  12. Alessandro Padovani reporter

    Commit 86972ef works fine for the bsdf option but doesn’t add the daz top coat group to the principled option.

    The idea is that we use extra daz groups for the features the principled shader doesn’t support, as is the case for dual lobe for example. Then we also use the principled clearcoat for the thin walled refraction, so this is another limit.

    The single principled option will only support a basic top coat since the extra daz groups are pruned. This means that complex top coats will not be converted for the single principled option that will have no top coat in this case.

    # the principled shader only supports a basic top coat
    # for extra features we use the bsdf daz groups
    if top coat anisotropy > 0
        use the daz top coat group
    

  13. Midnight Arrow

    On closer inspection of the MDL file, metallicity and glossiness both are just top coats set to custom curve mode. For efficiency you can eliminate the separate metallic and glossiness node groups and implement just a single top coat group for all.

    The reflectivity shader claims inspiration from the Disney principled shader, which inspired Blender’s own. https://media.disneyanimation.com/uploads/production/publication_asset/48/asset/s2012_pbs_disney_brdf_notes_v3.pdf

    The Disney principled incorporates another Schlick Approximation too. Custom curve mode and reflectivity mode under the hood call the same MDL function with slight difference in parameters.

    So reflectivity/custom curve mode are Schlick approximation of fresnel, fresnel mode is correct fresnel, weighted is mixed by weight directly.

  14. Alessandro Padovani reporter

    Metals are different because they have the glossy color driven by the fresnel, and the pbrskin is different too because it’s a “dual lobe“ metal. See #786. Then the fresnel could be the same as you say. Thank you so much for the insight into the mdl code I’m going to collect all your information for testing and improvement.

    At this point may be we can finish the top coat first that will also serve as a first test.

    Again please feel free to fix anything yourself if you want to. I can always help with testing.

  15. Midnight Arrow

    I misunderstood how custom_curve_layer works. I though it took the IOR values directly but it doesn’t. Normal reflectivity and grazing reflectivity are instead the brightness of the facing and rim geometry. It’s the same as putting a color ramp after a fresnel node in Blender, you set the range to remap the fresnel effect. So a normal reflectivity of 0.08 and a grazing reflectivity of 0 will have bright highlights on the face but no edge lighting.

    The only thing different between reflectivity mode and custom curve mode, reflectivity is bounded to the 0.0 - 1.0 range and multiplied by 0.08 to force it inside dielectric range of 0.0 to 0.08. For custom curve you set curve 0 directly, you can keep it in the dielectric range or ramp it all the way to the metallic, 0.5 to 1.0 range.

    This is how metals are made by the Uber shader (it’s driven by Schlick not fresnel).

    Fresnel mode is the same but with correct fresnel controlled by the IOR. So to achieve a correct metallic effect, you need to disable the “metallic” slider and use top coat fresnel mode instead. Weighted blends by weight directly.

    This is the correct Schlick node group.

    We no longer need to convert the values down to dielectric range, they should be passed in that way already.

    I’ve implemented all four top coat groups (so that means glossiness and metallic are done too). Still waiting on word from Daz to share them.

  16. Alessandro Padovani reporter

    I was just going to ask your help because I didn’t understand the custom curve so you anticipated me thank you so much.

  17. Alessandro Padovani reporter

    daz studio 4.21.0.5, blender 3.6.0, diffeomorphic 1.7.1.1679

    Ok I believe I got it.

    This is a first implementation, not perfect there's some approximation but it is a neat improvement since we support all the top coat modes. Credits go to @Midnight for looking at the mdl code and providing useful information. I'd never be able to do this without his help.

    So below it's the setup and equations. Please note that the new top coat uses the schlick approximation for fresnel that's similar to what iray does.

    # daz top coat based on the schlick fresnel approximation
    
    fac = top coat weight
    
    if top coat mode = reflectivity
        specular 0 = reflectivity * 0.08
        specular 90 = 1
        power = 5
    
    if top coat mode = fresnel
        specular 0 = ((top coat ior - 1)/(top coat ior + 1)) ** 2
        specular 90 = 0.5
        power = 5
    
    if top coat mode = weighted
        specular 0 = 1
        specular 90 = 1
        power = 1
    
    if top coat mode = custom curve
        specular 0 = top coat curve 0
        specular 90 = top coat curve 90
        power = top coat curve exponent
    
    color = top coat color
    roughness = top coat roughness
    anisotropy = top coat anisotropy
    rotation = 1 - top coat rotations
    
    if pbr specular glossiness is used
        roughness = 1 - top coat glosiness ** 2
    

  18. Thomas Larsson repo owner

    Implemented in last commit.

    How do we deal with other shaders? For pbrskin I used the same as reflectivity mode, but with another channel (Top Coat Reflectivity instead of Reflectivity). For unsupported shaders I used the same as weighted.

  19. Alessandro Padovani reporter

    Commit 64fe7f7.

    Thank you for the fast fix.

    bug. missing channels. There’s a bug since it doesn’t seem to import any other channel as diffuse or glossy for example, tried uber and pbrskin it’s the same. Test scene topcoat-schlick.duf.

    As for pbrskin yes it’s reflectivity.

    As for unsupported shaders it depends, most don’t support topcoat as the default shader. So it is case by case, but since we don’t support unsupported shaders then I guess anything will do. Or if you have any example let me know.

  20. Thomas Larsson repo owner

    Fixed in last commit. Normally the incoming shader is ignored when the weight = 1. However, for some channels, e.g. glossy and dual lobe, the mixing also depends on a fresnel node, and then the link to the BSDF input cannot be removed. Now top coat also behaves like that.

  21. Alessandro Padovani reporter

    Commit c615936.

    bug. extended principled. I see the top coat is not used for extended principled. I don’t recall how we handled this before, probably approximating with the principled node instead of adding the top coat group, but now that we have full support it makes sense to use the top coat group for extended principled. While single principled will not support the top coat group as usual.

    Let me know if something is not clear.

    Other than that the basic functionality is there, will test the various unsupported cases reported so far then if everything works fine will close as resolved.

    p.s. If you can fix the metal mix #1641 this will complete for testing the natsuki hair with the new top coat.

  22. Thomas Larsson repo owner

    The top coat node for principled was only generated if there was anisotropy. Probably that was the only case that it mattered back when the test was set up. Now the top coat node is always generated, unless either

    1. Material method = single principled,
    2. Top coat is disabled (pbrskin)
    3. Top coat weight = 0.

  23. Log in to comment