ARKit: Connecting a Shader to a Material.
The following tutorial aims to reproduce the following video.
Ok.
So what exactly is happening here ?
We have an image tracking ARKit app, which presents a geometry at 0.1m.
The tutorials to do this are the following, I advise you to do them in the exact order they are presented.:
How to create an ARKit image recognition app that removes all objects on reset.
How to add an image to a plane on Maya.
How to make a cylinder in Maya
I advise you to do this ontop of the image of the EXACT dimensions.
How to add a Model to a Scene Node.
If you are looking to learn more about ARKit, this is the best I have written so far:
ARKit Theory: The Point Cloud, Image Recognition, AR Ready Images, True Scale, The Renderer and Nodes
Once you’re there, in the section where you add the children to the scene add this:
for child in scn!.rootNode.childNodes {// MOVE YOUR CHILD 0.1M ABOVE THE TARGET
child.position = SCNVector3.init(0, 0.1, 0);// CREATE A PROGRAM AND TIE IT TO A METAL SHADER FUNCTIONALITY
let program = SCNProgram()program.fragmentFunctionName = "trianglequiltFragment"program.vertexFunctionName = "trianglequiltVertex"// CREATE A MATERIAL, ADD THE PROGRAM, AND ADD IT TO THE CHILD.let shaderMaterial = SCNMaterial()shaderMaterial.program = program;shaderMaterial.diffuse.contents = UIColor.blueshaderMaterial.locksAmbientWithDiffuse = truechild.geometry?.materials = [shaderMaterial];
node.addChildNode(child)}
And then, create a shader.metal file in the same directory and add this code:
Thank you to my man Lock, for this piece of code.
#include <metal_stdlib>using namespace metal;#include <SceneKit/scn_metal>struct myPlaneNodeBuffer {float4x4 modelTransform;float4x4 modelViewTransform;float4x4 normalTransform;float4x4 modelViewProjectionTransform;float2x3 boundingBox;};typedef struct {float3 position [[ attribute(SCNVertexSemanticPosition) ]];float2 texCoords [[ attribute(SCNVertexSemanticTexcoord0) ]];} VertexInput;static float rand(float2 uv){return fract(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453);}static float2 uv2tri(float2 uv){float sx = uv.x - uv.y / 2;float sxf = fract(sx);float offs = step(fract(1 - uv.y), sxf);return float2(floor(sx) * 2 + sxf + offs, uv.y);}struct SimpleVertexWithUV{float4 position [[position]];float2 uv;};vertex SimpleVertexWithUV trianglequiltVertex(VertexInput in [[ stage_in ]],constant SCNSceneBuffer& scn_frame [[buffer(0)]],constant myPlaneNodeBuffer& scn_node [[buffer(1)]]){SimpleVertexWithUV vert;vert.position = scn_node.modelViewProjectionTransform * float4(in.position, 1.0);vert.uv = in.texCoords;return vert;}fragment float4 trianglequiltFragment(SimpleVertexWithUV in [[stage_in]],constant SCNSceneBuffer& scn_frame [[buffer(0)]],constant myPlaneNodeBuffer& scn_node [[buffer(1)]]){float4 fragColor;float2 uv = in.uv*10;float timer = scn_frame.time;uv.y += timer;float t = timer * 0.8;float tc = floor(t);float tp = smoothstep(0, 0.8, fract(t));float2 r1 = float2(floor(uv.y), tc);float2 r2 = float2(floor(uv.y), tc + 1);float offs = mix(rand(r1), rand(r2), tp);uv.x += offs * 8;float2 p = uv2tri(uv);float ph = rand(floor(p)) * 6.3 + p.y * 0.2;float c = abs(sin(ph + timer));fragColor = float4(c, c, c, 1);return(fragColor);}
Please leave any questions, in the comment section below.
Oscar