Passing Custom Parameters to Metal with Realitykit

Hello

As part of my app, I am using Metal shaders on CustomMaterials created and managed using RealityKit. Using the ECS approach, I have a Shader system that iterates through all my materials every frame and passes a SIMD4 of variables (that I can manage on the swift side) that can be interpreted and used every frame on the Metal side to influence elements of the shader.

This does work as intended but is limited to just 4 variables when I need more for my use case. I've experimented with trying multiple simd4 or other approaches for passing these to metal and be useable but I haven't had very much luck. I was hoping for some recommendations on the best scalable approach.

Swift:

class ShaderSystem: System { static let query = EntityQuery(where: .has(ModelComponent.self)) private var startTime: Date

required init(scene: Scene) {
    startTime = Date()
}

func update(context: SceneUpdateContext) {
    let audioLevel = AudioSessionManager.shared.audioLevel
    let elapsedTime = Float(Date().timeIntervalSince(startTime))
    
    guard let sceneType = SceneManager.shared.currentScenes.keys.first else { return }
    
    let sceneTime = SceneComposer.shared.getSceneTime(for: sceneType)
    let multiplier = ControlManager.shared.getControlValue(parameterName: "elapsedTimeMultiplier") ?? 1.0
    
    for entity in context.scene.performQuery(Self.query) {
        guard var modelComponent = entity.components[ModelComponent.self] as? ModelComponent else { continue }
        
        modelComponent.materials = modelComponent.materials.map { material in
            guard var customMaterial = material as? CustomMaterial else { return material }
            
            // Passing audioLevel, elapsedTime, sceneTime, and multiplier
            customMaterial.custom.value = SIMD4<Float>(audioLevel, elapsedTime, sceneTime, multiplier)
            
            return customMaterial
        }
        
        entity.components[ModelComponent.self] = modelComponent
    }
}

}

metal:

struct CustomMaterialUniforms { float4 custom; };

[[visible]] void fractalShader(realitykit::surface_parameters params) { auto uniforms = params.uniforms(); float4 customValues = uniforms.custom_parameter(); float audioLevel = customValues.x;

....

Thank you for the assistance

Answered by DTS Engineer in 796581022

Hello @BLHimmel,

I believe that withMutableUniforms(ofType:stage:_:) is exactly the method you are looking for.

Take a look over the documentation on that page :)

-g

Hello @BLHimmel,

I believe that withMutableUniforms(ofType:stage:_:) is exactly the method you are looking for.

Take a look over the documentation on that page :)

-g

Passing Custom Parameters to Metal with Realitykit
 
 
Q