A material that works with custom Metal shader functions.
Custom, or programmable, materials allow you to leverage RealityKit’s
existing shader pipeline to render physically based or unlit materials that
support custom Metal shader functions. These functions modify how RealityKit
renders an entity. Custom materials support two different types of custom
Metal shader functions: geometry modifiers and surface shaders.
Use a _surface shader _to calculate or specify all the material attributes
that RealityKit uses to render your entity, such as
``CustomMaterial/baseColor-swift.property``,
``CustomMaterial/normal-swift.property``, and
``CustomMaterial/roughness-swift.property``. A _geometry modifier_ can
offset the position of an entity’s vertices to change the size and shape of
an entity. It can also change other per-vertex data, such as vertex color
and UV texture coordinates, which define how RealityKit maps textures on to
the model.
- Important: For the Metal API documentation for custom material shader
functions, see [the Metal RealityKit APIs PDF](https://developer.apple.com/metal/Metal-RealityKit-APIs.pdf).
For more information on creating custom materials and writing shader
functions, see <doc:modifying-realitykit-rendering-using-custom-materials>.
Members (47)
get · iOS 18.0+
readsDepth
TypeScript
get readsDepth(): boolean
Swift declaration
var readsDepth: Bool { get set }
A boolean value that determines whether this material performs the depth test by reading RealityKit's depth buffer.
If true, meshes with this material will depth test each of their fragments when being rendered.
If an object that writes depth is in front of this material, this material will be hidden.
If false, meshes with this material will ignore the depth test, and always render all of their
fragments during their draw call, regardless of the positioning of other objects in the scene.
Note that other objects may still render on top of this material, depending on draw order.
The default value is true.
set · iOS 18.0+
readsDepth
TypeScript
set readsDepth(value: boolean)
Swift declaration
var readsDepth: Bool { get set }
A boolean value that determines whether this material performs the depth test by reading RealityKit's depth buffer.
If true, meshes with this material will depth test each of their fragments when being rendered.
If an object that writes depth is in front of this material, this material will be hidden.
If false, meshes with this material will ignore the depth test, and always render all of their
fragments during their draw call, regardless of the positioning of other objects in the scene.
Note that other objects may still render on top of this material, depending on draw order.
The default value is true.
get · iOS 15.0+
faceCulling
TypeScript
get faceCulling(): MaterialParameterTypes_FaceCulling
Swift declaration
var faceCulling: CustomMaterial.FaceCulling { get set }
A process in which the system specifies polygons to remove before
rendering a mesh using this material.
To improve performance, RealityKit culls polygons, or _faces_, that it
determines won’t be visible. Discarding faces that aren’t part of the
final render eliminates the need to do any calculations for those
faces.
RealityKit recognizes when a face aims toward the camera (a _front
face_) or away from the camera (a _back face_). This value controls the
type of faces RealityKit culls.
The default for this value is
``MaterialParameterTypes/FaceCulling/back``, which means RealityKit
removes faces that point away from the camera. Because back faces point
away from the camera and are usually obscured by front-facing polygons,
the user typically won’t see them. As a result, in most cases, the
default setting is desirable because it culls polygons that don’t
contribute to the rendered scene.
You can change the culling behavior to cull front faces instead or to
turn off face culling altogether, but be aware that turning off face
culling results in less efficient rendering and may negatively impact
your app’s frame rate.
set · iOS 15.0+
faceCulling
TypeScript
set faceCulling(value: MaterialParameterTypes_FaceCulling)
Swift declaration
var faceCulling: CustomMaterial.FaceCulling { get set }
A process in which the system specifies polygons to remove before
rendering a mesh using this material.
To improve performance, RealityKit culls polygons, or _faces_, that it
determines won’t be visible. Discarding faces that aren’t part of the
final render eliminates the need to do any calculations for those
faces.
RealityKit recognizes when a face aims toward the camera (a _front
face_) or away from the camera (a _back face_). This value controls the
type of faces RealityKit culls.
The default for this value is
``MaterialParameterTypes/FaceCulling/back``, which means RealityKit
removes faces that point away from the camera. Because back faces point
away from the camera and are usually obscured by front-facing polygons,
the user typically won’t see them. As a result, in most cases, the
default setting is desirable because it culls polygons that don’t
contribute to the rendered scene.
You can change the culling behavior to cull front faces instead or to
turn off face culling altogether, but be aware that turning off face
culling results in less efficient rendering and may negatively impact
your app’s frame rate.
get · iOS 18.0+
writesDepth
TypeScript
get writesDepth(): boolean
Swift declaration
var writesDepth: Bool { get set }
A boolean value that determines whether this material writes its depth into RealityKit's depth buffer.
If true, meshes with this material will occlude objects behind them by writing their depth
into RealityKit's depth buffer.
If false, meshes with this material will not write their depth into
RealityKit's depth buffer, and may be overwritten by objects drawn behind them, depending on
draw order.
The default value is true.
set · iOS 18.0+
writesDepth
TypeScript
set writesDepth(value: boolean)
Swift declaration
var writesDepth: Bool { get set }
A boolean value that determines whether this material writes its depth into RealityKit's depth buffer.
If true, meshes with this material will occlude objects behind them by writing their depth
into RealityKit's depth buffer.
If false, meshes with this material will not write their depth into
RealityKit's depth buffer, and may be overwritten by objects drawn behind them, depending on
draw order.
The default value is true.
get · iOS 15.0+
emissiveColor
TypeScript
get emissiveColor(): CustomMaterial_EmissiveColor
Swift declaration
var emissiveColor: CustomMaterial.EmissiveColor { get set }
The color of light this material emits.
With physically based rendering (PBR), you can give entities in
RealityKit the appearance of emitting light. Use this property to
simulate real-world objects that glow, such as objects with LEDs or
computer screens. To enable light emission from a material, set
``PhysicallyBasedMaterial/emissiveIntensity`` to a value greater than
zero, then specify a color (other than black) using this property. You
can specify a single emissive color for the entire material, or use a
UV-mapped image texture to use different colors for different parts of
the entity.
With custom materials, RealityKit doesn’t use
``CustomMaterial/emissiveColor-swift.property`` automatically to render
your entity.
Call `params.surface().set_emissive_color()` from your surface shader,
otherwise RealityKit renders no light emission.
The following example assigns a tint color to the
``PhysicallyBasedMaterial/emissiveColor-swift.property`` property,
without a texture:
```swift
self.emissiveColor = PhysicallyBasedMaterial.EmissiveColor(color: .red)
```
This next example uses a texture to specify the
``PhysicallyBasedMaterial/emissiveColor-swift.property`` property:
```swift
if let emissiveResource = try? TextureResource.load(named: "entity_emissive") {
let emissiveMap = MaterialParameters.Texture(emissiveResource)
material.emissiveColor = .init(texture: emissiveMap)
}
```
This Metal code shows how to access the emissive color tint in your
shader functions:
```cpp
half3 emissiveTint = (half3)params.material_constants().emissive_color();
```
The following Metal code demonstrates how to sample the emissive color
texture for the current fragment:
```cpp
// Get the entity's primary texture coordinates.
float2 uv = params.geometry().uv0();
// Flip the y-axis. You only need to do this for entities you load from
// USDZ or .reality files.
uv.y = 1.0 - uv.y;
// Sample the emissive color texture to get the value for this fragment.
auto tex = params.textures();
half3 emissiveColor = (half3)tex.emissive_color()
.sample(textureSampler, uv).rgb;
```
set · iOS 15.0+
emissiveColor
TypeScript
set emissiveColor(value: CustomMaterial_EmissiveColor)
Swift declaration
var emissiveColor: CustomMaterial.EmissiveColor { get set }
The color of light this material emits.
With physically based rendering (PBR), you can give entities in
RealityKit the appearance of emitting light. Use this property to
simulate real-world objects that glow, such as objects with LEDs or
computer screens. To enable light emission from a material, set
``PhysicallyBasedMaterial/emissiveIntensity`` to a value greater than
zero, then specify a color (other than black) using this property. You
can specify a single emissive color for the entire material, or use a
UV-mapped image texture to use different colors for different parts of
the entity.
With custom materials, RealityKit doesn’t use
``CustomMaterial/emissiveColor-swift.property`` automatically to render
your entity.
Call `params.surface().set_emissive_color()` from your surface shader,
otherwise RealityKit renders no light emission.
The following example assigns a tint color to the
``PhysicallyBasedMaterial/emissiveColor-swift.property`` property,
without a texture:
```swift
self.emissiveColor = PhysicallyBasedMaterial.EmissiveColor(color: .red)
```
This next example uses a texture to specify the
``PhysicallyBasedMaterial/emissiveColor-swift.property`` property:
```swift
if let emissiveResource = try? TextureResource.load(named: "entity_emissive") {
let emissiveMap = MaterialParameters.Texture(emissiveResource)
material.emissiveColor = .init(texture: emissiveMap)
}
```
This Metal code shows how to access the emissive color tint in your
shader functions:
```cpp
half3 emissiveTint = (half3)params.material_constants().emissive_color();
```
The following Metal code demonstrates how to sample the emissive color
texture for the current fragment:
```cpp
// Get the entity's primary texture coordinates.
float2 uv = params.geometry().uv0();
// Flip the y-axis. You only need to do this for entities you load from
// USDZ or .reality files.
uv.y = 1.0 - uv.y;
// Sample the emissive color texture to get the value for this fragment.
auto tex = params.textures();
half3 emissiveColor = (half3)tex.emissive_color()
.sample(textureSampler, uv).rgb;
```
get · iOS 15.0+
lightingModel
TypeScript
get lightingModel(): CustomMaterial_LightingModel
Swift declaration
var lightingModel: CustomMaterial.LightingModel { get }
The lighting model that the material uses.
A custom material’s lighting model determines exactly how RealityKit
uses the values set in your surface shader’s to render the entity.
Custom materials supports the following lighting models:
| Lighting Model | Description | Supported Shader Outputs |
|-------------- | ----------- | ------------------------ |
| `.lit` | Uses physically based rendering techniques, but excludes clearcoat. | All except `set_clearcoat()` and `set_clearcoat_roughness()` |
| `.clearcoat` | Uses physically based rendering techniques, including clearcoat. | All |
| `.unlit` | Renders without any shading or lighting calculations. The result is similar to using an ``UnlitMaterial``. | Uses `set_emissive_color()` only |
Creates a custom material from a lighting model, surface shader, and
geometry modifier.
This initializer creates a custom material using a lighting model you
specify, which determines how RealityKit renders the output of your
shader functions. The ``CustomMaterial/LightingModel-swift.enum/lit``
and ``CustomMaterial/LightingModel-swift.enum/clearcoat`` use
RealityKit’s physically-based shaders to render the entity based on the
output of your shader functions. When using these lighting models,
RealityKit uses all provided material attributes like
``CustomMaterial/baseColor-swift.property``,
``CustomMaterial/metallic-swift.property`` and
``CustomMaterial/normal-swift.property``.
The ``CustomMaterial/LightingModel-swift.enum/unlit`` lighting model
renders the entity with no shadows or surface effects. This lighting
model only supports ``CustomMaterial/baseColor-swift.property`` and
``CustomMaterial/blending-swift.property``.
- Parameters:
- surfaceShader: The surface shader function.
- geometryModifier: The geometry modifier shader function.
- lightingModel: The lighting model.
get · iOS 18.0+
clearcoatNormal
TypeScript
get clearcoatNormal(): CustomMaterial_ClearcoatNormal
Swift declaration
var clearcoatNormal: CustomMaterial.ClearcoatNormal { get set }
Waviness and imperfections for the top clearcoat.
An entity in RealityKit can display a clearcoat, which is a separate
layer of transparent specular highlights used to simulate a clear
coating, like on a car or the surface of lacquered objects. This
property allows you to specify a clearcoat normal and add
waviness and imperfections to the top clearcoat.
This example shows how to set the `clearcoatNormal` using a UV-mapped
image:
```swift
if let clearcoatNormalTextureResource = try?
TextureResource.load(named: "entity_cc_normalMap") {
let ccNormalMap = CustomMaterial.Texture(clearcoatNormalTextureResource)
material.clearcoatNormal = .init(texture: ccNormalMap)
}
```
With custom materials, RealityKit only renders a clearcoat if
``CustomMaterial/lightingModel-swift.property`` is
``CustomMaterial/LightingModel-swift.enum/clearcoat`` and the material’s
surface shader function calls `params.surface().set_clearcoat()`.
To specify ``CustomMaterial/clearcoatNormal-swift.property``,
your surface shader function also needs to call
`params.surface().set_clearcoat_normal()`.
The following Metal code demonstrates using
``CustomMaterial/clearcoat-swift.property`` and
``CustomMaterial/clearcoatNormal-swift.property`` in a surface
shader, replicating the behavior of the ``PhysicallyBasedMaterial``
shader:
```cpp
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from a USDZ or .reality file use texture coordinates with
// a flipped y-axis. This compensates for that.
uv.y = 1.0 - uv.y;
// Sample a value from the clearcoat normal texture.
auto tex = params.textures();
half3 clearcoatNormal = realitykit::unpack_normal(tex.clearcoat_normal().sample(textureSampler, uv).rgb);
// assign the result.
params.surface().set_clearcoat_normal(clearcoatNormal);
params.surface().set_clearcoat(1.0);
```
set · iOS 18.0+
clearcoatNormal
TypeScript
set clearcoatNormal(value: CustomMaterial_ClearcoatNormal)
Swift declaration
var clearcoatNormal: CustomMaterial.ClearcoatNormal { get set }
Waviness and imperfections for the top clearcoat.
An entity in RealityKit can display a clearcoat, which is a separate
layer of transparent specular highlights used to simulate a clear
coating, like on a car or the surface of lacquered objects. This
property allows you to specify a clearcoat normal and add
waviness and imperfections to the top clearcoat.
This example shows how to set the `clearcoatNormal` using a UV-mapped
image:
```swift
if let clearcoatNormalTextureResource = try?
TextureResource.load(named: "entity_cc_normalMap") {
let ccNormalMap = CustomMaterial.Texture(clearcoatNormalTextureResource)
material.clearcoatNormal = .init(texture: ccNormalMap)
}
```
With custom materials, RealityKit only renders a clearcoat if
``CustomMaterial/lightingModel-swift.property`` is
``CustomMaterial/LightingModel-swift.enum/clearcoat`` and the material’s
surface shader function calls `params.surface().set_clearcoat()`.
To specify ``CustomMaterial/clearcoatNormal-swift.property``,
your surface shader function also needs to call
`params.surface().set_clearcoat_normal()`.
The following Metal code demonstrates using
``CustomMaterial/clearcoat-swift.property`` and
``CustomMaterial/clearcoatNormal-swift.property`` in a surface
shader, replicating the behavior of the ``PhysicallyBasedMaterial``
shader:
```cpp
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from a USDZ or .reality file use texture coordinates with
// a flipped y-axis. This compensates for that.
uv.y = 1.0 - uv.y;
// Sample a value from the clearcoat normal texture.
auto tex = params.textures();
half3 clearcoatNormal = realitykit::unpack_normal(tex.clearcoat_normal().sample(textureSampler, uv).rgb);
// assign the result.
params.surface().set_clearcoat_normal(clearcoatNormal);
params.surface().set_clearcoat(1.0);
```
get · iOS 15.0+
ambientOcclusion
TypeScript
get ambientOcclusion(): CustomMaterial_AmbientOcclusion
Swift declaration
var ambientOcclusion: CustomMaterial.AmbientOcclusion { get set }
The ambient light exposure for a material.
Ambient occlusion (AO) represents the entity’s exposure to ambient
light. Specify ambient occlusion using a UV-mapped image called an
_ambient occlusion map_. In an AO map, black pixels represent parts of
the model that receive no ambient light because of a crevice, dent, or
recessed area, or another part of the entity blocking ambient light from
reaching it. White pixels represent flat portions of the model that
receive full ambient light. You generate ambient occlusion maps using a
3D software package.
The following code loads an ambient occlusion map and adds it to the
custom material:
```swift
if let aoResource = try? TextureResource.load(named:"entity_ao") {
let aoMap = MaterialParameters.Texture(aoResource)
material.emissiveColor = .init(texture: aoMap)
}
```
In a custom material, RealityKit doesn’t automatically use the value you
set on this property to render your entity. The ambient occlusion
texture is available in the material’s shader functions, but RealityKit
only renders ambient occlusion if the material’s
``CustomMaterial/lightingModel-swift.property`` is
``CustomMaterial/LightingModel-swift.enum/lit`` or
``CustomMaterial/LightingModel-swift.enum/clearcoat`` and its surface
shader calls `params.surface().set_ambient_occlusion()`.
The following Metal code shows how to sample the ambient occlusion
texture to set the AO value in a surface shader function:
```cpp
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from USDZ or .reality files have texture coordinates
// with a flipped y-axis. This adjusts for that.
uv.y = 1.0 - uv.y;
// Sample the ambient occlusion texture and use it to set the
// ambient occlusion value to use during rendering.
auto tex = params.textures();
half metallic = tex.ambient_occlusion().sample(textureSampler, uv).r;
params.surface().set_ambient_occlusion(metallic);
```
set · iOS 15.0+
ambientOcclusion
TypeScript
set ambientOcclusion(value: CustomMaterial_AmbientOcclusion)
Swift declaration
var ambientOcclusion: CustomMaterial.AmbientOcclusion { get set }
The ambient light exposure for a material.
Ambient occlusion (AO) represents the entity’s exposure to ambient
light. Specify ambient occlusion using a UV-mapped image called an
_ambient occlusion map_. In an AO map, black pixels represent parts of
the model that receive no ambient light because of a crevice, dent, or
recessed area, or another part of the entity blocking ambient light from
reaching it. White pixels represent flat portions of the model that
receive full ambient light. You generate ambient occlusion maps using a
3D software package.
The following code loads an ambient occlusion map and adds it to the
custom material:
```swift
if let aoResource = try? TextureResource.load(named:"entity_ao") {
let aoMap = MaterialParameters.Texture(aoResource)
material.emissiveColor = .init(texture: aoMap)
}
```
In a custom material, RealityKit doesn’t automatically use the value you
set on this property to render your entity. The ambient occlusion
texture is available in the material’s shader functions, but RealityKit
only renders ambient occlusion if the material’s
``CustomMaterial/lightingModel-swift.property`` is
``CustomMaterial/LightingModel-swift.enum/lit`` or
``CustomMaterial/LightingModel-swift.enum/clearcoat`` and its surface
shader calls `params.surface().set_ambient_occlusion()`.
The following Metal code shows how to sample the ambient occlusion
texture to set the AO value in a surface shader function:
```cpp
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from USDZ or .reality files have texture coordinates
// with a flipped y-axis. This adjusts for that.
uv.y = 1.0 - uv.y;
// Sample the ambient occlusion texture and use it to set the
// ambient occlusion value to use during rendering.
auto tex = params.textures();
half metallic = tex.ambient_occlusion().sample(textureSampler, uv).r;
params.surface().set_ambient_occlusion(metallic);
```
get · iOS 15.0+
opacityThreshold
TypeScript
get opacityThreshold(): (number) | null
Swift declaration
var opacityThreshold: Float? { get set }
The minimum opacity value to treat as fully opaque.
In a custom material, `opacityThreshold` helps define how RealityKit
renders transparency when using a texture (known as an _alpha map_) to
control opacity. This property is available as an input to the
material’s surface shader, but RealityKit doesn’t automatically use this
value to render your entity.
To render an entity transparent,
call `params.surface().set_opacity()` from the surface shader.
When `opacityThreshold` is set, ``PhysicallyBasedMaterial``
uses the opacity texture as a mask. RealityKit discards pixels with opacity values less
than the `opacityThreshold`, and renders opacity values greater than or equal to
`opacityThreshold` fully opaque.
The following Metal code replicates the behavior of the
``PhysicallyBasedMaterial`` shaders:
```cpp
// Retrieve the threshold from the CustomMaterial.
float opacityThreshold = params.material_constants().opacity_threshold();
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from USDZ or .reality files use texture coordinates with
// a flipped y-axis. This adjusts for that.
uv.y = 1.0 - uv.y;
// Retrieve the opacity texture from the material.
auto tex = params.textures();
// Sample the value from the opacity texture.
half opacity = tex.opacity().sample(textureSampler, uv).r;
// When the opacity threshold is used, set the opacity to either
// 1.0 or 0.0 depending on the value of the opacity threshold for
// the masking behavior.
opacity = (opacity <= opacityThreshold) ? 0.0 : 1.0;
// Use the calculated value to set the opacity for rendering.
params.surface().set_opacity(opacity);
```
set · iOS 15.0+
opacityThreshold
TypeScript
set opacityThreshold(value: (number) | null)
Swift declaration
var opacityThreshold: Float? { get set }
The minimum opacity value to treat as fully opaque.
In a custom material, `opacityThreshold` helps define how RealityKit
renders transparency when using a texture (known as an _alpha map_) to
control opacity. This property is available as an input to the
material’s surface shader, but RealityKit doesn’t automatically use this
value to render your entity.
To render an entity transparent,
call `params.surface().set_opacity()` from the surface shader.
When `opacityThreshold` is set, ``PhysicallyBasedMaterial``
uses the opacity texture as a mask. RealityKit discards pixels with opacity values less
than the `opacityThreshold`, and renders opacity values greater than or equal to
`opacityThreshold` fully opaque.
The following Metal code replicates the behavior of the
``PhysicallyBasedMaterial`` shaders:
```cpp
// Retrieve the threshold from the CustomMaterial.
float opacityThreshold = params.material_constants().opacity_threshold();
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from USDZ or .reality files use texture coordinates with
// a flipped y-axis. This adjusts for that.
uv.y = 1.0 - uv.y;
// Retrieve the opacity texture from the material.
auto tex = params.textures();
// Sample the value from the opacity texture.
half opacity = tex.opacity().sample(textureSampler, uv).r;
// When the opacity threshold is used, set the opacity to either
// 1.0 or 0.0 depending on the value of the opacity threshold for
// the masking behavior.
opacity = (opacity <= opacityThreshold) ? 0.0 : 1.0;
// Use the calculated value to set the opacity for rendering.
params.surface().set_opacity(opacity);
```
get · iOS 18.0+
triangleFillMode
TypeScript
get triangleFillMode(): MaterialParameterTypes_TriangleFillMode
Swift declaration
var triangleFillMode: CustomMaterial.TriangleFillMode { get set }
The object that controls how RealityKit draws triangles.
A value of ``MaterialParameterTypes/TriangleFillMode/fill`` causes RealityKit
to draw triangles normally, while a value of ``MaterialParameterTypes/TriangleFillMode/lines``
turns on wireframe rendering.
set · iOS 18.0+
triangleFillMode
TypeScript
set triangleFillMode(value: MaterialParameterTypes_TriangleFillMode)
Swift declaration
var triangleFillMode: CustomMaterial.TriangleFillMode { get set }
The object that controls how RealityKit draws triangles.
A value of ``MaterialParameterTypes/TriangleFillMode/fill`` causes RealityKit
to draw triangles normally, while a value of ``MaterialParameterTypes/TriangleFillMode/lines``
turns on wireframe rendering.
get · iOS 15.0+
clearcoatRoughness
TypeScript
get clearcoatRoughness(): CustomMaterial_ClearcoatRoughness
Swift declaration
var clearcoatRoughness: CustomMaterial.ClearcoatRoughness { get set }
The degree to which an entity’s clear, shiny coating scatters light to
create soft highlights.
An entity in RealityKit can display a clearcoat, which is a separate
layer of transparent specular highlights used to simulate a clear
coating, like on a car or the surface of lacquered objects. This
property allows you to specify a clearcoat roughness value to indicate
how much the clearcoat scatters light that bounces off of it, which
softens and disperses the highlights.
You can specify a single value that applies to the entire material, or
you can supply a UV-mapped image texture containing different roughness
values for different parts of the entity. This value is available in
your surface shader. RealityKit won’t render a clearcoat with roughness
unless your surface shader calls both
`params.surface().set_clearcoat_roughness()` and
`params.surface().set_clearcoat()` with a value greater than `0.0`.
The following Swift code demonstrates setting the `clearcoatRoughness`
using a single value:
```swift
material.clearcoatRoughness = .init(floatLiteral: 0.5)
```
This example shows how to set the `clearcoatRoughness` using a UV-mapped
image:
```swift
if let clearcoatRoughnessResource = try?
TextureResource.load(named: "entity_cc_roughness") {
let ccRoughnessMap = MaterialParameters.Texture(clearcoatRoughnessResource)
material.clearcoat = .init(texture: ccRoughnessMap)
}
```
With custom materials, RealityKit only renders a clearcoat if
``CustomMaterial/lightingModel-swift.property`` is
``CustomMaterial/LightingModel-swift.enum/clearcoat`` and the material’s
surface shader function calls `params.surface().set_clearcoat()`.
To specify ``CustomMaterial/clearcoatRoughness-swift.property``,
your surface shader function needs to also call
`params.surface().set_clearcoat_roughness()`.
The following Metal code demonstrates using
``CustomMaterial/clearcoat-swift.property`` and
``CustomMaterial/clearcoatRoughness-swift.property`` in a surface
shader, replicating the behavior of the ``PhysicallyBasedMaterial``
shader:
```cpp
// Retrieve the clearcoat scale and roughness from the CustomMaterial.
float clearcoatScale = params.material_constants().clearcoat_scale();
float clearcoatRoughnessScale = params.material_constants().clearcoat_roughness_scale();
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from a USDZ or .reality file use texture coordinates with
// a flipped y-axis. This compensates for that.
uv.y = 1.0 - uv.y;
// Sample a value from the clearcoat and clearcoat roughness textures.
auto tex = params.textures();
half clearcoat = tex.clearcoat().sample(textureSampler, uv).r;
half clearcoatRoughness = tex.clearcoat_roughness().sample(textureSampler, uv).r;
// Multiply the scale and sampled texture value from the clearcoat and
// assign the result.
clearcoat *= clearcoatScale;
params.surface().set_clearcoat(clearcoat);
// Multiply the scale and sampled texture value from the clearcoat roughness
// and assign the result.
clearcoatRoughness *= clearcoatRoughnessScale;
params.surface().set_clearcoat_roughness(clearcoatRoughness);
```
set · iOS 15.0+
clearcoatRoughness
TypeScript
set clearcoatRoughness(value: CustomMaterial_ClearcoatRoughness)
Swift declaration
var clearcoatRoughness: CustomMaterial.ClearcoatRoughness { get set }
The degree to which an entity’s clear, shiny coating scatters light to
create soft highlights.
An entity in RealityKit can display a clearcoat, which is a separate
layer of transparent specular highlights used to simulate a clear
coating, like on a car or the surface of lacquered objects. This
property allows you to specify a clearcoat roughness value to indicate
how much the clearcoat scatters light that bounces off of it, which
softens and disperses the highlights.
You can specify a single value that applies to the entire material, or
you can supply a UV-mapped image texture containing different roughness
values for different parts of the entity. This value is available in
your surface shader. RealityKit won’t render a clearcoat with roughness
unless your surface shader calls both
`params.surface().set_clearcoat_roughness()` and
`params.surface().set_clearcoat()` with a value greater than `0.0`.
The following Swift code demonstrates setting the `clearcoatRoughness`
using a single value:
```swift
material.clearcoatRoughness = .init(floatLiteral: 0.5)
```
This example shows how to set the `clearcoatRoughness` using a UV-mapped
image:
```swift
if let clearcoatRoughnessResource = try?
TextureResource.load(named: "entity_cc_roughness") {
let ccRoughnessMap = MaterialParameters.Texture(clearcoatRoughnessResource)
material.clearcoat = .init(texture: ccRoughnessMap)
}
```
With custom materials, RealityKit only renders a clearcoat if
``CustomMaterial/lightingModel-swift.property`` is
``CustomMaterial/LightingModel-swift.enum/clearcoat`` and the material’s
surface shader function calls `params.surface().set_clearcoat()`.
To specify ``CustomMaterial/clearcoatRoughness-swift.property``,
your surface shader function needs to also call
`params.surface().set_clearcoat_roughness()`.
The following Metal code demonstrates using
``CustomMaterial/clearcoat-swift.property`` and
``CustomMaterial/clearcoatRoughness-swift.property`` in a surface
shader, replicating the behavior of the ``PhysicallyBasedMaterial``
shader:
```cpp
// Retrieve the clearcoat scale and roughness from the CustomMaterial.
float clearcoatScale = params.material_constants().clearcoat_scale();
float clearcoatRoughnessScale = params.material_constants().clearcoat_roughness_scale();
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from a USDZ or .reality file use texture coordinates with
// a flipped y-axis. This compensates for that.
uv.y = 1.0 - uv.y;
// Sample a value from the clearcoat and clearcoat roughness textures.
auto tex = params.textures();
half clearcoat = tex.clearcoat().sample(textureSampler, uv).r;
half clearcoatRoughness = tex.clearcoat_roughness().sample(textureSampler, uv).r;
// Multiply the scale and sampled texture value from the clearcoat and
// assign the result.
clearcoat *= clearcoatScale;
params.surface().set_clearcoat(clearcoat);
// Multiply the scale and sampled texture value from the clearcoat roughness
// and assign the result.
clearcoatRoughness *= clearcoatRoughnessScale;
params.surface().set_clearcoat_roughness(clearcoatRoughness);
```
get · iOS 15.0+
textureCoordinateTransform
TypeScript
get textureCoordinateTransform(): MaterialParameterTypes_TextureCoordinateTransform
Swift declaration
var textureCoordinateTransform: CustomMaterial.TextureCoordinateTransform { get set }
A two-dimensional transformation RealityKit applies to the entity’s
primary texture coordinates.
An entity’s UV texture coordinates control how RealityKit materials map
image textures onto an entity. Use this property to transform the
texture coordinates and change the way this material maps its textures.
For example, you might change the scale of the UV coordinates to apply a
tiled, repeating pattern to the surface of your entity, or continuously
rotate or translate the texture coordinates to animate materials and
create special effects, such as fire or flowing liquids.
The following example shows how to set a material’s UV transformation:
```swift
let rotationRadians = Float(45.0) * .pi / 180 // 45 degrees converted to radians.
material.textureCoordinateTransform = .init(
offset: [0.5, 0.5], scale: [0.5, 0.5],
rotation: rotationRadians
)
```
The material’s shader function doesn’t have to do anything to apply the
transformation. When the shader calls `params.geometry().uv1()`,
RealityKit already transforms the returned coordinates.
set · iOS 15.0+
textureCoordinateTransform
TypeScript
set textureCoordinateTransform(value: MaterialParameterTypes_TextureCoordinateTransform)
Swift declaration
var textureCoordinateTransform: CustomMaterial.TextureCoordinateTransform { get set }
A two-dimensional transformation RealityKit applies to the entity’s
primary texture coordinates.
An entity’s UV texture coordinates control how RealityKit materials map
image textures onto an entity. Use this property to transform the
texture coordinates and change the way this material maps its textures.
For example, you might change the scale of the UV coordinates to apply a
tiled, repeating pattern to the surface of your entity, or continuously
rotate or translate the texture coordinates to animate materials and
create special effects, such as fire or flowing liquids.
The following example shows how to set a material’s UV transformation:
```swift
let rotationRadians = Float(45.0) * .pi / 180 // 45 degrees converted to radians.
material.textureCoordinateTransform = .init(
offset: [0.5, 0.5], scale: [0.5, 0.5],
rotation: rotationRadians
)
```
The material’s shader function doesn’t have to do anything to apply the
transformation. When the shader calls `params.geometry().uv1()`,
RealityKit already transforms the returned coordinates.
get · iOS 26.0+
supportsMutableUniformsResources
TypeScript
static get supportsMutableUniformsResources(): boolean
Swift declaration
static var supportsMutableUniformsResources: Bool
Whether the current device supports resource storage within the WithMutableUniforms API.
Ensure this is true before setting resources such as textures and buffers on `CustomMaterial.ResourceStorage`
set · iOS 26.0+
supportsMutableUniformsResources
TypeScript
static set supportsMutableUniformsResources(value: boolean)
Swift declaration
static var supportsMutableUniformsResources: Bool
Whether the current device supports resource storage within the WithMutableUniforms API.
Ensure this is true before setting resources such as textures and buffers on `CustomMaterial.ResourceStorage`
get · iOS 15.0+
secondaryTextureCoordinateTransform
TypeScript
get secondaryTextureCoordinateTransform(): MaterialParameterTypes_TextureCoordinateTransform
Swift declaration
var secondaryTextureCoordinateTransform: CustomMaterial.TextureCoordinateTransform { get set }
A two-dimensional transformation RealityKit applies to the entity’s
secondary texture coordinates.
An entity’s UV texture coordinates define how RealityKit maps image
textures onto an entity. Use this property to transform the secondary
texture coordinates and change the way this material maps textures onto
an entity. If an entity has multiple materials assigned to it, the
transformation doesn’t affect how the other materials map their
textures.
For example, you might change the scale of the UV coordinates to apply a
tiled, repeating pattern to the surface of your entity, or continuously
rotate or translate the texture coordinates to animate materials and
create special effects, such as fire or flowing liquids.
The following example demonstrates how to set a material’s UV
transformation:
```swift
let rotationRadians = Float(45.0) * .pi / 180 // 45 degrees converted to radians.
secondaryTextureCoordinateTransform = .init(
offset: [0.5, 0.5], scale: [0.5, 0.5],
rotation: rotationRadians
)
```
The material’s shader function doesn’t have to do anything to apply the
transformation. When the shader calls `params.geometry().uv1()`,
RealityKit already transforms the returned coordinates.
set · iOS 15.0+
secondaryTextureCoordinateTransform
TypeScript
set secondaryTextureCoordinateTransform(value: MaterialParameterTypes_TextureCoordinateTransform)
Swift declaration
var secondaryTextureCoordinateTransform: CustomMaterial.TextureCoordinateTransform { get set }
A two-dimensional transformation RealityKit applies to the entity’s
secondary texture coordinates.
An entity’s UV texture coordinates define how RealityKit maps image
textures onto an entity. Use this property to transform the secondary
texture coordinates and change the way this material maps textures onto
an entity. If an entity has multiple materials assigned to it, the
transformation doesn’t affect how the other materials map their
textures.
For example, you might change the scale of the UV coordinates to apply a
tiled, repeating pattern to the surface of your entity, or continuously
rotate or translate the texture coordinates to animate materials and
create special effects, such as fire or flowing liquids.
The following example demonstrates how to set a material’s UV
transformation:
```swift
let rotationRadians = Float(45.0) * .pi / 180 // 45 degrees converted to radians.
secondaryTextureCoordinateTransform = .init(
offset: [0.5, 0.5], scale: [0.5, 0.5],
rotation: rotationRadians
)
```
The material’s shader function doesn’t have to do anything to apply the
transformation. When the shader calls `params.geometry().uv1()`,
RealityKit already transforms the returned coordinates.
Creates a custom material from an existing material, surface shader, and
geometry modifier.
Use this initializer to create a custom material with the same
properties as another existing material, but with a geometry modifier
and surface shader.
- Parameters:
- material: The material from which to copy properties.
- surfaceShader: The surface shader function.
- geometryModifier: The geometry modifier shader function.
init(from material: any Material, geometryModifier: CustomMaterial.GeometryModifier) throws
Creates a custom material from an existing material and a geometry
modifier.
Use this initializer to create a custom material with the same
properties as another existing material, but with a geometry modifier.
- Parameters:
- material: The material on which to base the custom material.
- geometryModifier: The geometry modifier shader function.
get · iOS 15.0+
custom
TypeScript
get custom(): CustomMaterial_Custom
Swift declaration
var custom: CustomMaterial.Custom { get set }
User-defined properties for the material’s shader functions.
Use a ``CustomMaterial/Custom-swift.struct`` object to send custom data
to your shader functions. A custom object can hold a texture or a vector
value, or both. Both the texture and vector value are available in your
shader functions.
- Note: Unlike other ``CustomMaterial`` properties, you don’t need to
create a ``CustomMaterial/Custom-swift.struct`` object for your
material. All ``CustomMaterial`` objects have one by default; you just
need to set the ``CustomMaterial/Custom-swift.struct/value`` property,
``CustomMaterial/Custom-swift.struct/texture`` property, or both.
The following code demonstrates how to use the custom property to pass a
vector to your shader functions:
```swift
// Specify a custom vector to pass to the shader functions.
customMaterial.custom.value = [0.25, 0.25, 0.25, 1.0]
```
You can also use it to pass up to four scalar values instead of a
vector:
```swift
let customValue1: Float = 0.25
let customValue2: Float = 0.75
customMaterial.custom.value[0] = customValue1
customMaterial.custom.value[1] = customValue2
```
The custom property can also include a texture. The following code
demonstrates how to add a texture to the custom property:
```swift
if let theResource = try? TextureResource.load(named: "MyCustomTexture") {
let myTexture = CustomMaterial.Texture(theResource)
customMaterial.custom.texture = .init(myTexture)
}
```
The following Metal code shows how to retrieve the custom vector in a
shader function:
```cpp
float4 myCustomVector = params.uniforms().custom_parameter();
```
The following Metal code shows how to retrieve individual values from
the custom vector in your shader functions:
```cpp
float firstCustomValue = params.uniforms().custom_parameter()[0];
float secondCustomValue = params.uniforms().custom_parameter()[1];
```
Here’s how to retrieve the custom texture in your shader functions:
```cpp
float voronoiColor = params.textures()
.custom().sample(textureSampler, UV).r;
```
set · iOS 15.0+
custom
TypeScript
set custom(value: CustomMaterial_Custom)
Swift declaration
var custom: CustomMaterial.Custom { get set }
User-defined properties for the material’s shader functions.
Use a ``CustomMaterial/Custom-swift.struct`` object to send custom data
to your shader functions. A custom object can hold a texture or a vector
value, or both. Both the texture and vector value are available in your
shader functions.
- Note: Unlike other ``CustomMaterial`` properties, you don’t need to
create a ``CustomMaterial/Custom-swift.struct`` object for your
material. All ``CustomMaterial`` objects have one by default; you just
need to set the ``CustomMaterial/Custom-swift.struct/value`` property,
``CustomMaterial/Custom-swift.struct/texture`` property, or both.
The following code demonstrates how to use the custom property to pass a
vector to your shader functions:
```swift
// Specify a custom vector to pass to the shader functions.
customMaterial.custom.value = [0.25, 0.25, 0.25, 1.0]
```
You can also use it to pass up to four scalar values instead of a
vector:
```swift
let customValue1: Float = 0.25
let customValue2: Float = 0.75
customMaterial.custom.value[0] = customValue1
customMaterial.custom.value[1] = customValue2
```
The custom property can also include a texture. The following code
demonstrates how to add a texture to the custom property:
```swift
if let theResource = try? TextureResource.load(named: "MyCustomTexture") {
let myTexture = CustomMaterial.Texture(theResource)
customMaterial.custom.texture = .init(myTexture)
}
```
The following Metal code shows how to retrieve the custom vector in a
shader function:
```cpp
float4 myCustomVector = params.uniforms().custom_parameter();
```
The following Metal code shows how to retrieve individual values from
the custom vector in your shader functions:
```cpp
float firstCustomValue = params.uniforms().custom_parameter()[0];
float secondCustomValue = params.uniforms().custom_parameter()[1];
```
Here’s how to retrieve the custom texture in your shader functions:
```cpp
float voronoiColor = params.textures()
.custom().sample(textureSampler, UV).r;
```
get · iOS 15.0+
normal
TypeScript
get normal(): CustomMaterial_Normal
Swift declaration
var normal: CustomMaterial.Normal { get set }
A texture map that stores fine surface details for the entity.
_Normal mapping_ is a real-time rendering technique that captures fine
surface details for a model by using a texture instead of increasing the
number of polygons in the model. It works by storing _surface normals_,
which are vectors perpendicular to the surface of the model, from a much
higher-resolution version of the same 3D object. A normal map stores
each vector in the image by storing the vectors’ `X`, `Y`, and `Z`
values as the `R`, `G`, and `B` components of the corresponding pixel in
the UV-mapped image.
For custom materials, ``CustomMaterial/normal-swift.property`` is only
used when ``CustomMaterial/lightingModel-swift.property`` is
``CustomMaterial/LightingModel-swift.enum/lit`` or
``CustomMaterial/LightingModel-swift.enum/clearcoat`` and its surface
shader calls `params.surface().set_normal(). T`he normal map texture is
still available to your surface shader function when using
``CustomMaterial/LightingModel-swift.enum/unlit``.
The following code loads a normal map texture and uses it to set this
property:
```swift
if let normalResource = try? TextureResource.load(named:"entity_normals") {
let normalMap = MaterialParameters.Texture(normalResource)
material.normal = .init(texture:normalMap)
}
```
The following Metal code shows how to sample the normal map texture in a
surface shader and use it to set the fragment’s surface normal:
```cpp
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from USDZ or .reality files have texture coordinates
// with a flipped y-axis. This adjusts for that.
uv.y = 1.0 - uv.y;
// Sample the normal map to get the surface normal for this fragment.
auto tex = params.textures();
float3 color = (float3)tex.normal().sample(textureSampler, uv).rgb;
// Set the fragment's surface normal using the sampled value.
params.surface().set_normal(color);
```
For more information on creating custom materials and writing shader
functions, see
<doc:modifying-realitykit-rendering-using-custom-materials>.
set · iOS 15.0+
normal
TypeScript
set normal(value: CustomMaterial_Normal)
Swift declaration
var normal: CustomMaterial.Normal { get set }
A texture map that stores fine surface details for the entity.
_Normal mapping_ is a real-time rendering technique that captures fine
surface details for a model by using a texture instead of increasing the
number of polygons in the model. It works by storing _surface normals_,
which are vectors perpendicular to the surface of the model, from a much
higher-resolution version of the same 3D object. A normal map stores
each vector in the image by storing the vectors’ `X`, `Y`, and `Z`
values as the `R`, `G`, and `B` components of the corresponding pixel in
the UV-mapped image.
For custom materials, ``CustomMaterial/normal-swift.property`` is only
used when ``CustomMaterial/lightingModel-swift.property`` is
``CustomMaterial/LightingModel-swift.enum/lit`` or
``CustomMaterial/LightingModel-swift.enum/clearcoat`` and its surface
shader calls `params.surface().set_normal(). T`he normal map texture is
still available to your surface shader function when using
``CustomMaterial/LightingModel-swift.enum/unlit``.
The following code loads a normal map texture and uses it to set this
property:
```swift
if let normalResource = try? TextureResource.load(named:"entity_normals") {
let normalMap = MaterialParameters.Texture(normalResource)
material.normal = .init(texture:normalMap)
}
```
The following Metal code shows how to sample the normal map texture in a
surface shader and use it to set the fragment’s surface normal:
```cpp
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from USDZ or .reality files have texture coordinates
// with a flipped y-axis. This adjusts for that.
uv.y = 1.0 - uv.y;
// Sample the normal map to get the surface normal for this fragment.
auto tex = params.textures();
float3 color = (float3)tex.normal().sample(textureSampler, uv).rgb;
// Set the fragment's surface normal using the sampled value.
params.surface().set_normal(color);
```
For more information on creating custom materials and writing shader
functions, see
<doc:modifying-realitykit-rendering-using-custom-materials>.
The reflectiveness of an entity.
In physically based rendering, the `metallic` property represents the
reflectiveness of an entity. Use this property to specify whether the
entity displays metallic qualities and reflects the surrounding
environment, or displays dielectric qualities and doesn’t reflect the
environment. With custom materials, RealityKit doesn’t automatically use
the values set on this property.
To render a custom material using the metallic property, set
``CustomMaterial/lightingModel-swift.property`` to
``CustomMaterial/LightingModel-swift.enum/lit`` or
``CustomMaterial/LightingModel-swift.enum/clearcoat``
and call `params.surface().set_roughness()`
from its surface shader.

The following Swift code shows how to use an image and a scale to
specify roughness:
```swift
if let metallicResource = try? TextureResource.load(named:"entity_metallic") {
let metallic = MaterialParameters.Texture(metallicResource)
material.metallic = PhysicallyBasedMaterial.Metallic(scale: 1.0, texture:metallic)
}
```
The following surface shader takes the scale and texture values from the
``CustomMaterial/metallic-swift.property`` property, multiplies them
together, and uses the result to specify the metallic value for
rendering, which emulates the behavior of ``PhysicallyBasedMaterial``.
```cpp
#include <metal_stdlib>
#include <RealityKit/RealityKit.h>
using namespace metal;
// Use samplers to retrieve a color value from a texture based on // the
entity's UV coordinates. Samplers can be reused with different textures.
// Surface shader functions should define no more than eight samplers.
constexpr sampler textureSampler(address::clamp_to_edge,
filter::bicubic);
[[visible]] void mySurfaceShader(realitykit::surface_parameters params)
{
// Retrieve the metallic scale from the CustomMaterial.
float metallicScale = params.material_constants().metallic_scale();
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from USDZ or .reality files have texture coordinates
// with a flipped y-axis. This adjusts for that.
uv.y = 1.0 - uv.y;
// Sample the metallic texture based on the UV coordinates.
auto tex = params.textures();
half metallic = tex.metallic().sample(textureSampler, uv).r;
// Multiply the tint and the sampled value from the texture,
// and assign the result to the shader's metallic property.
metallic *= metallicScale;
params.surface().set_metallic(metallic);
}
```
For more information on creating custom materials and writing shader
functions, see
<doc:modifying-realitykit-rendering-using-custom-materials>.
set · iOS 15.0+
metallic
TypeScript
set metallic(value: CustomMaterial_Metallic)
Swift declaration
var metallic: CustomMaterial.Metallic { get set }
The reflectiveness of an entity.
In physically based rendering, the `metallic` property represents the
reflectiveness of an entity. Use this property to specify whether the
entity displays metallic qualities and reflects the surrounding
environment, or displays dielectric qualities and doesn’t reflect the
environment. With custom materials, RealityKit doesn’t automatically use
the values set on this property.
To render a custom material using the metallic property, set
``CustomMaterial/lightingModel-swift.property`` to
``CustomMaterial/LightingModel-swift.enum/lit`` or
``CustomMaterial/LightingModel-swift.enum/clearcoat``
and call `params.surface().set_roughness()`
from its surface shader.

The following Swift code shows how to use an image and a scale to
specify roughness:
```swift
if let metallicResource = try? TextureResource.load(named:"entity_metallic") {
let metallic = MaterialParameters.Texture(metallicResource)
material.metallic = PhysicallyBasedMaterial.Metallic(scale: 1.0, texture:metallic)
}
```
The following surface shader takes the scale and texture values from the
``CustomMaterial/metallic-swift.property`` property, multiplies them
together, and uses the result to specify the metallic value for
rendering, which emulates the behavior of ``PhysicallyBasedMaterial``.
```cpp
#include <metal_stdlib>
#include <RealityKit/RealityKit.h>
using namespace metal;
// Use samplers to retrieve a color value from a texture based on // the
entity's UV coordinates. Samplers can be reused with different textures.
// Surface shader functions should define no more than eight samplers.
constexpr sampler textureSampler(address::clamp_to_edge,
filter::bicubic);
[[visible]] void mySurfaceShader(realitykit::surface_parameters params)
{
// Retrieve the metallic scale from the CustomMaterial.
float metallicScale = params.material_constants().metallic_scale();
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from USDZ or .reality files have texture coordinates
// with a flipped y-axis. This adjusts for that.
uv.y = 1.0 - uv.y;
// Sample the metallic texture based on the UV coordinates.
auto tex = params.textures();
half metallic = tex.metallic().sample(textureSampler, uv).r;
// Multiply the tint and the sampled value from the texture,
// and assign the result to the shader's metallic property.
metallic *= metallicScale;
params.surface().set_metallic(metallic);
}
```
For more information on creating custom materials and writing shader
functions, see
<doc:modifying-realitykit-rendering-using-custom-materials>.
get · iOS 15.0+
specular
TypeScript
get specular(): CustomMaterial_Specular
Swift declaration
var specular: CustomMaterial.Specular { get set }
The bright highlights to apply to the entity.
In physically based rendering (PBR), specular highlights primarily come
from the object’s ``PhysicallyBasedMaterial/roughness-swift.property``
value. RealityKit renders materials that have a low roughness value with
specular highlights based on the environment, lighting, and shape of the
entity. As a result, for most materials, you don’t need to specify a
`specular` value.
For some types of dielectric (nonmetallic) materials, like facet-cut
glass or gems, PBR algorithms don’t create bright enough specular
highlights using just roughness. To accurately simulate those types of
materials, the ``PhysicallyBasedMaterial/specular-swift.property``
property allows you to specify additional specularity for the entity.
The following example demonstrates how to add specularity using a single
value for the entire material:
```swift
material.specular = .init(floatLiteral: 0.8)
```
The following code shows how to add specularity using a UV-mapped image
texture:
```swift
if let specularResource = try? TextureResource.load(named: "entity_specular") {
let specularMap = MaterialParameters.Texture(specularResource)
material.specular = .init(texture: specularMap)
}
```
With custom materials, the specular
``CustomMaterial/Specular-swift.struct/scale`` and
``CustomMaterial/Specular-swift.struct/texture`` are available to the
material’s shader functions, but RealityKit doesn’t automatically use
the values you set.
To render a custom material with additional specular highlights, set
``CustomMaterial/lightingModel-swift.property`` to
``CustomMaterial/LightingModel-swift.enum/lit`` or
``CustomMaterial/LightingModel-swift.enum/clearcoat``,
and call `params().surface().set_specular()`
from its surface shader.
The following Metal code demonstrates using the specular scale and
texture values, simulating the behavior of the shaders that render a
``PhysicallyBasedMaterial``:
```cpp
// Retrieve the opacity scale from the CustomMaterial.
float specularScale = params.material_constants().specular_scale();
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from a USDZ or .reality file use texture coordinates
// with a flipped y-axis. This compensates for that.
uv.y = 1.0 - uv.y;
// Sample the specular texture.
auto tex = params.textures();
half specular = tex.specular().sample(textureSampler, uv).r;
// Multiply the tint and the sampled value from the texture and assign
// the result.
specular *= specularScale;
params.surface().set_specular(specular);
```
For more information on creating custom materials and writing shader
functions, see
<doc:modifying-realitykit-rendering-using-custom-materials>.
set · iOS 15.0+
specular
TypeScript
set specular(value: CustomMaterial_Specular)
Swift declaration
var specular: CustomMaterial.Specular { get set }
The bright highlights to apply to the entity.
In physically based rendering (PBR), specular highlights primarily come
from the object’s ``PhysicallyBasedMaterial/roughness-swift.property``
value. RealityKit renders materials that have a low roughness value with
specular highlights based on the environment, lighting, and shape of the
entity. As a result, for most materials, you don’t need to specify a
`specular` value.
For some types of dielectric (nonmetallic) materials, like facet-cut
glass or gems, PBR algorithms don’t create bright enough specular
highlights using just roughness. To accurately simulate those types of
materials, the ``PhysicallyBasedMaterial/specular-swift.property``
property allows you to specify additional specularity for the entity.
The following example demonstrates how to add specularity using a single
value for the entire material:
```swift
material.specular = .init(floatLiteral: 0.8)
```
The following code shows how to add specularity using a UV-mapped image
texture:
```swift
if let specularResource = try? TextureResource.load(named: "entity_specular") {
let specularMap = MaterialParameters.Texture(specularResource)
material.specular = .init(texture: specularMap)
}
```
With custom materials, the specular
``CustomMaterial/Specular-swift.struct/scale`` and
``CustomMaterial/Specular-swift.struct/texture`` are available to the
material’s shader functions, but RealityKit doesn’t automatically use
the values you set.
To render a custom material with additional specular highlights, set
``CustomMaterial/lightingModel-swift.property`` to
``CustomMaterial/LightingModel-swift.enum/lit`` or
``CustomMaterial/LightingModel-swift.enum/clearcoat``,
and call `params().surface().set_specular()`
from its surface shader.
The following Metal code demonstrates using the specular scale and
texture values, simulating the behavior of the shaders that render a
``PhysicallyBasedMaterial``:
```cpp
// Retrieve the opacity scale from the CustomMaterial.
float specularScale = params.material_constants().specular_scale();
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Entities loaded from a USDZ or .reality file use texture coordinates
// with a flipped y-axis. This compensates for that.
uv.y = 1.0 - uv.y;
// Sample the specular texture.
auto tex = params.textures();
half specular = tex.specular().sample(textureSampler, uv).r;
// Multiply the tint and the sampled value from the texture and assign
// the result.
specular *= specularScale;
params.surface().set_specular(specular);
```
For more information on creating custom materials and writing shader
functions, see
<doc:modifying-realitykit-rendering-using-custom-materials>.
get · iOS 15.0+
baseColor
TypeScript
get baseColor(): CustomMaterial_BaseColor
Swift declaration
var baseColor: CustomMaterial.BaseColor { get set }
The color of an entity unmodified by lighting.
In physically based rendering, the base color of an entity is its color
before RealityKit applies any lighting calculations or other rendering
calculations to it. With custom materials, the base color `texture` and
`tint` are available as inputs in your surface shader. With custom
materials, RealityKit doesn’t automatically use the values set on the
``CustomMaterial/baseColor-swift.property`` property. The material’s
surface shader is responsible for calculating or setting the actual base
color value for rendering by calling
`params.surface().set_base_color()`.
The following code shows how to create a base color from a tint color
and a texture, and then assign it to a custom material:
```swift
// Load entity_basecolor.jpg from the app's bundle.
if let baseResource = try? TextureResource.load(named: "entity_basecolor") {
let baseColor = CustomMaterial.Texture(baseResource)
customMaterial.baseColor = CustomMaterial.BaseColor(tint: .blue,
texture:baseColor)
}
```
In your surface shader, you can access the `tint` of the material’s base
color property by calling
`params.material_constants().base_color_tint()`. You can access the
texture by calling `params.textures().base_color()`.
The following surface shader function takes the tint and texture values
from the ``CustomMaterial/baseColor-swift.property`` property,
multiplies them together, and sets the resulting value as the base color
for rendering, which emulates the behavior of
``PhysicallyBasedMaterial``:
```cpp
#include <metal_stdlib>
#include <RealityKit/RealityKit.h>
using namespace metal;
// Use samplers to retrieve a color value from a texture based on // UV
coordinates. Samplers can be reused with different textures. //
RealityKit reserves eight samplers for itself, so surface shaders should
// never define more than eight samplers. constexpr sampler
textureSampler(address::clamp_to_edge, filter::bicubic);
[[visible]] void mySurfaceShader(realitykit::surface_parameters params)
{
// Retrieve the base color tint from the CustomMaterial.
half3 baseColorTint = (half3)params.material_constants().base_color_tint();
// Sample a value from the CustomMaterial's base color texture
// using the entity's UV coordinates.
auto uv = params.geometry().uv0();
auto tex = params.textures();
half3 color = (half3)tex.base_color().sample(textureSampler, uv).rgb;
// Multiply the tint and color sampled from the base color texture and
// assign the result to the shader's base color property.
color *= baseColorTint;
params.surface().set_base_color(color);
}
```
For more information on creating custom materials and writing shader
functions, see
<doc:modifying-realitykit-rendering-using-custom-materials>.
set · iOS 15.0+
baseColor
TypeScript
set baseColor(value: CustomMaterial_BaseColor)
Swift declaration
var baseColor: CustomMaterial.BaseColor { get set }
The color of an entity unmodified by lighting.
In physically based rendering, the base color of an entity is its color
before RealityKit applies any lighting calculations or other rendering
calculations to it. With custom materials, the base color `texture` and
`tint` are available as inputs in your surface shader. With custom
materials, RealityKit doesn’t automatically use the values set on the
``CustomMaterial/baseColor-swift.property`` property. The material’s
surface shader is responsible for calculating or setting the actual base
color value for rendering by calling
`params.surface().set_base_color()`.
The following code shows how to create a base color from a tint color
and a texture, and then assign it to a custom material:
```swift
// Load entity_basecolor.jpg from the app's bundle.
if let baseResource = try? TextureResource.load(named: "entity_basecolor") {
let baseColor = CustomMaterial.Texture(baseResource)
customMaterial.baseColor = CustomMaterial.BaseColor(tint: .blue,
texture:baseColor)
}
```
In your surface shader, you can access the `tint` of the material’s base
color property by calling
`params.material_constants().base_color_tint()`. You can access the
texture by calling `params.textures().base_color()`.
The following surface shader function takes the tint and texture values
from the ``CustomMaterial/baseColor-swift.property`` property,
multiplies them together, and sets the resulting value as the base color
for rendering, which emulates the behavior of
``PhysicallyBasedMaterial``:
```cpp
#include <metal_stdlib>
#include <RealityKit/RealityKit.h>
using namespace metal;
// Use samplers to retrieve a color value from a texture based on // UV
coordinates. Samplers can be reused with different textures. //
RealityKit reserves eight samplers for itself, so surface shaders should
// never define more than eight samplers. constexpr sampler
textureSampler(address::clamp_to_edge, filter::bicubic);
[[visible]] void mySurfaceShader(realitykit::surface_parameters params)
{
// Retrieve the base color tint from the CustomMaterial.
half3 baseColorTint = (half3)params.material_constants().base_color_tint();
// Sample a value from the CustomMaterial's base color texture
// using the entity's UV coordinates.
auto uv = params.geometry().uv0();
auto tex = params.textures();
half3 color = (half3)tex.base_color().sample(textureSampler, uv).rgb;
// Multiply the tint and color sampled from the base color texture and
// assign the result to the shader's base color property.
color *= baseColorTint;
params.surface().set_base_color(color);
}
```
For more information on creating custom materials and writing shader
functions, see
<doc:modifying-realitykit-rendering-using-custom-materials>.
get · iOS 15.0+
clearcoat
TypeScript
get clearcoat(): CustomMaterial_Clearcoat
Swift declaration
var clearcoat: CustomMaterial.Clearcoat { get set }
The transparent highlights that simulate a clear, shiny coating on an
entity.
An entity in RealityKit can display a clearcoat, which is a separate
layer of transparent specular highlights used to simulate a clear
coating, like on a car or the surface of lacquered objects.
This property allows you to specify
``PhysicallyBasedMaterial/clearcoat-swift.property`` using a single
`Float` that applies to the entire material, or a UV-mapped grayscale
image to provide different values for different parts of an entity.
The following example specifies `clearcoat` using a single value:
```swift
material.clearcoat = .init(floatLiteral: 0.8)
```
This example shows how to specify `clearcoat` using a UV-mapped image
texture:
```swift
if let clearcoatResource = try? TextureResource.load(named:
"entity_clearcoat") {
let clearcoatMap = MaterialParameters.Texture(clearcoatResource)
material.clearcoat = .init(texture: clearcoatMap)
}
```
With custom materials, RealityKit doesn’t automatically use the values
you set for this property to render your entity. The values from this
property are available to the custom material’s surface shader, but it
doesn’t render a clearcoat unless the custom material’s
``CustomMaterial/lightingModel-swift.property`` is
``CustomMaterial/LightingModel-swift.enum/clearcoat`` and the surface
shader calls `params.surface().set_clearcoat()`.
The following Metal code demonstrates how to retrieve the scale and
texture from this property, and use them to enable clearcoat rendering.
```cpp
// Retrieve the clearcoat scale from the CustomMaterial.
float clearcoatScale = params.material_constants().clearcoat_scale();
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Models loaded from USDZ or .reality files use texture coordinates with a
// flipped y-axis. This compensates for that.
uv.y = 1.0 - uv.y;
// Sample the clearcoat texture using the texture coordinates.
auto tex = params.textures();
half clearcoat = tex.clearcoat().sample(textureSampler, uv).r;
// Multiply the scale and sampled value from the texture, and assign
// the result.
clearcoat *= clearcoatScale;
params.surface().set_clearcoat(clearcoat);
```
set · iOS 15.0+
clearcoat
TypeScript
set clearcoat(value: CustomMaterial_Clearcoat)
Swift declaration
var clearcoat: CustomMaterial.Clearcoat { get set }
The transparent highlights that simulate a clear, shiny coating on an
entity.
An entity in RealityKit can display a clearcoat, which is a separate
layer of transparent specular highlights used to simulate a clear
coating, like on a car or the surface of lacquered objects.
This property allows you to specify
``PhysicallyBasedMaterial/clearcoat-swift.property`` using a single
`Float` that applies to the entire material, or a UV-mapped grayscale
image to provide different values for different parts of an entity.
The following example specifies `clearcoat` using a single value:
```swift
material.clearcoat = .init(floatLiteral: 0.8)
```
This example shows how to specify `clearcoat` using a UV-mapped image
texture:
```swift
if let clearcoatResource = try? TextureResource.load(named:
"entity_clearcoat") {
let clearcoatMap = MaterialParameters.Texture(clearcoatResource)
material.clearcoat = .init(texture: clearcoatMap)
}
```
With custom materials, RealityKit doesn’t automatically use the values
you set for this property to render your entity. The values from this
property are available to the custom material’s surface shader, but it
doesn’t render a clearcoat unless the custom material’s
``CustomMaterial/lightingModel-swift.property`` is
``CustomMaterial/LightingModel-swift.enum/clearcoat`` and the surface
shader calls `params.surface().set_clearcoat()`.
The following Metal code demonstrates how to retrieve the scale and
texture from this property, and use them to enable clearcoat rendering.
```cpp
// Retrieve the clearcoat scale from the CustomMaterial.
float clearcoatScale = params.material_constants().clearcoat_scale();
// Retrieve the entity's texture coordinates.
float2 uv = params.geometry().uv0();
// Models loaded from USDZ or .reality files use texture coordinates with a
// flipped y-axis. This compensates for that.
uv.y = 1.0 - uv.y;
// Sample the clearcoat texture using the texture coordinates.
auto tex = params.textures();
half clearcoat = tex.clearcoat().sample(textureSampler, uv).r;
// Multiply the scale and sampled value from the texture, and assign
// the result.
clearcoat *= clearcoatScale;
params.surface().set_clearcoat(clearcoat);
```
get · iOS 15.0+
roughness
TypeScript
get roughness(): CustomMaterial_Roughness
Swift declaration
var roughness: CustomMaterial.Roughness { get set }
The amount the surface of the 3D object scatters reflected light.
In physically based rendering, the `roughness` property represents how
much the surface of an entity scatters the light that it reflects. A
material with a high roughness has a matte appearance, whereas one with
a low roughness has a shiny appearance. With custom materials,
RealityKit doesn’t automatically use the values set on this property.
To render a custom material using roughness, set
``CustomMaterial/lightingModel-swift.property`` to
``CustomMaterial/LightingModel-swift.enum/lit`` or
``CustomMaterial/LightingModel-swift.enum/clearcoat``,
and specify a roughness value by calling `params.surface().set_roughness()`
from the surface shader.

With custom materials, the `texture` and `scale` values from the
``CustomMaterial/roughness-swift.property`` property are available in
your surface shader function, but RealityKit doesn’t automatically use
them to render your entity. Your surface shader is responsible for
calculating or setting the actual roughness value for rendering.
The following example shows how to use an image and a scale value to
specify roughness:
```swift
if let roughnessResource = try? TextureResource.load(named: "entity_roughness") {
let roughness = MaterialParameters.Texture(roughnessResource)
material.roughness = PhysicallyBasedMaterial.Roughness(tint: .green, texture:roughness)
}
```
The following surface shader takes the scale and texture from the
``CustomMaterial/roughness-swift.property`` property, multiplies them
together, and sets the resulting value as the roughness for rendering,
which emulates the behavior of ``PhysicallyBasedMaterial``:
```cpp
#include <metal_stdlib>
#include <RealityKit/RealityKit.h>
using namespace metal;
// Samplers are used to retrieve a color value from a texture based on
// the entity's UV coordinates. Samplers can be reused with different textures.
// Surface shader functions should define no more than eight samplers.
constexpr sampler textureSampler(address::clamp_to_edge, filter::bicubic);
[[visible]] void mySurfaceShader(realitykit::surface_parameters params)
{
// Retrieve the roughness scale from the CustomMaterial.
float roughnessScale = params.material_constants().roughness_scale();
// Retrieve the sampled value from the CustomMaterial's base color texture.
auto uv = getFlippedUVs(params);
auto tex = params.textures();
half roughness = tex.roughness().sample(textureSampler, uv).r;
// Multiply the tint and the sampled value from the texture, and assign it
// to the shader's base color property.
roughness *= roughnessScale;
// Set the roughness value to be used by the custom material shader.
params.surface().set_roughness(roughness);
}
```
For more information on creating custom materials and writing shader
functions, see
<doc:modifying-realitykit-rendering-using-custom-materials>.
set · iOS 15.0+
roughness
TypeScript
set roughness(value: CustomMaterial_Roughness)
Swift declaration
var roughness: CustomMaterial.Roughness { get set }
The amount the surface of the 3D object scatters reflected light.
In physically based rendering, the `roughness` property represents how
much the surface of an entity scatters the light that it reflects. A
material with a high roughness has a matte appearance, whereas one with
a low roughness has a shiny appearance. With custom materials,
RealityKit doesn’t automatically use the values set on this property.
To render a custom material using roughness, set
``CustomMaterial/lightingModel-swift.property`` to
``CustomMaterial/LightingModel-swift.enum/lit`` or
``CustomMaterial/LightingModel-swift.enum/clearcoat``,
and specify a roughness value by calling `params.surface().set_roughness()`
from the surface shader.

With custom materials, the `texture` and `scale` values from the
``CustomMaterial/roughness-swift.property`` property are available in
your surface shader function, but RealityKit doesn’t automatically use
them to render your entity. Your surface shader is responsible for
calculating or setting the actual roughness value for rendering.
The following example shows how to use an image and a scale value to
specify roughness:
```swift
if let roughnessResource = try? TextureResource.load(named: "entity_roughness") {
let roughness = MaterialParameters.Texture(roughnessResource)
material.roughness = PhysicallyBasedMaterial.Roughness(tint: .green, texture:roughness)
}
```
The following surface shader takes the scale and texture from the
``CustomMaterial/roughness-swift.property`` property, multiplies them
together, and sets the resulting value as the roughness for rendering,
which emulates the behavior of ``PhysicallyBasedMaterial``:
```cpp
#include <metal_stdlib>
#include <RealityKit/RealityKit.h>
using namespace metal;
// Samplers are used to retrieve a color value from a texture based on
// the entity's UV coordinates. Samplers can be reused with different textures.
// Surface shader functions should define no more than eight samplers.
constexpr sampler textureSampler(address::clamp_to_edge, filter::bicubic);
[[visible]] void mySurfaceShader(realitykit::surface_parameters params)
{
// Retrieve the roughness scale from the CustomMaterial.
float roughnessScale = params.material_constants().roughness_scale();
// Retrieve the sampled value from the CustomMaterial's base color texture.
auto uv = getFlippedUVs(params);
auto tex = params.textures();
half roughness = tex.roughness().sample(textureSampler, uv).r;
// Multiply the tint and the sampled value from the texture, and assign it
// to the shader's base color property.
roughness *= roughnessScale;
// Set the roughness value to be used by the custom material shader.
params.surface().set_roughness(roughness);
}
```
For more information on creating custom materials and writing shader
functions, see
<doc:modifying-realitykit-rendering-using-custom-materials>.
Skipped declarations
2 declarations were excluded from these bindings. Each reason comes from the generator or the iOS SDK compiler.