You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mitsuba自定义Python采样器遇traverse方法未实现错误求助

在Mitsuba中用Python实现自定义采样器的问题解决

1. 是否可以用Python在Mitsuba中创建自定义采样器?

是的,Mitsuba 3完全支持通过Python编写自定义插件,包括采样器。不过在可微渲染变体(如llvm_ad_rgb)下,需要确保实现所有必要的接口方法,以兼容可微渲染流程。

2. 解决traverse()方法未实现的错误

你遇到的错误根源在于调用了基类未实现的traverse方法,同时代码中还有几处小问题需要修正:

错误原因分析

你的traverse方法中调用了super().traverse(cb),但Mitsuba的mi.Sampler基类在Python绑定中并未实现该方法(或为纯虚函数),导致触发Sampler::traverse_1_cb_ro(): not implemented!错误。此外,代码中还有两处逻辑问题:

  • next_1d方法生成了两个随机数但只返回第二个,浪费采样资源
  • clone方法未正确初始化新采样器的随机数生成器

修正后的完整代码

import mitsuba as mi
import drjit as dr
mi.set_variant('llvm_ad_rgb')

# 自定义采样器
class MySampler(mi.Sampler):
    def __init__(self, props):
        super().__init__(props)
        self.sample_count = props.get('sample_count', 256)
        self.base_seed = props.get('seed', 0)
        self.rng = mi.PCG32()
        self.seed(self.base_seed, 1)

    def seed(self, seed: int, wavefront_size: int) -> None:
        self.rng.seed(seed, wavefront_size)

    def next_1d(self, active=True):
        # 修复:直接返回单个随机数,避免浪费采样
        return self.rng.next_float32()
    
    def next_2d(self, active=True):
        return mi.Point2f(self.next_1d(active), self.next_1d(active))

    def advance(self):
        pass

    def set_sample_count(self, sample_count: int):
        self.sample_count = sample_count

    def get_sample_count(self) -> int:
        return self.sample_count

    def current_sample_index(self) -> int:
        return 0

    def clone(self):
        new_sampler = MySampler(mi.Properties())
        new_sampler.sample_count = self.sample_count
        new_sampler.base_seed = self.base_seed
        # 修复:初始化新采样器的随机数生成器
        new_sampler.seed(new_sampler.base_seed, 1)
        return new_sampler
    
    def traverse(self, cb):
        # 移除基类调用,直接处理自定义参数
        cb.put_parameter('sample_count', self.sample_count, mi.ParamFlags.NonDifferentiable)
        cb.put_parameter('base_seed', self.base_seed, mi.ParamFlags.NonDifferentiable)

    def to_string(self):
        return f"MySampler[\n  sample_count = {self.sample_count},\n  base_seed = {self.base_seed}\n]"

mi.register_sampler("mysampler", lambda props: MySampler(props))
scene = mi.load_file('teapot.xml')
image_xml = mi.render(scene)
import matplotlib.pyplot as plt
plt.axis('off')
plt.imshow(image_xml ** (1.0 / 2.2));

关键修正点说明

  • 移除super().traverse(cb):基类mi.Sampler的traverse方法未实现,无需调用。自定义参数的遍历逻辑已在当前方法中完成。
  • 修复next_1d方法:直接返回单个随机数,避免不必要的采样浪费。
  • 完善clone方法:为新采样器初始化随机数生成器,确保克隆后的采样器能正常工作。

场景XML文件说明

你的场景XML文件无需修改,只需确保模型和纹理路径正确即可。

内容的提问来源于stack exchange,提问作者Shreyas Shivakumara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 18:05:56