Reputation: 63
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
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 }
}
}
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
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