-
Hi again! I'm trying to model a custom BSDF which allows me to use a specular reflectance texture for a Principled Disney BSDF. Before implementing my custom Principled BSDF, I have implemented a very simple custom diffuse BSDF in order to see if it works correctly with my custom integrators. The problem with that comes when I try to evaluate some attributes from my BSDF, which gives me the following error message:
This is my custom BSDF so far: class CustomBSDF(mi.BSDF):
def __init__(self, props):
mi.BSDF.__init__(self, props)
self.tint = props['tint']
self.m_flags = mi.BSDFFlags.DiffuseReflection | mi.BSDFFlags.FrontSide
self.m_components = [self.m_flags]
def eval(self, ctx: mi.BSDFContext, si: mi.SurfaceInteraction3f, wo: mi.Vector3f,
active: bool = True) -> mi.Color3f:
if not ctx.is_enabled(mi.BSDFFlags.DiffuseReflection):
return mi.Color3f(0.0)
return mi.Color3f(self.tint)
def pdf(self, ctx: mi.BSDFContext, si: mi.SurfaceInteraction3f, wo: mi.Vector3f,
active: bool = True) -> float:
if not ctx.is_enabled(mi.BSDFFlags.DiffuseReflection):
return 0.0
cos_theta_i = mi.Frame3f.cos_theta(si.wi)
cos_theta_o = mi.Frame3f.cos_theta(wo)
pdf = mi.warp.square_to_cosine_hemisphere_pdf(wo)
return dr.select(dr.and_(cos_theta_i > 0.0, cos_theta_o > 0.0), pdf, 0.0)
def sample(self, ctx: mi.BSDFContext, si: mi.SurfaceInteraction3f, sample1: float, sample2: mi.Point2f,
active: bool = True) -> tuple[mi.BSDFSample3f, mi.Color3f]:
cos_theta_i = mi.Frame3f.cos_theta(si.wi)
active &= cos_theta_i > 0.0
bs = mi.BSDFSample3f()
bs.wo = mi.warp.square_to_cosine_hemisphere(sample2)
bs.pdf = mi.warp.square_to_cosine_hemisphere_pdf(bs.wo)
bs.eta = 1.0
bs.sampled_type = +mi.BSDFFlags.DiffuseReflection
bs.sampled_component = 0
value = mi.Color3f(self.tint)
return bs, dr.select(active & (bs.pdf > 0.0), value, mi.Color3f(0.0))
def traverse(self, callback: mi.TraversalCallback):
callback.put_parameter('tint', self.tint, mi.ParamFlags.Differentiable)
def to_string(self) -> str:
return ('CustomBSDF[\n'
' tint=%s,\n'
']' % (self.tint)) Searching through the code I've found that the implementation that I would like to be used for this case is the same as the implementation of the class AttributeCallback. Is there a way to indicate that I want to use that implementation when rendering from a custom integrator? An example of a custom integrator could look like this: class Roughness(mi.SamplingIntegrator):
def __init__(self, props):
mi.SamplingIntegrator.__init__(self, props)
def sample(self, scene: mi.Scene, sampler, ray: mi.RayDifferential3f, medium: mi.Medium = None,
active: bool = True) -> tuple[mi.Color3f, bool, List[float]]:
si = scene.ray_intersect(ray=ray, active=active)
bsdf = si.bsdf(ray)
col_eval = bsdf.eval_attribute('roughness', si=si, active=active)
valid = si.is_valid()
color = dr.select(valid, col_eval, mi.Color3f(0.0, 0.0, 0.0))
return color, valid, [dr.select(valid, 1.0, 0.0)] Note: I'm okay with the eval_attribute() method outputting black if that attribute is not found, I want the attribute to be evaluated if found and outputting some default value (for example, black) if that attribute is not found. Thanks in advance! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 4 replies
-
Hi @Frollo24 This should just work? I litterally ran your code and couldn't reproduce the same error message. Here's a test where we use a custom BSDF and test that we can evaluate its custom attribute: https://github.com/mitsuba-renderer/mitsuba3/blob/master/src/render/tests/test_bsdf.py#L30-L66 Could you send a full reproducer if you're still seeing this issue? |
Beta Was this translation helpful? Give feedback.
-
Hi @Frollo24 , I think the main problem is that you should be using Additionally, a few small things I had to modify to get your example to work
Also, please keep in mind that I tested this with latest version of Mitsuba (3.5.0) so you may also want to consider upgrading if you're still encountering issues. |
Beta Was this translation helpful? Give feedback.
Thanks again for your response! I think I'm going to wrap my float as a uniform spectrum, which I think is cleaner than converting the float to a texture.
For anyone reading this, I'm going to mark this comment as the answer because I'm going to include some example working code about this discussion, but I want to mention both @njroussel and @rtabbara for helping me out with this question I had.
Here is the code that I have now: