How to connect custom variables to SCNTechnique and associated Metal Shaders.
Truth be told, this one gave me fever.
Common Problems
This might let you know whether you’re in the right place.
The Symbol is not appearing in the debugger
Yeah. I know — you’re going to have to accept . I was pushed by an unnamed god to literally go for it as they told me it was being passed.
The documentation example breaks ARKit
Yeah. I know — ARKit metal shaders are brand new. They’re still being documented.
The Binding of Symbol returns nothing in the completion block.
Yep
How on earth am I meant to understand the documentation.
Yes, that’s what I’m here for.
Solution
Step One : Create your Dictionary
Or use this one.
What’s important Here
- The declaration of the Symbol.
A symbol is the term that Apple uses for custom variables in SCNTechnique.
<key>symbols</key><dict><key>customVariableSymbol</key><dict><key>type</key><string>float</string></dict></dict>
We have declared the symbol as customVariableSymbol with type float.
2. We have set symbol as an input for every single pass.
As shown below, we have set the key symbolAsCalledInMetal (important for our struct later) to match the customVariableSymbol.
<key>inputs</key><dict><key>symbolAsCalledInMetal</key><string>customVariableSymbol</string><key>maskSampler</key><string>MASK</string></dict>
Step Two : Create your shader/s
Or take these.
What’s important Here
- The declaration of the Uniform struct
typedef struct {float symbolAsCalledInMetal;} Uniforms;
The variable in the struct MUST match the name of the input associated with your symbol with your pass in your SCNTechnique description. In this case ::: symbolAsCalledInMetal.
2. How the Symbol is passed to the Shader functions.
constant Uniforms& uniforms [[ buffer(0) ]])
Buffer 0 is recommended.
3. How the symbol is used
float customVariableSymbol = uniforms.symbolAsCalledInMetal;
Yes. Finally, something simple.
Step Three : Attach the symbol to the SCNTechnique
For an update every frame use the following:
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {self.sceneView.technique?.setObject(NSNumber(value: YOUR_VALUE), forKeyedSubscript: "customVariableSymbol" as NSCopying)
}
But really, what’s key here is:
self.sceneView.technique?.setObject(NSNumber(value: YOUR_VALUE), forKeyedSubscript: "customVariableSymbol" as NSCopying)
The forKeyedSubscript must match the name of your symbol definition in your dictionary.
In this case, customVariableSymbol.
—
Please leave any comments or questions in the comment section below.
Oscar