ARKit Tutorial: How to attach Custom Variables to a Metal Shader & its associated SCNProgram through a TimedStroke Shader iOS 12.
The Problem
According to Apple:
Custom Variables
To use custom input variables in a Metal shader, first declare those variables as input parameters to your Metal shader functions, using an attribute qualifier to bind to buffer 2 (or higher). Because these variables pass to your Metal shader in a buffer, you typically also define a data structure for your variables, as seen in the partial shader below.
And suggests that you can achieve this by passing a struct of type MyAccentColors to a shader fragment in the following way:
struct MyAccentColors {
float4 primaryColor;
float4 secondaryColor;
};
fragment half4 myFragmentShader(default_io in [[stage_in]],
constant MyAccentColors& colors [[buffer(2)]]) { ... }
It then says that you can input it using
Key-value coding, by setting values on the geometry or material to be rendered with your shader, passing an
NSData
object containing your data structure as the value and the name of the corresponding shader function parameter as the key
Cool. But what ?!
The Solution Explained
To walk you through it using a different example, I will walk you through how to achieve the following stroke.
Please note that this shader works with this UV Mapping:
Metal Shader Half
In this case, the custom variables are called TimeVariables and are defined on line 48 to 52.
This TimeVariables are then passed in to the shader fragment on line 83 as timeVariables — this is super important for later.
They are then applied using dot notation as demonstrated on lines 91, 93, 95, 99 and 102.
SCNProgram Half
This shader can then be applied using the following function:
self.addStrokeShaderWithTimeForChild(child: YOUR_CHILD, loopTime: LOOP_TIME, startTime: START_TIME, endTime: END_TIME);
Which calls the following function:
As you can see, the custom variables are declared as strokeTimeVariableStruct in the form of a struct in lines 1 to 11.
This is then instantiated on line 34, to add the request loop time, start time and end time.
They are then passed to the geometry, which holds the SCNProgram, (line 27) through to the material (line 35) by setting a value holding the struct to a key called timeVariables — the same name as that in our shader fragment described in line 83 of the TimedStroke.metal.
I hope it helps
Please leave any feedback or questions in the comment section below.
Oscar