Source code for eradiate.scenes.integrators._path_tracers
from __future__ import annotations
import attrs
import eradiate
from ._core import Integrator
from ...attrs import define, documented
@define(eq=False, slots=False)
class MonteCarloIntegrator(Integrator):
"""
Base class for integrator elements wrapping kernel classes
deriving from
:class:`mitsuba.MonteCarloIntegrator`.
.. warning:: This class should not be instantiated.
"""
max_depth: int | None = documented(
attrs.field(default=None, converter=attrs.converters.optional(int)),
doc="Longest path depth in the generated measure data (where -1 "
"corresponds to ∞). A value of 1 will display only visible emitters. 2 "
"computes only direct illumination (no multiple scattering), etc. If "
"unset, the kernel default value (-1) is used.",
type="int or None",
init_type="int, optional",
)
rr_depth: int | None = documented(
attrs.field(default=None, converter=attrs.converters.optional(int)),
doc="Minimum path depth after which the implementation starts applying "
"the Russian roulette path termination criterion. If unset, the kernel "
"default value (5) is used.",
type="int or None",
init_type="int, optional",
)
hide_emitters: bool | None = documented(
attrs.field(default=None, converter=attrs.converters.optional(bool)),
doc="Hide directly visible emitters. If unset, the kernel default "
"value (``false``) is used.",
type="bool or None",
init_type="bool, optional",
)
@property
def kernel_type(self) -> str:
raise NotImplementedError
@property
def template(self) -> dict:
result = {"type": self.kernel_type}
if self.timeout is not None:
result["timeout"] = self.timeout
if self.max_depth is not None:
result["max_depth"] = self.max_depth
if self.rr_depth is not None:
result["rr_depth"] = self.rr_depth
if self.hide_emitters is not None:
result["hide_emitters"] = self.hide_emitters
if self.stokes and not eradiate.mode().is_polarized:
raise RuntimeError("stokes should only be set to True in polarized mode.")
if self.stokes:
result = {
"type": "stokes",
"integrator": result,
"meridian_align": self.meridian_align,
}
if self.moment:
result = {"type": "moment", "nested": result}
return result
[docs]
@define(eq=False, slots=False)
class PathIntegrator(MonteCarloIntegrator):
"""
A thin interface to the path tracer kernel plugin.
This integrator samples paths using random walks starting from the sensor.
It supports multiple scattering and does not account for volume
interactions.
"""
@property
def kernel_type(self) -> str:
return "path"
[docs]
@define(eq=False, slots=False)
class VolPathIntegrator(MonteCarloIntegrator):
"""
A thin interface to the volumetric path tracer kernel plugin.
This integrator samples paths using random walks starting from the sensor.
It supports multiple scattering and accounts for volume interactions.
"""
@property
def kernel_type(self) -> str:
return "volpath"
[docs]
@define(eq=False, slots=False)
class VolPathMISIntegrator(MonteCarloIntegrator):
"""
A thin interface to the volumetric path tracer (with spectral multiple
importance sampling) kernel plugin
:cite:`Miller2019NullscatteringPathIntegral`.
"""
use_spectral_mis = attrs.field(
default=None, converter=attrs.converters.optional(bool)
)
@property
def kernel_type(self) -> str:
return "volpathmis"
@property
def template(self) -> dict:
result = super().template
if self.use_spectral_mis is not None:
result["use_spectral_mis"] = self.use_spectral_mis
return result
[docs]
@define(eq=False, slots=False)
class PiecewiseVolPathIntegrator(MonteCarloIntegrator):
"""
A thin interface to the piecewise volumetric path tracer kernel plugin.
This integrator samples paths using random walks starting from the sensor.
It supports multiple scattering and accounts for 1D volume interactions.
"""
@property
def kernel_type(self) -> str:
return "piecewise_volpath"