Skip to main content

ANARI Materials and Lights

ExperimentalPrivate workspaceFrom-v10

Retained ANARI materials translate directly into the canonical @luma.gl/shadertools PBR uniforms and texture bindings. ANARI does not own a separate BRDF or shader implementation. Lights reuse the shared ambient, directional, point, and spot lighting descriptions.

ANARIMaterial

const material = anariDevice.newMaterial('physicallyBased', {
baseColor: [0.18, 0.52, 0.96, 0.8],
metallic: 0.7,
roughness: 0.25,
alphaMode: 'blend',
clearcoat: 0.35
});

The supported subtypes are matte and physicallyBased. Both share these parameters:

type ANARIMaterialParameters = {
color?: ANARIVector3 | ANARIVector4;
baseColor?: ANARIVector3 | ANARIVector4;
emissive?: ANARIVector3;
emissiveStrength?: number;
metallic?: number;
roughness?: number;
opacity?: number;
alphaMode?: 'opaque' | 'mask' | 'blend';
alphaCutoff?: number;
doubleSided?: boolean;
unlit?: boolean;
specularColor?: ANARIVector3;
specularIntensity?: number;
clearcoat?: number;
clearcoatRoughness?: number;
transmission?: number;
dispersion?: number;
thickness?: number;
attenuationDistance?: number;
attenuationColor?: ANARIVector3;
indexOfRefraction?: number;
sheenColor?: ANARIVector3;
sheenRoughness?: number;
iridescence?: number;
iridescenceIndexOfRefraction?: number;
iridescenceThicknessMinimum?: number;
iridescenceThicknessMaximum?: number;
anisotropyStrength?: number;
anisotropyRotation?: number;
anisotropyDirection?: readonly [number, number];
normalScale?: number;
occlusionStrength?: number;
baseColorTexture?: ANARISampler;
metallicRoughnessTexture?: ANARISampler;
normalTexture?: ANARISampler;
occlusionTexture?: ANARISampler;
emissiveTexture?: ANARISampler;
specularColorTexture?: ANARISampler;
specularIntensityTexture?: ANARISampler;
transmissionTexture?: ANARISampler;
thicknessTexture?: ANARISampler;
clearcoatTexture?: ANARISampler;
clearcoatRoughnessTexture?: ANARISampler;
clearcoatNormalTexture?: ANARISampler;
sheenColorTexture?: ANARISampler;
sheenRoughnessTexture?: ANARISampler;
iridescenceTexture?: ANARISampler;
iridescenceThicknessTexture?: ANARISampler;
anisotropyTexture?: ANARISampler;
};

Core material factors

ParameterDefaultMeaning
baseColor, color[0.8, 0.8, 0.8]Linear RGB/RGBA base color; baseColor takes precedence.
metallic0Metallic factor; matte materials always use zero.
roughness0.38 physically based; 0.92 matteSurface roughness.
emissive, emissiveStrength[0, 0, 0], 1Linear emitted color and intensity.
normalScale, occlusionStrength1, 1Normal-map and occlusion-map multipliers.
opacityBase-color alpha, otherwise 1Explicit opacity overriding the color's alpha component.
alphaModeblend when opacity is below one; otherwise opaqueExplicit opaque, mask, or blend rendering mode.
alphaCutoff0.5Fragment-discard threshold when alphaMode is mask.
doubleSidedtrueWhether both triangle faces are rendered.
unlitfalseWhether the canonical material bypasses lighting.

Extension material factors

ParametersMeaning
specularColor, specularIntensityDielectric specular color and strength.
clearcoat, clearcoatRoughnessSecondary surface coating and coating roughness.
transmission, thicknessScreen-space transmission strength and medium thickness.
dispersionNonnegative chromatic transmission spread using the ratified glTF 20/Abbe-number parameterization; defaults to zero.
attenuationColor, attenuationDistance, indexOfRefractionTransmitted-light tint, attenuation distance, and IOR.
sheenColor, sheenRoughnessCloth-like sheen response.
iridescence, iridescenceIndexOfRefractionThin-film iridescence strength and film IOR.
iridescenceThicknessMinimum, iridescenceThicknessMaximumAuthored iridescent film thickness range.
anisotropyStrength, anisotropyRotation, anisotropyDirectionDirectional highlight response.

When a retained material has nonzero transmission, ANARI's shared experimental SceneRenderer automatically captures opaque scene color and samples it for screen-space refraction. Thickness, attenuation, index of refraction, chromatic dispersion, and roughness shape the transmitted result. Opaque radiance is captured in linear HDR when supported, then exposed and tone-mapped only after the physical material response. This is a single opaque-scene capture, not ray tracing or arbitrary layered refraction. ANARI inherits this behavior from the shared renderer and does not implement a separate transmission pass.

Supported image maps

