Diffuse And BRDF Scattering
KrakenOS UI now exposes diffuse object workflows with two physics paths:
built-in deterministic scatter models and an optional pySCATMECH BRDF
backend. This removes the previous hard limitation where an object target
could only be represented as a specular mirror proxy.
Surface Type
Use the editable table surface type Diffuse Object for a non-sequential
scattering target. Internally the row still uses Glass='MIRROR' so the
native KrakenOS hit solver treats it as a reflective boundary, but the row also
stores a DiffuseScatter metadata block. During NsTrace the core branch
queue intercepts this hit and spawns deterministic scatter child rays instead
of the normal specular reflection.
Right-click the surface row and choose Coating / Polarization -> Diffuse /
BRDF Settings.... The current settings are:
modelLambertianfor matte diffuse scatter,Oren-Nayarfor rough diffuse reflection under directional illumination, orCosine Lobefor a glossy Phong-style lobe around the physical specular reflection direction.backendBuilt-infor dependency-free deterministic scatter, orpySCATMECHfor optional SCATMECH BRDF weighting.backend_modelandbackend_parameterspySCATMECHonly.backend_modelis the SCATMECH BRDF class name, such asMicroroughness_BRDF_Model.backend_parametersis a JSON/Python dict passed through to that model. For nested SCATMECH model dictionaries, use"__model__"as the nested model-name key.reflectanceDiffuse albedo in
[0, 1]. A value of0.8means the total spawned diffuse branch power is 80 percent of the incident branch power.sample_countNumber of deterministic child rays spawned per diffuse hit. The UI example uses nine rays: one surface-normal ray plus cosine-weighted off-axis samples.
max_scatter_angle_degScatter cone half-angle.
90degrees is a full Lambertian hemisphere. ForCosine Lobethis limits the glossy lobe around the specular reflection direction.lobe_exponentCosine Lobeonly.0is broad, Lambertian-like over the selected lobe cone; larger values make the lobe narrower and more mirror-like. Typical UI preview values are roughly10to100.roughness_degOren-Nayaronly. Sigma roughness angle in degrees.0collapses toward Lambertian-like diffuse weighting; larger values increase the rough-diffuse directional contrast for oblique illumination.min_branch_powerandmax_branch_depthBranch pruning controls used to prevent runaway recursive diffuse bounces.
target_surfaceOptional surface index for target-guided sampling. Leave it as
Nonefor a deterministic hemisphere/cone fan. Set it to a pupil, lens entrance, detector, beam splitter return aperture, or Image surface when the goal is source-driven imaging and the useful camera path would otherwise receive too few rays.target_radius_scaleMultiplier for the selected target surface clear radius.
1.0samples the nominal clear aperture; smaller values concentrate rays near the target center and larger values deliberately overfill the target for vignetting checks.
Guided Target Sampling
Guided sampling is deterministic importance sampling, not a shortcut back to a
specular object proxy. At a Diffuse Object hit the core builds child rays
from the hit point to samples on the selected target surface. Each child branch
is weighted by the selected scatter model and the approximate solid angle of
that target sample:
diffuse = {
"model": "Lambertian",
"backend": "Built-in",
"reflectance": 0.8,
"sample_count": 21,
"max_scatter_angle_deg": 90.0,
"target_surface": 1, # e.g. splitter return aperture / entrance pupil
"target_radius_scale": 0.9,
"min_branch_power": 1e-8,
"max_branch_depth": 4,
}
If no valid target sample is visible from the diffuse hit, the tracer falls back to the unguided scatter fan so the row still behaves as a diffuse surface.
Examples
Open Layouts -> Diffuse Object Lambertian Scatter or run:
python -m KrakenOS.Examples.Examp_Diffuse_Object_Lambertian_Scatter
The example launches one collimated ray from the source plane to a Diffuse
Object surface. The trace result contains one branch per Lambertian child
sample. Each branch has a BRANCH_PATH ending in /scatterNN and a
BRANCH_POWER equal to reflectance / sample_count for this deterministic
preview.
Open Layouts -> Diffuse Object Cosine Lobe Scatter or run:
python -m KrakenOS.Examples.Examp_Diffuse_Object_Cosine_Lobe_Scatter
This example uses model='Cosine Lobe' with lobe_exponent=35 and a
25 degree scatter cone. The generated branches stay near the physical
specular reflection direction, which is useful for satin, polished, or
partially glossy targets where a Lambertian surface would be too broad.
Open Layouts -> Diffuse Object Oren-Nayar Scatter or run:
python -m KrakenOS.Examples.Examp_Diffuse_Object_Oren_Nayar_Scatter
This example uses model='Oren-Nayar' with roughness_deg=35 and an
oblique collimated source. Unlike the Lambertian fixture, the deterministic
scatterNN child powers are not uniform; they follow the rough-diffuse
directional term produced by the Oren-Nayar BRDF.
Open Layouts -> Diffuse Object pySCATMECH Microroughness or run:
python -m KrakenOS.Examples.Examp_Diffuse_Object_pySCATMECH_Microroughness
This example requests backend='pySCATMECH' with
backend_model='Microroughness_BRDF_Model' and a Gaussian PSD. When the
SCATPY extension is installed, SCATMECH evaluates the BRDF weights for the
same deterministic branch directions used by the UI preview. If the extension
is unavailable, the trace still runs and records a pySCATMECH fallback
interaction label so the downgrade is explicit.
Regression check:
python -m KrakenOS.UI.validate_diffuse_object_scatter
python -m KrakenOS.UI.validate_diffuse_object_cosine_lobe
python -m KrakenOS.UI.validate_diffuse_object_oren_nayar
python -m KrakenOS.UI.validate_diffuse_object_pyscatmech
pySCATMECH Optional Backend
The local ~/Projects/pySCATMECH clone is directly useful here. It provides
SCATMECH bindings for physics-based polarized surface-scattering models:
pySCATMECH.brdf.BRDF_Modelevaluates scalar, Mueller, and Jones BRDF.pySCATMECH.local.Local_BRDF_Modelevaluates differential scattering cross sections for particles or localized defects on surfaces.pySCATMECH.fresnelandpySCATMECH.muellerprovide thin-film, polarization, Jones, Mueller, and Stokes helpers.
KrakenOS continues to own ray/surface hit finding, geometry, deterministic branch spawning, non-sequential bookkeeping, and detector analysis. The BRDF backend answers only this question at each hit: given wavelength, incident direction, surface normal, and model parameters, what relative BRDF weights should the deterministic child directions receive?
Current UI flow for the optional backend:
Choose surface type
Diffuse Object.Open
Diffuse / BRDF Settings....Set
ModeltopySCATMECH BRDFandBackendtopySCATMECH.Set
Backend modelto a SCATMECH class such asMicroroughness_BRDF_Model.Enter
Backend parametersas JSON or a Python dict.
Example backend-parameter block:
{
"substrate": "(1.56,0.0)",
"type": 0,
"psd": {
"__model__": "Gaussian_PSD_Function",
"sigma": 0.05,
"length": 1.0
}
}
The optional backend requires the compiled SCATPY extension. If the Python
package is visible but the extension is not installed, KrakenOS keeps tracing
and labels the interaction as a fallback so the user can still inspect the
layout without silent physics changes.
Current limitations:
pySCATMECHuses deterministic KrakenOS child directions. It does not yet ask SCATMECH to generate its own stochastic angular samples.The branch metadata preserves/project-transports the current Jones vector; it does not yet carry a full depolarized Stokes distribution.
Guided target sampling uses an approximate solid-angle weight and is intended for deterministic UI workflows.