ohmyxm
ohmyxm

Reputation: 63

RealityKit - how to send data from CPU to custom material shaders?

In my project, I need to send custom structured data buffer from CPU to shaders in every frame. In SceneKit this can be done using setValue(_:forKey:) or handleBinding(ofBufferNamed:frequency:handler:) on a SCNProgram object. However in RealityKit I only found one custom value property that can be used to send data, like:

customMaterial.custom.value = SIMD4<Float>(x: 0.25, y: 0.25, z: 0.25, w: 1.0)

I know possibly I could use the material constants like roughness or specular kind of values to store more custom data but that doesn't allow other data format other than just some 4 component vectors (And this method seems dirty and confused)

How can I send more customizable data to the shader program or is it even possible to do this in the current version of RealityKit?

Upvotes: 4

Views: 742

Answers (1)

Andy Jazz
Andy Jazz

Reputation: 58553

You can create your own custom collection to store any number of values:

import Metal
import RealityKit

public extension CustomMaterial.Custom {
    struct Keeper {
        static var _computedPty: [SIMD4<Float>] = []
    }
    var collection: [SIMD4<Float>] {
        get { return Keeper._computedPty }
        set { Keeper._computedPty = newValue }
    }
}

Swift part

var material = try! CustomMaterial(surfaceShader: shading,
                                geometryModifier: modifier,
                                   lightingModel: .lit)
        
material.custom.collection += [SIMD4<Float>(1.0, 0.5, 1.0, 0.0)]
material.custom.collection += [SIMD4<Float>(0.3, 0.7, 0.9, 1.0)]
material.custom.collection += [SIMD4<Float>(0.0, 0.0, 0.0, 0.4)]
        
print(material.custom.collection[0][1])     //  0.5
print(material.custom.collection[1][2])     //  0.9
print(material.custom.collection[2][3])     //  0.4

Metal part

array<packed_float4, 12> customized = params.uniforms().custom_collection()[2];

To implement a Metal part, you need to create a buffer for sharing data between Metal shaders' methods and Swift ViewController. Read this excellent post to find out how to do that.

Upvotes: 1

Related Questions