Hello knl,
To pass a custom symbol to a metal shader used in an SCNTechnique pass:
Step 1 - Defining a custom symbol in an SCNTechnique:
//…other dictionaries to define a technique,
"symbols": [
//…other symbols,
"mvpSymbol": ["semantic": "modelViewProjectionTransform"],
"myFloatSymbol": ["type": "float"]
//…other symbols
],
//…other dictionaries to define a technique
Important notes for Step 1:
The name that you choose for your symbol here MUST correspond with the name you use in your pass definition (which we will define next). Please see the SCNTechnique page for a list of semantics and types.
Step 2 - Adding your custom symbols to a particular pass:
//…rest of pass definition
"inputs": [
"symbolAsCalledInMetal": "mvpSymbol",
"myFloat": "myFloatSymbol"
],
//…rest of pass definition
Important notes for Step 2:
Whatever you decide to name your symbol for a particular pass, THAT is the name that you must use for the variable in your struct in Metal (which we will define soon). You can use the same symbol in different passes, just make sure that you add it to the "inputs" of each pass.
Step 3 - Defining the metal shader for a particular pass:
I think you probably already have this step down, but just in case, here is an example where we assume we have a .metal file with a vertex shader named "myVertexShader", and a fragment shader named "myFragmentShader"
//...rest of pass definition
"metalVertexShader": "myVertexShader",
"metalFragmentShader": "myFragmentShader",
//...rest of pass definition
Step 4 - Binding a value to each of your custom symbols on a per-frame basis:
//...Called inside the renderer(_:updateAtTime:) method
// For "myFloatSymbol", use NSNumber and pass the number that you want to use in your shader
sceneView.technique?.setObject(NSNumber(value: 3.0), forKeyedSubscript: “myFloatSymbol” as NSCopying)
// For "mvpSymbol", use NSValue and pass it the transform that you want to use in your shader
sceneView.technique?.setObject(NSValue(scnMatrix4: transform, forKeyedSubscript: “mvpSymbol” as NSCopying)
Important notes for Step 4:
I recommend that you bind your values in the renderer(_:updateAtTime:) method (assuming you want to update your symbols on a per-frame basis). Using the setObject method of an SCNTechnique, you want to use either NSNumber or NSValue depending on the type of your symbol, in this example, I use SCNMatrix4 for the transform because that is the type that corresponds with float4x4 in Metal, and Model-View-Projection Transforms are 4x4 matrices. Lastly, note that I am using the name of the symbol defined in the technique's "symbols" dict here, not the name of the symbol defined in a particular pass' "inputs" dict.
Step 5 - Defining your struct in your .metal file:
typedef struct {
// other symbols...
float myFloat;
float4x4 symbolAsCalledInMetal;
// other symbols…
} Inputs;
Important notes for Step 5:
Notice that in the struct definition, I am using the names defined for a particular pass' "inputs" dict.
At this point, you should now be able to access your custom symbols in your .metal shaders!