ARKit Tutorial: How to attach Custom Variables to a Metal Shader & its associated SCNProgram through a TimedStroke Shader iOS 12.

Oscar de la Hera
AR Tips And Tricks
Published in
2 min readSep 24, 2018

--

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

--

--

Oscar de la Hera
AR Tips And Tricks

Oscar is an award-winning Spanish Inventor whose work impacts lives through brands that include Nike, MoMA and Samsung.