Class MaterialPropertyBlock<T>

MaterialPropertyBlock allows per-object material property overrides without creating new material instances. This is useful for rendering multiple objects with the same base material but different properties (e.g., different colors, textures, or shader parameters).

Important: Overrides are registered on the Object3D, not on the material. This means:

  • If you change the object's material, the overrides will still be applied to the new material
  • Multiple objects can share the same material but have different property overrides
  • If you don't want overrides applied after changing a material, you must remove them using removeOveride, clearAllOverrides, or dispose

The property block system works by:

  • Temporarily applying overrides in onBeforeRender
  • Restoring original values in onAfterRender
  • Managing shader defines and program cache keys for correct shader compilation
  • Supporting texture coordinate transforms per object
  • Lightmaps: Apply unique lightmap textures to individual objects sharing the same material
  • Reflection Probes: Apply different environment maps per object for localized reflections
  • See-through effects: Temporarily override transparency/transmission properties for X-ray effects

Important: Do not use the constructor directly. Instead, use the static MaterialPropertyBlock.get method:

const block = MaterialPropertyBlock.get(myMesh);

This method will either return an existing property block or create a new one if it doesn't exist. It automatically:

  • Creates the property block instance
  • Registers it in the internal registry
  • Attaches the necessary render callbacks to the object
  • Handles Groups by applying overrides to all child meshes
// Get or create a property block for an object
const block = MaterialPropertyBlock.get(myMesh);

// Override the color property
block.setOverride("color", new Color(1, 0, 0));

// Override a texture with custom UV transform (useful for lightmaps)
block.setOverride("lightMap", myLightmapTexture, {
offset: new Vector2(0.5, 0.5),
repeat: new Vector2(2, 2)
});

// Set a shader define
block.setDefine("USE_CUSTOM_FEATURE", 1);
const mesh = new Mesh(geometry, materialA);
const block = MaterialPropertyBlock.get(mesh);
block.setOverride("color", new Color(1, 0, 0));

// The color override is red for materialA

// Swap the material - overrides persist and apply to the new material!
mesh.material = materialB;
// The color override is now red for materialB too

// If you don't want overrides on the new material, remove them:
block.clearAllOverrides(); // Remove all overrides
// or
block.removeOveride("color"); // Remove specific override
// or
block.dispose(); // Remove the entire property block
const block = MaterialPropertyBlock.get(mesh);
block.setOverride("lightMap", lightmapTexture);
block.setOverride("lightMapIntensity", 1.5);
const block = MaterialPropertyBlock.get(mesh);
block.setOverride("transparent", true);
block.setOverride("opacity", 0.3);

Type Parameters

  • T extends Material = Material

    The material type this property block is associated with

Constructors

Accessors

  • get object(): null | Object3D<Object3DEventMap>

    The object this property block is attached to

    Returns null | Object3D<Object3DEventMap>

  • get overrides(): readonly PropertyBlockOverride<MaterialPropertyType>[]

    Gets all property overrides as a readonly array

    Returns readonly PropertyBlockOverride<MaterialPropertyType>[]

    Array of all property overrides

