Optional ReadonlyanisotropyRuntime anisotropy controls; present only when the material was built with an anisotropy
group
Optional ReadonlyclearcoatRuntime clearcoat controls; present only when the material was built with a clearcoat group
AdvancedcolorThe colour space this material's shader works in; see ColorSpace
'display' takes effect only on an unlit material, in a view with toneMapping: 'none' and no
enabled 'beforeToneMapping' effect, on a mesh no fog or vertex colours reach. Anywhere else
the shader works in linear light. To change it after the material has rendered, see
BaseMaterial3D.
Bits on a 'display' material should read colours through these helpers, which exist in both
shader stages and return the colour in the shader's space:
decodeColor(c: vec3): a display colour, such as a texture sample.inputTint(linearTint: vec4, displayTint: vec4): pass material.baseColor and
material.displayBaseColor, which the material fills once a bit declares them in
bindings.material.decodeFrame(c: vec3): a colour from a frame this view drew, such as a render-texture feed.Multiplying colours read this way gives the same bytes in both spaces. Adding, blending or
scaling them by a number doesn't, so the result changes when fog moves the shader to linear
light. On the display path, a SceneOutput bit that reads albedo sees display colours.
The values the material's shader reads, one property per field its bits declare; see MaterialData for how they read and write
Whether destroy() has run
ReadonlydoubleWhether back faces are drawn too, lit with their normal flipped; set by the doubleSided option
Optional ReadonlyemissiveRuntime glow controls; present only when the material was built with an emissive group
Readonly AdvancedextraThe shader bits this material was built with on top of its own, from the extraBits option
Fixed for the material's lifetime. BaseMaterial3D#clone makes a copy with more.
ReadonlyflatWhether triangles are shaded with their face normal; set by the flatShading option
ReadonlyfogOptional ReadonlyiridescenceRuntime iridescence controls; present only when the material was built with an iridescence
group
OptionallabelName for debugging and for finding the material, such as the glTF material name the loader gives it; a Model3DOptions#materials record matches it
Whether the material's shader does lighting
Set it to false for a shader that does none, as FlatMaterial does. That leaves out
calculateShadow, so a shader that calls it fails to compile. To change it after the material
has rendered, see BaseMaterial3D.
Optional ReadonlysheenRuntime sheen controls; present only when the material was built with a sheen group
Optional ReadonlyspecularRuntime specular controls; present only when the material was built with a specular group
Render state (blending, depth, culling) for every draw with this material
alphaMode and doubleSided set parts of it. To change a field after the material has
rendered, see BaseMaterial3D. polygonOffset works on WebGL only; WebGPU ignores it.
The material's textures by slot name, the same names the textures option takes
Assigning swaps the slot, and a name the material doesn't have throws. A swap reuses the
compiled shader, except that a real map in the normal slot, or the default put back, switches
normal mapping on or off.
Wrap mode, filtering and anisotropy come from each texture's source.style, which clamps by
default. To tile a texture, set texture.source.style.addressMode = 'repeat', then call
style.update().
Optional ReadonlytopologyPrimitive topology for every pass that doesn't set its own; set by the topology option, and PassDescriptor lists what overrides it
Optional ReadonlytransmissionRuntime transmission controls; present only when the material was built with a transmission
group
AdvanceduidUnique id for this material instance
Whether a geometry's vertex colours (its colors) tint this material
Off by default, since exporters often fill the colour set with masks or weights; put data that
isn't colour in colors1 when you can. The glTF loader turns
it on, as glTF's COLOR_0 is a base colour multiplier in linear light; convert colours picked
in sRGB with srgbToLinear. To change it after the material has rendered, see
BaseMaterial3D.
Sets the base opacity
From 0 (transparent) to 1 (opaque)
Alpha below which fragments are discarded while BaseMaterial3D#alphaMode is 'mask'
Sets the alpha cutoff
Alpha below which fragments are discarded
How the material treats alpha; see AlphaMode
Setting it also sets the blending and depth writes of state. 'blend' turns depth writes
off, and its meshes cast no shadow. On a material built from a raw descriptor, 'mask'
discards only if the descriptor's bits include alphaMaskBit.
Base colour tint, read back as a hex number
Takes any ColorSource in display (sRGB) space, like Container.tint. The source's alpha is
ignored; BaseMaterial3D#alpha is the opacity.
Sets the base colour tint
Display colour; its alpha is ignored
Sets the index of refraction
Refractive index; 1.5 suits most glass and plastic
Sets the metalness
Metalness, 0 to 1
Sets the strength of the normal map's bumps
Bump strength
Sets the multiplier on the occlusion
Multiplier on the occlusion
Sets the perceptual roughness
Roughness, 0 to 1
The UV transform you set, or undefined while the base colour texture's frame sets it
One transform, as glTF's KHR_texture_transform defines it, applies to every texture of the
material. Setting a matrix takes over from a framed (spritesheet) base colour texture, and a
framed texture assigned while it's set warns that its frame is ignored; setting undefined
hands it back. Either is a data write, never a shader rebuild. On a material whose bits lack
uvTransformBit, setting a matrix warns and does nothing.
A UV (u, v) becomes (a * u + b * v + tx, c * u + d * v + ty), transposed from pixi's
Matrix.apply, so new Matrix().rotate(rotation).scale(sx, sy).translate(x, y) gives the
KHR_texture_transform result for those values. The getter returns the material's own matrix;
changing it in place does nothing until you assign it again.
Sets the UV transform
The transform, or undefined to follow the base colour texture's frame
StaticEMPTYAdvanced
A shared material with no shader, which a Mesh3D holds until it's given a material
A mesh on it draws nothing and compiles no shader, though its skeleton and morph targets still
upload. Assign it to a mesh's material to stop the mesh drawing; to hide a mesh for a
while, visible = false is cheaper. Don't give it to a BatchedMesh3D slot that's in a
pass, even a hidden one: such a slot needs a real material.
Every waiting mesh shares it, so don't edit it. Its destroy does nothing, as with pixi's
Texture.EMPTY.
Makes a material of the same class that draws as this one does now, with the options you pass changed
options are the class's constructor options. clone reads this material's current values
back as those options, merges yours over them, and passes the result to the class's
constructor. An option left out, or set to undefined, keeps this material's value. One that
takes an object, such as a feature group or passes, is merged one level deep:
emissive: { strength: 2 } on a Material3D keeps its emissive colour. descriptor is
replaced whole. A group the material doesn't have, such as clearcoat, adds the feature.
extraBits adds to this material's BaseMaterial3D#extraBits, skipping a bit it already
has. Fields a new bit declares start at 0 and its texture slots hold Texture.WHITE, so set
them on the copy. The fields of the extra bits it already had keep their values.
A raw-descriptor material, or any class that inherits BaseMaterial3D's _toOptions
unchanged, keeps every field value and texture it has, except those an option you pass sets.
What isn't an option comes across too: colorSpace, lit, the passes joined with
BaseMaterial3D#enablePass, and state with any change made through it, except the
flags an option you pass sets, such as alphaMode's blending. Colour options read back as
8-bit hex, as their getters return them.
Textures are shared, not copied. Everything else belongs to the copy: assign it to meshes and
destroy() it when you're done, which leaves the shared textures alive. Materials with the same
bits share compiled shaders, so a copy compiles nothing new unless its bits are new.
Optionaloptions: Material3DOptions
Constructor options to change on the copy; left out, it's a plain copy.
The copy, of the same class.
Frees the material for good
Its textures stay alive unless options asks for them. Calling it again does nothing.
Optionaloptions: TypeOrBool<TextureDestroyOptions>
Whether to destroy the textures too, as BaseMaterial3D#destroy takes them
Removes this material from a custom render pass
Meshes using the material leave the pass on the next render, except one that joined it through
Mesh3D#enablePass. An override given for the pass in the passes option is kept, so
BaseMaterial3D#enablePass brings it back.
The pass's name, such as 'outline'.
Adds this material to a custom render pass, such as an OutlinePass, as naming it true
in the passes option does
Meshes using the material draw in the pass from the next render, except one that left it through Mesh3D#disablePass. BatchedMesh3D slots take their passes from BatchedMesh3D#setPassesAt instead. Overrides for the pass can only be given at construction, and the passes option has the limit on custom pass names.
The pass's name, such as 'outline'.
Advanced
The shader descriptor for a view, cached per kind of environment
View whose environment picks the descriptor
Frees the GPU memory of this material's textures until a frame draws them again
The next frame that draws the material re-uploads them from their CPU copies, so it keeps
drawing the same. Texture sources are shared, so every other material using one re-uploads it
too, as with texture.source.unload(). The engine's default textures are skipped, and so are
render textures and ContainerTextures, whose pixels exist only on the GPU.
Call BatchedMesh3D#invalidate for each batch slot that draws the material. Does nothing once the material is destroyed.
view.root.removeChild(model);
material.unload(); // hand the texture memory back until the model is shown again
Model3D.unload For giving back a whole model's geometry and textures at once.
The standard physically based (PBR) material
Base colour, metalness and roughness, with normal, occlusion and emissive maps, plus the glTF extensions for specular, iridescence, transmission and volume, clearcoat, sheen and anisotropy. glTF materials load into it, except unlit ones, which load as FlatMaterial.
Each extension is an option group, and passing one gives the material a runtime object of the same name:
new Material3D({ clearcoat: { roughness: 0.2 } })givesmaterial.clearcoat.roughness. Writing to it, or to a core value such asroughness, never recompiles the shader.The groups passed to the constructor fix the material's features for good. A group left out costs nothing, while a feature turned off at runtime, such as a coat at factor 0, keeps its cost. To add a feature to a material that exists, such as one the glTF loader built,
material.clone({ clearcoat: { factor: 1 } })(BaseMaterial3D#clone) makes a copy with it and everything else the material has.Custom shader code in BaseMaterial3DOptions#extraBits runs after the features in each slot, and in the
materialslot before the'mask'cutoff, so it sees the finalalbedoandalpha, and alpha it writes there still reaches the cutoff. Like the groups, it's fixed when the material is built, andclone({ extraBits })makes a copy with more.Example