Canvatorium Visio Lab 5042
Edit a property on ShaderGraphMaterial from code.
Change the value of a named property/input for a ShaderGraphMaterial at runtime.
I’m using the SmoothConcrete material for this lab. It has a property called Basecolor Tint that we can edit in the sidebar in Reality Composer Pro.
But what if we want to change this color at runtime?
- Get the entity that we want to modify
- Get the material from the entity and cast it as ShaderGraphMaterial
- Use setParameter(name:value:) to provide a new value (docs). This method requires us to pass the value wrapped in MaterialParameters, in this case using the color option.
Full lab code
struct Lab5042: View {
@State var color: UIColor = .systemRed
func changeColorExample(root: Entity) {
// Get the target entity and the shader graph material
if let entity = root.findEntity(named: "Subject"),
var material = entity.components[ModelComponent.self]?.materials.first as? ShaderGraphMaterial {
do {
// Change the Basecolor_Tint property using MaterialParameters.Value.color
try material.setParameter(name: "Basecolor_Tint", value: MaterialParameters.Value.color(color))
// Apply the modified material back to the entity - this will replace the previous version with the one we just modified
entity.components[ModelComponent.self]?.materials[0] = material
} catch {
print("could not edit material parameter: \(error.localizedDescription)")
}
}
}
var body: some View {
ZStack(alignment: Alignment(horizontal: .center, vertical: .bottom)) {
RealityView { content in
if let root = try? await Entity(named: "MaterialLab", in: realityKitContentBundle) {
root.position = [0, -0.45, 0]
root.scale = [2,2,2]
content.add(root)
changeColorExample(root: root)
}
} update: { content in
if let root = content.entities.first {
changeColorExample(root: root)
}
}
.toolbar {
ToolbarItemGroup(placement: .bottomOrnament) {
Button {
color = .systemRed
} label: {
Text("R")
}
.foregroundColor(color == .systemRed ? .red : .white)
Button {
color = .systemGreen
} label: {
Text("G")
}
.foregroundColor(color == .systemGreen ? .green : .white)
Button {
color = .systemBlue
} label: {
Text("B")
}
.foregroundColor(color == .systemBlue ? .blue : .white)
}
}
}
}
}
Demo