Methods

  • Removes all property overrides from this block. After calling this, the material will use its original values for all properties.

    Note: This does NOT remove shader defines. Use clearDefine or dispose for that.

    Returns void

    const block = MaterialPropertyBlock.get(mesh);

    // Set multiple overrides
    block.setOverride("color", new Color(1, 0, 0));
    block.setOverride("roughness", 0.5);
    block.setOverride("lightMap", lightmapTexture);

    // Later, remove all overrides at once
    block.clearAllOverrides();

    // The material now uses its original values
    // The property block still exists and can be reused with new overrides
    const block = MaterialPropertyBlock.get(mesh);

    // Save current overrides if you want to restore them later
    const savedOverrides = [...block.overrides];

    // Clear all overrides temporarily
    block.clearAllOverrides();

    // Do some rendering without overrides...

    // Restore overrides
    savedOverrides.forEach(override => {
    block.setOverride(override.name, override.value, override.textureTransform);
    });
    • removeOveride - To remove a single override
    • dispose - To completely remove the property block and clean up resources
  • Remove a shader define

    Parameters

    • name: string

      The define name to remove

    Returns void

  • Disposes this property block and cleans up associated resources. After calling dispose, this property block should not be used.

    Returns void

  • Get all defines set on this property block

    Returns Readonly<Record<string, string | number | boolean>>

    A readonly record of all defines

  • Gets the override for a specific property with type-safe value inference

    Type Parameters

    • K extends string | number | symbol

    Parameters

    • name: K

      The property name to get

    Returns undefined | PropertyBlockOverride<T[K] & MaterialPropertyType>

    The PropertyBlockOverride with correctly typed value if it exists, undefined otherwise

    const block = MaterialPropertyBlock.get<MeshStandardMaterial>(mesh);

    // Value is inferred as number | undefined
    const roughness = block.getOverride("roughness")?.value;

    // Value is inferred as Color | undefined
    const color = block.getOverride("color")?.value;

    // Value is inferred as Texture | null | undefined
    const map = block.getOverride("map")?.value;

    // Explicitly specify the type for properties not on the base material type
    const transmission = block.getOverride<number>("transmission")?.value;

    // Or use a more specific material type
    const physicalBlock = block as MaterialPropertyBlock<MeshPhysicalMaterial>;
    const transmissionTyped = physicalBlock.getOverride("transmission")?.value; // number
  • Gets the override for a specific property with type-safe value inference

    Type Parameters

    • V extends MaterialPropertyType = MaterialPropertyType

    Parameters

    • name: string

      The property name to get

    Returns undefined | PropertyBlockOverride<V>

    The PropertyBlockOverride with correctly typed value if it exists, undefined otherwise

    const block = MaterialPropertyBlock.get<MeshStandardMaterial>(mesh);

    // Value is inferred as number | undefined
    const roughness = block.getOverride("roughness")?.value;

    // Value is inferred as Color | undefined
    const color = block.getOverride("color")?.value;

    // Value is inferred as Texture | null | undefined
    const map = block.getOverride("map")?.value;

    // Explicitly specify the type for properties not on the base material type
    const transmission = block.getOverride<number>("transmission")?.value;

    // Or use a more specific material type
    const physicalBlock = block as MaterialPropertyBlock<MeshPhysicalMaterial>;
    const transmissionTyped = physicalBlock.getOverride("transmission")?.value; // number
  • Checks if this property block has any overrides

    Returns boolean

    True if there are any overrides set

  • Removes a specific property override. After removal, the material will use its original property value for this property.

    Type Parameters

    • K extends string | number | symbol

    Parameters

    • name: K | {} & string

      The property name to remove the override for

    Returns void

    const block = MaterialPropertyBlock.get(mesh);

    // Set some overrides
    block.setOverride("color", new Color(1, 0, 0));
    block.setOverride("roughness", 0.5);
    block.setOverride("lightMap", lightmapTexture);

    // Remove a specific override - the material will now use its original color
    block.removeOveride("color");

    // Other overrides (roughness, lightMap) remain active
  • Set a shader define that will be included in the program cache key. This allows different objects sharing the same material to have different shader programs.

    Defines affect shader compilation and are useful for enabling/disabling features per-object.

    Parameters

    • name: string

      The define name (e.g., "USE_LIGHTMAP", "ENABLE_REFLECTIONS")

    • value: string | number | boolean

      The define value (typically a boolean, number, or string)

    Returns void

    // Enable a feature for this specific object
    block.setDefine("USE_CUSTOM_SHADER", true);
    block.setDefine("QUALITY_LEVEL", 2);
  • Sets or updates a material property override. The override will be applied to the material during rendering.

    Type Parameters

    • K extends string | number | symbol

    Parameters

    • name: K

      The name of the material property to override (e.g., "color", "map", "roughness")

    • value: T[K]

      The value to set

    • OptionaltextureTransform: TextureTransform

      Optional UV transform (only used when value is a Texture)

    Returns void

    // Override a simple property
    block.setOverride("roughness", 0.8);

    // Override a color
    block.setOverride("color", new Color(0xff0000));

    // Override a texture with UV transform
    block.setOverride("map", texture, {
    offset: new Vector2(0, 0),
    repeat: new Vector2(2, 2)
    });
  • Sets or updates a material property override. The override will be applied to the material during rendering.

    Parameters

    • name: string

      The name of the material property to override (e.g., "color", "map", "roughness")

    • value: MaterialPropertyType

      The value to set

    • OptionaltextureTransform: TextureTransform

      Optional UV transform (only used when value is a Texture)

    Returns void

    // Override a simple property
    block.setOverride("roughness", 0.8);

    // Override a color
    block.setOverride("color", new Color(0xff0000));

    // Override a texture with UV transform
    block.setOverride("map", texture, {
    offset: new Vector2(0, 0),
    repeat: new Vector2(2, 2)
    });
  • Gets or creates a MaterialPropertyBlock for the given object. This is the recommended way to obtain a property block instance.

    Type Parameters

    Parameters

    • object: Object3D

      The object to get/create a property block for

    Returns MaterialPropertyBlock<T>

    The MaterialPropertyBlock associated with this object

    const block = MaterialPropertyBlock.get(myMesh);
    block.setOverride("roughness", 0.5);
  • Checks if an object has any property overrides

    Parameters

    Returns boolean

    True if the object has a property block with overrides