material-shader-inputs#
Code |
VM.BIND.002 |
|---|---|
Validator |
|
Compatibility |
open-usd |
Tags |
✅ |
Summary#
Shader inputs must use the type their specification declares and hold a finite value.
Description#
Every authored shader input MUST hold the type its specification declares, and MUST NOT hold a NaN or an Infinity in any component.
The specification is the MDL module named by info:mdl:sourceAsset, or the definition
info:id resolves to.
Types. Against an info:id definition the comparison is on the underlying Tf.Type, so
color3f and float3 are the same type.
Finiteness. This applies to any input with floating-point components, not only inputs typed
float. A vector, color, matrix or array is flattened and each component tested, so a NaN in
one channel of a float3 normal is reported against that component. Booleans and integers are
exempt: neither can hold a non-finite value.
The value is read wherever the constant is authored. An input connected to an interface input
on the enclosing Material is followed to that interface input, and the report names the
attribute holding the value.
Comparing an MDL input against its module needs a runtime that can parse MDL. Where that
runtime is absent, the type comparison is skipped for MDL shaders. Finiteness still applies,
and shaders identified by info:id are still compared against their definition.
Finiteness and range#
A non-finite value is not out of range, so the two questions are separate and one authored value produces one finding.
Question |
Owned by |
|---|---|
Is the value finite? |
this requirement, on every numeric input of every shader |
Is a finite value inside its physical range? |
|
VM.PBR.002 skips a non-finite value, so an authored nan on base_weight is reported once,
here.
A type the OpenPBR nodedef does not declare is reported here and by VM.PBR.003. Either
requirement can be enabled without the other.
Why is it required?#
A type the shader definition does not declare produces incorrect visual output, or a runtime error in a simulation environment
A NaN or an Infinity breaks rendering
Types matching the declaration let a material move between tools without re-authoring
Examples#
Valid: every input has its declared type and a finite value#
def Material "ValidPreview"
{
token outputs:surface.connect = </ValidPreview/Surface.outputs:surface>
def Shader "Surface"
{
uniform token info:id = "UsdPreviewSurface"
color3f inputs:diffuseColor = (0.8, 0.8, 0.8)
float inputs:metallic = 0.0
float inputs:roughness = 0.5
token outputs:surface
}
}
Valid: an MDL shader with the asset and float types its module declares#
def Material "ValidMdl"
{
token outputs:mdl:surface.connect = </ValidMdl/Shader.outputs:out>
def Shader "Shader"
{
uniform token info:implementationSource = "sourceAsset"
uniform asset info:mdl:sourceAsset = @./OmniPBR.mdl@
uniform token info:mdl:sourceAsset:subIdentifier = "OmniPBR"
asset inputs:diffuse_texture = @./textures/bracket_basecolor.png@
float inputs:metallic_constant = 1.0
float inputs:reflection_roughness_constant = 0.5
token outputs:out
}
}
Invalid: an input with a type its declaration does not allow#
roughness is declared float by UsdPreviewSurface and authored here as a color.
def Material "WrongType"
{
token outputs:surface.connect = </WrongType/Surface.outputs:surface>
def Shader "Surface"
{
uniform token info:id = "UsdPreviewSurface"
color3f inputs:diffuseColor = (0.8, 0.8, 0.8)
color3f inputs:roughness = (0.5, 0.5, 0.5)
token outputs:surface
}
}
Invalid: a NaN reaching the surface through the material interface#
The constant sits on the Material, one connection away from the input it applies to. The finding
names both the shader input and the interface input the value came from.
def Material "NonFinite"
{
float inputs:roughness = nan
token outputs:surface.connect = </NonFinite/Surface.outputs:surface>
def Shader "Surface"
{
uniform token info:id = "UsdPreviewSurface"
color3f inputs:diffuseColor = (0.8, 0.8, 0.8)
float inputs:roughness.connect = </NonFinite.inputs:roughness>
token outputs:surface
}
}
Invalid: a NaN in one component of a vector input#
def Material "NonFiniteNormal"
{
token outputs:mtlx:surface.connect = </NonFiniteNormal/OpenPBR.outputs:out>
def Shader "OpenPBR"
{
uniform token info:id = "ND_open_pbr_surface_surfaceshader"
float3 inputs:geometry_normal = (0, nan, 1)
token outputs:out
}
}
Invalid: a NaN on an MDL shader input#
def Material "NonFiniteMdl"
{
token outputs:mdl:surface.connect = </NonFiniteMdl/Shader.outputs:out>
def Shader "Shader"
{
uniform token info:implementationSource = "sourceAsset"
uniform asset info:mdl:sourceAsset = @./OmniPBR.mdl@
uniform token info:mdl:sourceAsset:subIdentifier = "OmniPBR"
float inputs:reflection_roughness_constant = nan
token outputs:out
}
}
Invalid: an MDL source asset with no value#
Nothing names the module, so there is no specification to compare the inputs against.
def Material "EmptyMdl"
{
token outputs:mdl:surface.connect = </EmptyMdl/Shader.outputs:out>
def Shader "Shader"
{
uniform token info:implementationSource = "sourceAsset"
uniform asset info:mdl:sourceAsset = @@
token outputs:out
}
}
How to comply#
MDL shaders#
Use the USD type each parameter is declared with in the MDL module, such as
asset,floatorcolor3fPoint
info:mdl:sourceAssetat the.mdlfile and authorinfo:mdl:sourceAsset:subIdentifier
Built-in shaders#
Use the types the shader’s specification declares, such as the UsdPreviewSurface specification for
UsdPreviewSurfaceand the MaterialX nodedef for anND_*id
Both#
Author a finite value on every numeric input, including each component of a vector or color, and wherever the constant is authored — an interface input on the
Materialis checked as the shader input’s own value would beKeep OpenPBR surface values inside the bounds
VM.PBR.002sets