mitsuba-renderer / mitsuba3

Mitsuba 3: A Retargetable Forward and Inverse Renderer
https://www.mitsuba-renderer.org/
Other
2.1k stars 246 forks source link

How to eval attribute from a sub-BSDF? #1314

Closed brabbitdousha closed 1 month ago

brabbitdousha commented 2 months ago

Summary

Hi, I am trying to get roughness in python using misuba3, however, si.bsdf().eval_attribute_1('roughness', si) could not be used for a specific BSDF inside the twosided BSDF.

System configuration

System information:

OS: windows CPU: intel i9-13900H GPU: RTX 4060 laptop Python version: 3.9 CUDA version: 12.0 NVidia driver: 550.54.14

Dr.Jit version: 0.4.4 Mitsuba version: 3.5.0

Description

Here is the bsdf that I tried with to eval roughness, with testBSDF2, everything is ok with my code below, however, when using testBSDF( with BSDF inside a twosided BSDF), si.bsdf().eval_attribute_1('roughness', si) will only return zeros, I think I need to call the sub BSDF to get the actual attribute, is there any way to do it in python-mitsuba3 ?

<bsdf type="twosided" id="testBSDF">
            <bsdf type="principled">
                <rgb name="base_color" value="0.01,0.9,0.9"/>
                <float name="metallic" value="1.0" />
                <float name="specular" value="0.2" />
                <float name="roughness" value="0.8" />
            </bsdf>
    </bsdf>

    <bsdf type="principled" id="testBSDF2">
                <rgb name="base_color" value="0.01,0.9,0.9"/>
                <float name="metallic" value="1.0" />
                <float name="specular" value="0.2" />
                <float name="roughness" value="0.8" />
    </bsdf>

    <shape type="ply" id="teapot_2">
        <string name="filename" value="meshes/teapot.ply"/>
        <transform name="to_world">
            <scale value="3.0"/>
            <translate x="-0.6" y="-3.0" z="0.0"/>
        </transform>
        <ref id="testBSDF2" />
    </shape>

my code that gets the roughness(alpha)

def get_roughness_detached(self, si):
        with dr.suspend_grad():
            with torch.no_grad():
                roughness_mask = si.bsdf().has_attribute('roughness')
                alpha_mask = si.bsdf().has_attribute('alpha')

                roughness = si.bsdf().eval_attribute_1('roughness', si)

                alpha = si.bsdf().eval_attribute_1('alpha', si)

                roughness = dr.select(alpha_mask, alpha, roughness)

                surf_with_no_roughness_mask = ~roughness_mask & ~alpha_mask & si.is_valid()

                roughness = dr.select(surf_with_no_roughness_mask, 1.0, roughness)

        return roughness

Steps to reproduce

  1. try different BSDF
  2. check the result
njroussel commented 1 month ago

Hi @brabbitdousha

This is a bug, we were missing an implementation for Twosided::eval_attribute. I've pushed a fix in https://github.com/mitsuba-renderer/mitsuba3/commit/5508ee6a392e2b32c1a4360742cbe9c966586458. Thank you!

You will either need to cherry-pick this commit into your local build and recompile, or wait for the next public release if you can't build the project yourself. You could also implement a custom BSDF in Python that behaves exactly like the twosided bsdf and add the missing eval_attribute code there if you do not want to compile yourself or wait for the release.

brabbitdousha commented 1 month ago

Hi @brabbitdousha

This is a bug, we were missing an implementation for Twosided::eval_attribute. I've pushed a fix in 5508ee6. Thank you!

You will either need to cherry-pick this commit into your local build and recompile, or wait for the next public release if you can't build the project yourself. You could also implement a custom BSDF in Python that behaves exactly like the twosided bsdf and add the missing eval_attribute code there if you do not want to compile yourself or wait for the release.

@njroussel Thanks for the quick reply! I checked your commit and I forgot to mention that has_attribute may also need an implementation, many thanks!

njroussel commented 1 month ago

Indeed... thank you :+1: