Materials#
Overview#
This extension provides non-visual materials for the Lidar, Radar, and Acoustic sensor models. A non-visual material describes how a sensor’s wave (optical or mechanical) interacts with a surface, and is used by the sensor’s BSDF to compute reflection and transmission at ray-traced hits.
Non-visual materials are authored in USD using semantic labels (e.g.
aluminum, concrete) and are mapped automatically to the underlying
sensor models. No code changes are required to label content; advanced users
can remap the material name-to-ID mapping or the BSDF behavior bound to a
material via carb settings.
Concepts#
Design principles#
The material system is designed around four properties that the rest of this document expands on:
Completeness — boundary reflections, volumetric transmission and attenuation, inter-reflection, optional phase/polarization.
Layering — additional sheets (coatings, paints) compose on top of the base material via the USD
coatingattribute, no code changes required.Semantic content workflow — content authors work in terms of named materials (
aluminum,concrete) rather than spectral data, with the runtime handling the mapping to BSDFs and property sets.Remappability — both the name-to-ID mapping and the BSDF-to-ID mapping can be overridden per modality at startup or at runtime (see Remappings).
Behaviors and properties#
A non-visual material has two parts:
A behavior — a BSDF (Bidirectional Scattering Distribution Function) kernel that defines how reflection and transmission are computed at a surface. Behaviors ship as the
Constant,DefaultMaterial,CoreMaterial,CompositeMaterial,RetroReflectiveMaterial,AcousticMaterial, andValidationMaterialplugins. Which behavior is bound to a material ID by default depends on the sensor’s wave type (see below).A property set — the spectral and physical data that a particular BSDF reads (
NvMatConfigplus the per-material JSON profile, holding spectral data, refractive indices, bulk properties, etc.).
The same behavior plugin (for example CompositeMaterial) is reused across
many base materials; only the property set bound to that material ID changes.
Sensor-agnostic output#
BSDFs return reflection and transmission coefficients as unitless values; the sensor model is responsible for interpreting them in its own radiometric unit-space (normalized intensity, absolute power, radiance, etc.). At the authoring level this means the same USD material labels can be reused across lidar, radar, and acoustic content; at the runtime level the wave type still selects different BSDF bindings (see below).
Wave types and modalities#
Materials are spectrally and wave-type aware:
Electromagnetic wave type — used by lidar and radar. BSDFs read optical/electromagnetic properties (refractive index, extinction coefficient, etc.).
Mechanical wave type — used by acoustic. BSDFs read physical properties (density, compressibility) and use impedance math rather than optical reflectance.
The default property-to-BSDF binding is wave-type dependent: on the EM path,
IDs 0 and 47 bind to DefaultMaterial and IDs 1-46 to CompositeMaterial;
on the acoustic path, IDs 0-46 bind to AcousticMaterial (ID 47, the
calibration target slot, has no acoustic interpretation and falls through to
DefaultMaterial).
Built-in BSDF behaviors#
The names below are what you pass to matBehaviorToIdOverrides to remap a
BSDF (see Remappings):
Behavior |
Description |
|---|---|
|
Returns a fixed constant factor for every hit regardless of geometry or material data; no Fresnel or spectral physics. |
|
Lambertian (cosine-weighted) reflection with a scalar factor. |
|
Full spectral diffuse + specular response with reflection and transmission, driven by the material’s property data. |
|
Behavior-level combination of lambertian, spectral diffuse/specular, and retro-reflective responses, selected by the material’s coating and attribute bits. The default behavior for EM base materials 1-46. |
|
Specialized retro-reflective response (e.g. road signs). |
|
Mechanical-wave BSDF that uses bulk physical properties instead of optical ones. |
|
Test/debug BSDF gated by
|
Optional BSDF features#
Most of these are controlled by the per-modality Settings:
Coatings and layers — additional material sheets (paint, clearcoat) layered on top of the base material. The presence of layers is driven purely by the
coatingUSD attribute (the runtime encodes coatings into the material ID andresolveNumLayersreads them directly);enableMaterialInterLayerContributionis a separate flag that turns on full inter-layer reflection/transmission physics across those layers.Phase and polarization — coherent tracking of phase and polarization state through material interactions. Enabled by
enablePolarization(currently only wired for lidar).Geometry-aware divergence — augments source-ray divergence using per-vertex normals/positions from rtxSensor (
BSDF.hderives ageomDivergenceFactorfrom neighboring vertex normals). Enabled byenableRtxSensorGeometry(currently only the radar key is consumed, with cross-modality side effects on BSDF profile loading).Continuation-ray output — BSDFs populate transmitted and reflected ray directions so the sensor model can fire secondary rays through transparent or partially transmissive surfaces.
Visual-band augmentation — diffuse reflectance and roughness from the visible-band material can be folded into the BSDF response. Enabled by
enableRtxReflectanceInformationandenableAdditionalRtxReturnInformation.
Specifying Non-Visual Materials in USD#
A non-visual material is specified by adding three custom string attributes to
a USD Material prim (typically under /Looks): a base material, an
optional coating, and optional attributes. The geometry binds to that
Material prim using the standard material:binding relationship.
def Cube "Cube3"
{
rel material:binding = </Looks/new_enc>
...
}
def Scope "Looks"
{
def Material "new_enc"
{
custom string omni:simready:nonvisual:base = "aluminum"
custom string omni:simready:nonvisual:coating = "clearcoat"
custom string omni:simready:nonvisual:attributes = "retroreflective"
def Shader "Shader"
{
uniform asset info:mdl:sourceAsset = @OmniPBR.mdl@
uniform token info:mdl:sourceAsset:subIdentifier = "OmniPBR"
color3f inputs:diffuse_color_constant = (0.67, 0.67, 0.97)
token outputs:out
}
}
}
Note
Only base is required. coating and attributes are optional and
may be omitted or set to none. Multiple attributes may be combined in
the attributes string (e.g. "retroreflective single_sided").
Note
The attribute prefix is configurable via the
/rtx/materialDb/nonVisualMaterialSemantics/prefix setting (see
Settings); the runtime concatenates this
prefix with the :base/:coating/:attributes suffixes, so any
prefix string is technically valid. The defaults shipped with content
are omni:simready:nonvisual (current) and inputs:nonvisual
(legacy).
Note
When the base material is calibration_lambertian, the shader’s
inputs:diffuse_color_constant is consumed: the red channel defines the
lambertian reflectance factor and the blue channel defines a
surface-roughness perturbation (the green channel is currently unused).
This consumption only happens through the DefaultMaterial BSDF and
only on the electromagnetic spectrum path (lidar, radar): the default
bindings put DefaultMaterial on IDs 0 and 47, with all other IDs on
CompositeMaterial. On the acoustic spectrum path, IDs 0-46 bind to
AcousticMaterial (which does not consume
inputs:diffuse_color_constant) and ID 47 has no acoustic
interpretation. Consumption also requires
enableRtxReflectanceInformation to be enabled for the modality.
Supported Materials, Coatings, and Attributes#
Each USD label maps to an integer index. The runtime encodes the chosen
base, coating, and attributes into a single 16-bit material ID
that is consumed by the sensor’s BSDF (see
Material ID Encoding).
Base Materials#
Material Name |
Index |
Description |
|---|---|---|
none |
0 |
Default, unlabeled, or unspecified |
Metals
aluminum |
1 |
Signs, poles, etc. |
steel |
2 |
Heavy construction metals |
oxidized_steel |
3 |
Rusted steel |
iron |
4 |
Manhole covers, drainage grills, etc. |
oxidized_iron |
5 |
Rusted iron |
silver |
6 |
Shiny metals |
brass |
7 |
Architecture |
bronze |
8 |
Statues, etc. |
oxidized_bronze_patina |
9 |
Old statues |
tin |
10 |
Food cans, etc. |
Polymers
plastic |
11 |
Generic plastics |
fiberglass |
12 |
Car bumpers, etc. |
carbon_fiber |
13 |
Car parts, bicycle parts, etc. |
vinyl |
14 |
Car interior, etc. |
plexiglass |
15 |
Light covers, etc. |
pvc |
16 |
Water tubing, etc. |
nylon |
17 |
Plastic bags, etc. |
polyester |
18 |
Some clothing, etc. |
Glass
clear_glass |
19 |
Glass that is clear with no contaminants |
frosted_glass |
20 |
Glass with volumetric particulates/imperfections |
one_way_mirror |
21 |
Building glass panels |
mirror |
22 |
Side mirrors, etc. |
ceramic_glass |
23 |
Heavy duty glass in construction |
Other
asphalt |
24 |
Roads, etc. |
concrete |
25 |
Construction |
leaf_grass |
26 |
Live vegetation |
dead_leaf_grass |
27 |
Dead vegetation |
rubber |
28 |
Tires, etc. |
wood |
29 |
Construction |
bark |
30 |
Trees, vegetation |
cardboard |
31 |
Boxes, etc. |
paper |
32 |
Newspapers, paper bags, writing paper, etc. |
fabric |
33 |
Clothing |
skin |
34 |
Human, pig, etc. |
fur_hair |
35 |
Human head, animal, etc. |
leather |
36 |
Clothing, car interior, etc. |
marble |
37 |
Construction |
brick |
38 |
Construction |
stone |
39 |
Nature, stones with structure |
gravel |
40 |
Nature, finer stones such as pebbles |
dirt |
41 |
Nature, very fine grains such as sand/dust |
mud |
42 |
Nature, wet dirt |
water |
43 |
Nature, water fountains, lakes, rivers, etc. |
salt_water |
44 |
Nature, oceans and seas, free from biologics |
snow |
45 |
Nature, frozen water droplets (crystalline) |
ice |
46 |
Nature, frozen water, larger bodies |
calibration_lambertian |
47 |
Special material with a defined diffuse reflectance, such as target panels with known reflectance |
Coatings#
Coating Name |
Index |
Description |
|---|---|---|
none |
0 |
Default, unlabeled, or unspecified |
paint |
1 |
Painted |
clearcoat |
2 |
Clear-coated |
paint_clearcoat |
3 |
Painted and clear-coated |
Indices 4-7 are reserved for future use.
Attributes#
Attributes are encoded as a bit field, so multiple attributes may apply to a single material. The “Bit value” column below is the value contributed to the attribute field of the material ID when that attribute is set.
Attribute Name |
Bit value |
Description |
|---|---|---|
none |
0 |
Unspecified attribute |
emissive |
1 |
Energy-emitting surface |
retroreflective |
2 |
Retro-reflective surface |
single_sided |
4 |
Single-sided surface (non-thin geometry) |
visually_transparent |
8 |
Material is visually transparent |
Bit value 16 is reserved for future use.
Note
The visually_transparent attribute is currently inert in the shipped
BSDFs: it is encoded into the material ID and decodable via
isVisuallyTransparent in MaterialUtils.h, but no built-in BSDF
currently changes its behavior based on it. It is reserved for content
authoring and for downstream consumers that may opt in.
Material ID Encoding#
The runtime packs the chosen base, coating, and attributes into a
single 16-bit material ID. The lower byte holds the base material; the upper
byte holds the coating (3 bits) and attribute bit field (5 bits):
bit: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+-----------------------+-------------+-------------------------------+
| attributes (5b) | coating (3b)| base material (8b) |
+-----------------------+-------------+-------------------------------+
Equivalently, given the indices from the tables above:
materialId = base | ((coating & 0x7) << 8) | ((attributeBits & 0x1F) << 11)
where attributeBits is the bitwise OR of the “Bit value” entries for every
attribute listed in the USD attributes string.
Worked example. A material with base = "steel" (2),
coating = "paint" (1), and attributes = "retroreflective" (bit value 2)
encodes as:
base = 0x02
coating = 0x01 << 8 = 0x0100
attribs = 0x02 << 11 = 0x1000
-----------------------------------------
materialId = 0x02 | 0x0100 | 0x1000 = 0x1102 = 4354
The preserveMaterialFlags setting (see Settings)
is applied as a mask on the upper byte, allowing the coating and attribute
bits to be selectively ignored at runtime.
Settings#
All settings below are carb settings and can be supplied as --/...
command-line arguments at startup or set at runtime via the carb Python
interface. The values shown are the defaults.
Per-modality settings#
The same settings are exposed independently for each of the three modalities
under /app/sensors/nv/{lidar,radar,acoustic}/:
--/app/sensors/nv/lidar/enableRtxReflectanceInformation=false
--/app/sensors/nv/lidar/enableAdditionalRtxReturnInformation=false
--/app/sensors/nv/lidar/enableRtxSensorGeometry=false
--/app/sensors/nv/lidar/enablePolarization=false
--/app/sensors/nv/lidar/matBehaviorToIdOverrides=""
--/app/sensors/nv/lidar/matNameToIdMapOverrides=""
# Same settings exist under /app/sensors/nv/radar/...
# Same settings exist under /app/sensors/nv/acoustic/...
enableRtxReflectanceInformation- Whentrue, rtxSensor allocates per-firing buffers for visible-band diffuse reflectance, specular reflectance, and shading normal. The lidar hit shader currently forwards only the diffuse reflectance (asNvMatInput::diffuseRefl) into the BSDF; specular and shading-normal buffers are reserved for future use. Required to consumeinputs:diffuse_color_constantfrom the USD shader (notably forcalibration_lambertian) and to layer paint reflectance over the base material.enableAdditionalRtxReturnInformation- Whentrue, rtxSensor additionally allocates per-firing buffers for visible-band index of refraction and roughness. The lidar hit shader forwards roughness (asNvMatInput::roughness) into the BSDF.enableRtxSensorGeometry- Intended to enable per-vertex normals and positions in rtxSensor returns and to swap BSDFs over to a geometry-aware material profile (_dev.json).enablePolarization- Intended to track polarization state through material interactions for coherent reflectance/transmittance.matNameToIdMapOverrides/matBehaviorToIdOverrides- Remap the material name (data) and BSDF behavior bound to a given material ID. See Remappings.
Warning
The enableRtxSensorGeometry and enablePolarization keys exist
under all three modality namespaces, but only a subset are actually
consumed by the runtime today:
enableRtxSensorGeometry: only the radar key (/app/sensors/nv/radar/enableRtxSensorGeometry) is read. It both drives radar’sRTXSENSOR_RETURN_GEOMETRYand is checked by every BSDF profile loader (Composite/Core/RetroReflective/Acoustic/ Validation) when deciding whether to load the geometry-aware_dev.jsonmaterial profile. The lidar and acoustic variants of this key are currently inert. Note that this means setting the radar key affects which material profiles are loaded for all sensor modalities, not just radar.enablePolarization: only the lidar key (/app/sensors/nv/lidar/enablePolarization) is read. The radar and acoustic variants are currently inert.
Note
For the acoustic modality, although WpmAcoustic does set the
RTXSENSOR_RETURN_MATERIAL_REFLECTANCE and
RTXSENSOR_RETURN_MATERIAL_ADDITIONAL flags from
enableRtxReflectanceInformation /
enableAdditionalRtxReturnInformation, the AcousticMaterial BSDF
does not currently read diffuse reflectance, roughness, or index of
refraction (it operates on bulk physical properties). Enabling those
flags for acoustic mainly adds GPU buffer cost without changing the BSDF
result.
How per-modality settings affect output#
Note
These settings change what data flows into the BSDF, not the layout of
GenericModelOutput. No new top-level fields or auxiliary data members
are added when these are toggled. The effect appears as different values
in the existing intensity/scalar field and in which hits pass the
sensor’s detection threshold.
Concretely:
Lidar.
BasicElements::scalarcarries the per-point intensity. EnablingenableRtxReflectanceInformationlets the BSDF blend the visible-band diffuse term (and any USD-specifieddiffuse_color_constantforcalibration_lambertian) into the reflectance, which directly scales the intensity.enableAdditionalRtxReturnInformationaugments roughness, redistributing intensity between specular and diffuse lobes.enablePolarizationis the only polarization key currently consumed and flows into the lidar BSDF as theCALC_PHASE_AND_POLARIZEDmaterial flag. Note: the lidar variant ofenableRtxSensorGeometryis currently inert (see warning above).Radar. Same BSDF inputs (diffuse reflectance, roughness) feed the WPM dmat-approx model; the result is a different RCS contribution per hit, which propagates to the radar detection list (range/Doppler/angle bins and detection scalar). Enabling these settings does not add new detection fields; it changes their values and which detections survive thresholding.
enableRtxSensorGeometryfor radar is consumed and enables geometry-aware RCS computation and the_dev.jsonmaterial profiles. The radar variant ofenablePolarizationis currently inert.Acoustic.
BasicElements::scalarcarries the received pressure level. The shippedAcousticMaterialBSDF operates on bulk physical properties (compressibility, density) and does not currently consume the visible-band diffuse/specular/roughness/IoR data, so enablingenableRtxReflectanceInformationandenableAdditionalRtxReturnInformationmainly adds GPU buffer cost without changing intensity.enableRtxSensorGeometryandenablePolarizationare not consumed by the acoustic plugin at present.
Note
The lidar materialId auxiliary field (LidarAuxiliaryData::matId)
is unrelated to these settings; its presence is governed by the
/app/sensors/nv/lidar/auxOutputType setting (EXTRA or FULL).
Warning
Each enabled flag allocates additional GPU buffers per firing:
enableRtxReflectanceInformation: three separate per-firing GPU buffers (diffuse, specular, shading-normal), eachfloat3per firing, totalling 9 floats per firing.enableAdditionalRtxReturnInformation: two scalar channels (IoR, roughness) = 2 floats/firing.enableRtxSensorGeometry: per-firing vertex normals and positions.
Enable only the data the chosen BSDFs actually consume.
Global material settings#
--/app/sensors/nv/materials/resetMaterials=false
--/app/sensors/nv/materials/enableMaterialInterLayerContribution=false
--/app/sensors/nv/materials/preserveMaterialFlags=0xff
--/rtx/materialDb/nonVisualMaterialSemantics/prefix=omni:simready:nonvisual
resetMaterials- Set totrueto re-process the material database after applying remappings at runtime.enableMaterialInterLayerContribution- Enables inter-layer reflectance and transmittance calculations across stacked material layers.preserveMaterialFlags- Bit mask filtering the upper byte of the encoded material ID (the byte that holds coating and attribute bits). Default0xffhonors all coating/attribute flags; setting it to0strips them and uses only the base material./rtx/materialDb/nonVisualMaterialSemantics/prefix- Selects the USD attribute prefix used to discover non-visual material labels. Set toinputs:nonvisualfor legacy content; otherwise leave at the defaultomni:simready:nonvisual.
Remappings (advanced)#
The default mapping from base material names to material IDs (and the BSDF behavior bound to each ID) can be overridden per modality. Only IDs being changed need to be listed.
For example, to remap material IDs 5 and 6 for the lidar sensor:
--/app/sensors/nv/lidar/matBehaviorToIdOverrides="CompositeMaterial:5;CoreMaterial:6"
--/app/sensors/nv/lidar/matNameToIdMapOverrides="asphalt:5;aluminum:6"
This binds material ID 5 to the asphalt properties evaluated by the
CompositeMaterial BSDF, and ID 6 to aluminum evaluated by the
CoreMaterial BSDF (overriding the defaults of oxidized_iron and
silver).
Remappings can be supplied at startup or applied at runtime. To apply at runtime, set both override settings first and then set:
--/app/sensors/nv/materials/resetMaterials=true
Warning
resetMaterials only takes effect after the override settings have
been written. If toggled first, the reset uses the previous (or default)
mapping.
Note
resetMaterials is self-clearing: once read by the runtime, it is
automatically set back to false. Inspecting the setting after a
reset will therefore show false, not the value you wrote. Always
write true again to trigger another reset.
Troubleshooting#
Note
All content has the same material. The USD content is most likely
using the legacy prefix inputs:nonvisual while the runtime is
configured for omni:simready:nonvisual. Set:
--/rtx/materialDb/nonVisualMaterialSemantics/prefix=inputs:nonvisual
(or re-author the USD with the default prefix).
Note
Coating or attribute flags are being ignored. Check
--/app/sensors/nv/materials/preserveMaterialFlags. If it is 0,
only the base material is honored. If it is set as expected, verify the
USD string tokens against the tables above (typos in the label silently fall back to
none).
Note
Inspect material IDs in a viewport. Open RenderSettings -> Common
in kit, then View -> DebugView -> Non-Visual Material ID. This
renders the non-visual materials as false color and supports picking,
which is useful for verifying content-to-ID mappings.