Every retained image sampler maps to its existing canonical PBR texture binding:

Material parameterTexture contentsColor space
baseColorTextureBase color and optional alpha.sRGB
metallicRoughnessTextureRoughness in green; metallic in blue.Linear
normalTextureTangent-space surface normals.Linear
occlusionTextureAmbient-occlusion data.Linear
emissiveTextureEmitted color.sRGB
specularColorTextureDielectric specular color.sRGB
specularIntensityTextureDielectric specular intensity.Linear
transmissionTextureTransmission factor.Linear
thicknessTextureVolume thickness.Linear
clearcoatTextureClearcoat intensity.Linear
clearcoatRoughnessTextureClearcoat roughness.Linear
clearcoatNormalTextureClearcoat tangent-space normals.Linear
sheenColorTextureSheen color.sRGB
sheenRoughnessTextureSheen roughness.Linear
iridescenceTextureIridescence strength.Linear
iridescenceThicknessTextureThin-film thickness.Linear
anisotropyTextureAnisotropy direction and strength.Linear

Color textures should be uploaded with an sRGB format; data textures should use a linear format. Avoid applying an additional shader-side sRGB conversion to textures already decoded by hardware.

Samplers, UV transforms, and secondary coordinates

const image = graphicsDevice.createTexture({
width: 256,
height: 256,
format: 'rgba8unorm-srgb',
sampler: {
addressModeU: 'repeat',
addressModeV: 'mirror-repeat',
minFilter: 'linear',
magFilter: 'linear',
mipmapFilter: 'linear'
},
data: imageData
});

const imageSampler = anariDevice.newSampler('image2D', {
image,
textureCoordinateSet: 1,
transform: [1, 0, 0, 0, 1, 0, 0.25, 0, 1]
});

material.setParameter('baseColorTexture', imageSampler).commitParameters();

Addressing and filtering belong to the underlying luma.gl Texture. The retained ANARI sampler adds a column-major 3×3 transform and selects 0 or 1, corresponding to geometry 'vertex.attribute1' / TEXCOORD_0 or 'vertex.attribute2' / TEXCOORD_1.

The showcase glTF importer reuses @luma.gl/gltf helpers to retain authored wrap modes, nearest/linear filters, mipmapping, slot-specific UV transforms, and source color-space choices.

Dynamic material updates

material
.setParameters({alphaMode: 'mask', alphaCutoff: 0.35, doubleSided: false})
.commitParameters();

frame.render();

Committed uniform changes update the shared cached material. Structural changes, including alpha mode and face-culling changes, select the appropriate shared renderer pipeline on later renders. Emission affects a surface's appearance but does not automatically illuminate surrounding objects; add a separate light when that behavior is needed.

Image-based lighting

An ANARI renderer can use existing, caller-owned image-based lighting textures:

const renderer = anariDevice.newRenderer('default', {
environment: {
diffuseTexture,
specularTexture,
brdfLUTTexture,
intensity: 1,
rotation: Math.PI / 4
}
});

Supply the complete diffuse/specular/BRDF texture set to enable the existing shared environment shader. ANARI forwards these resources to the experimental SceneRenderer; it does not generate cubemaps or implement its own environment shader. Existing prefiltered source textures can be loaded with @luma.gl/gltf's loadPBREnvironment() helper, or generated from an equirectangular source through the shared PBREnvironmentGenerator.

ANARILight

const light = anariDevice.newLight('spot', {
position: [0, 5, 3],
direction: [0, -1, -0.5],
color: [0.8, 0.9, 1],
intensity: 24,
openingAngle: Math.PI / 5,
falloffAngle: Math.PI / 8
});

The supported light subtypes are ambient, directional, point, and spot.

type ANARILightParameters = {
color?: ANARIVector3;
direction?: ANARIVector3;
position?: ANARIVector3;
intensity?: number;
irradiance?: number;
radiance?: number;
openingAngle?: number;
falloffAngle?: number;
};
ParameterUsed byMeaning
colorAll lightsLinear RGB light color; defaults to [1, 1, 1].
directiondirectional, spotWorld-space light direction.
positionpoint, spotWorld-space light position.
intensityAll lightsGeneral strength fallback.
irradiancedirectionalDirectional strength; overrides intensity.
radianceambientAmbient strength; overrides intensity.
openingAnglespotOuter cone angle in radians; defaults to 0.5.
falloffAnglespotInner cone angle in radians; defaults to openingAngle * 0.7.

glTF showcase import reuses parseGLTFLights(gltf, {useByteColors: false}), preserving authored world transforms, linear light color, intensity, and both spotlight cone angles.

Lights attached to instanced groups are collected, but group instance transforms are not applied to their positions or directions; specify world-space light parameters. As with other retained objects, changed light parameters become visible after commitParameters().