---
title: Animating Shapes with Simple Equations
tags:  #metal #msl #shaders #swift  
author: [Shuichi Tsutsumi](https://www.docswell.com/user/shu223)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/37KDD84VED.jpg?width=480
description: yakatabune.swift での発表資料です。
published: March 21, 24
canonical: https://www.docswell.com/s/shu223/Z6YR8P-MetalSDF
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/37KDD84VED.jpg)

Animating Shapes
with Simple Equations
Shuichi Tsutsumi @shu223


# Page. 2

![Page Image](https://bcdn.docswell.com/page/LJ3RR2DQE5.jpg)

Disclaimer
• No Swift, only MSL (Metal Shader Language)
• HOWEVER, the concept is universal — GLSL, HLSL, even
Swift.
• Hope you&#039;ll find the concept interesting!


# Page. 3

![Page Image](https://bcdn.docswell.com/page/8JDYYZPWJG.jpg)

参考書籍
リアルタイムグラフィックスの数学 ― GLSLではじめるシェーダプログラミング
amazon
第II部「距離がつくりし世界」
のサンプルをMSLで写経し、
学びを整理したのが本発表


# Page. 4

![Page Image](https://bcdn.docswell.com/page/VEP66DNX78.jpg)

Examples of Animating Shapes


# Page. 5

![Page Image](https://bcdn.docswell.com/page/27V331K3JQ.jpg)

3D


# Page. 6

![Page Image](https://bcdn.docswell.com/page/5JG332QYEL.jpg)

2D


# Page. 7

![Page Image](https://bcdn.docswell.com/page/47Q55PK6EP.jpg)

How to create animations like
these?


# Page. 8

![Page Image](https://bcdn.docswell.com/page/KE499YPMJ1.jpg)

Define the shape for each frame?
and display the sequence of images?
animatedImage(with: images, duration: 2.0)


# Page. 9

![Page Image](https://bcdn.docswell.com/page/L71KK69YEG.jpg)

!
too hard...


# Page. 10

![Page Image](https://bcdn.docswell.com/page/G7WDDWQ1E2.jpg)

Calculate the shape for each frame?
like vector images
&lt;?xml version=&quot;1.0&quot; standalone=&quot;no&quot;?&gt;
&lt;svg width=&quot;200&quot; height=&quot;250&quot; version=&quot;1.1&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot;&gt;
&lt;rect x=&quot;10&quot; y=&quot;10&quot; width=&quot;30&quot; height=&quot;30&quot; stroke=&quot;black&quot; fill=&quot;transparent&quot; stroke-width=&quot;5&quot;/&gt;
&lt;rect x=&quot;60&quot; y=&quot;10&quot; rx=&quot;10&quot; ry=&quot;10&quot; width=&quot;30&quot; height=&quot;30&quot; stroke=&quot;black&quot; fill=&quot;transparent&quot; stroke-width=&quot;5&quot;/&gt;
&lt;circle cx=&quot;25&quot; cy=&quot;75&quot; r=&quot;20&quot; stroke=&quot;red&quot; fill=&quot;transparent&quot; stroke-width=&quot;5&quot;/&gt;
&lt;ellipse cx=&quot;75&quot; cy=&quot;75&quot; rx=&quot;20&quot; ry=&quot;5&quot; stroke=&quot;red&quot; fill=&quot;transparent&quot; stroke-width=&quot;5&quot;/&gt;
&lt;line x1=&quot;10&quot; x2=&quot;50&quot; y1=&quot;110&quot; y2=&quot;150&quot; stroke=&quot;orange&quot; stroke-width=&quot;5&quot;/&gt;
&lt;polyline points=&quot;60 110 65 120 70 115 75 130 80 125 85 140 90 135 95 150 100 145&quot;
stroke=&quot;orange&quot; fill=&quot;transparent&quot; stroke-width=&quot;5&quot;/&gt;
&lt;polygon points=&quot;50 160 55 180 70 180 60 190 65 205 50 195 35 205 40 190 30 180 45 180&quot;
stroke=&quot;green&quot; fill=&quot;transparent&quot; stroke-width=&quot;5&quot;/&gt;
&lt;path d=&quot;M20,230 Q40,205 50,230 T90,230&quot; fill=&quot;none&quot; stroke=&quot;blue&quot; stroke-width=&quot;5&quot;/&gt;
&lt;/svg&gt;


# Page. 11

![Page Image](https://bcdn.docswell.com/page/4JZGG5WX73.jpg)

!
too difficult...


# Page. 12

![Page Image](https://bcdn.docswell.com/page/YE6YY9GPJV.jpg)

!
You don&#039;t need to do that


# Page. 13

![Page Image](https://bcdn.docswell.com/page/GE5GGNVPE4.jpg)

Just use ONE function
mix(x, y, a)
• x: Shape 1
• y: Shape 2
• a: 0.0 - 1.0


# Page. 14

![Page Image](https://bcdn.docswell.com/page/972YY53Z7R.jpg)

!


# Page. 15

![Page Image](https://bcdn.docswell.com/page/DJYGGK1NJM.jpg)

How can we achieve the animation
with just ONE function?


# Page. 16

![Page Image](https://bcdn.docswell.com/page/V7NGGR2VE8.jpg)

Explaining Step by Step


# Page. 17

![Page Image](https://bcdn.docswell.com/page/YJ9WWM1VJ3.jpg)

Sample code
Available on GitHub:
shu223/Metal-SDF-Examples


# Page. 18

![Page Image](https://bcdn.docswell.com/page/GJ8NNL44ED.jpg)

Representing Shapes
with &quot;Distance&quot;


# Page. 19

![Page Image](https://bcdn.docswell.com/page/LJLPPL6VER.jpg)

Signed Distance Function (SDF)
Function Returning the Distance to a Shape
• Returns 0 for points on the
contour of the shape
• Positive values for points
outside the shape
• Negative values for points
inside the shape


# Page. 20

![Page Image](https://bcdn.docswell.com/page/47M44M5NEW.jpg)

SDF of a Circle for P(x, y)


# Page. 21

![Page Image](https://bcdn.docswell.com/page/P7RWWV34E9.jpg)

Implementing SDF of a Circle
⬇ Metal Shader Language (MSL)
float circleSDF(float2 p, float2 c, float r) {
return length(p - c) - r;
}


# Page. 22

![Page Image](https://bcdn.docswell.com/page/PJXPPZ4ZEX.jpg)

Rendering Circle SDF with MSL
float circleSDF(float2 p, float2 c, float r){
return length(p - c) - r;
}
float contour(float v) {
return step(abs(v), 0.008);
}
[[ stitchable ]] half4 circleShader(float2 position,
half4 color,
float4 boundingRect)
{
float2 p = (position.xy * 2.0 - boundingRect.zw) / min(boundingRect.z, boundingRect.w);
half3 rgb = contour(circleSDF(p, float2(0.0), 0.9));
return half4(rgb, 1);
}
Sample code: circleShader.metal


# Page. 23

![Page Image](https://bcdn.docswell.com/page/3JKDD8ZV7D.jpg)



# Page. 24

![Page Image](https://bcdn.docswell.com/page/LE3RR2XQ75.jpg)

Implementing SDF of a Sphere
float circleSDF(float2 p, float2 c, float r){
return length(p - c) - r;
}
⬇
float sphereSDF(float3 p, float3 c, float r) {
return length(p - c) - r;
}


# Page. 25

![Page Image](https://bcdn.docswell.com/page/8EDYYZ2WEG.jpg)

Rendering Sphere SDF
with MSL
float sphereSDF(float3 p, float3 c, float r) {
return length(p - c) - r;
}
!
Not explain today about 3D graphics...
(Camera, Lighting, Ray casting / Ray
marching)
Sample code: mathShader_8_6.metal


# Page. 26

![Page Image](https://bcdn.docswell.com/page/V7P66D1XJ8.jpg)

Recap on SDF
• SDF is a function that returns the distance to a shape.
• It enables the representing shapes using &quot;distance&quot;.
• Learned the SDF of a circle and sphere, and their
implementations in MSL.


# Page. 27

![Page Image](https://bcdn.docswell.com/page/2JV331Y3EQ.jpg)

Controlling SDF Shapes


# Page. 28

![Page Image](https://bcdn.docswell.com/page/5EG3329Y7L.jpg)

Combining Shapes
The union of SDFs can be calculated
with min(d1, d2)
// Circle SDF 1
float d1 = circleSDF(p, float2(0, 0.5), 0.9);
// Circle SDF 2
float d2 = circleSDF(p, float2(0, -0.5), 0.5);
// The union of SDFs
float u = min(d1, d2);
→ Enable SDF shapes to be combined.
Sample code: minCircles.metal


# Page. 29

![Page Image](https://bcdn.docswell.com/page/4JQ55PW67P.jpg)

Example of combining shapes using
min:
float d = 1.0;
for (float i = 0.0; i &lt; 6.0; i++)
float3 cent = float3(cos(PI *
sin(PI *
0.0);
d = min(d, sphereSDF(p, cent,
}
{
i / 3.0),
i / 3.0),
0.2));
→ Represents six spheres with a single
SDF.


# Page. 30

![Page Image](https://bcdn.docswell.com/page/K7499YKME1.jpg)

Morphing
mix(d1, d2, a) enables Morphing
between Shapes.
• d1: SDF representing one sphere
• d2: SDF representing six spheres
• a: Cycles from 0.0 to 1.0 over time
float a = abs(mod(time, 2.0) - 1.0);
Sample code: mathShader_9_2.metal


# Page. 31

![Page Image](https://bcdn.docswell.com/page/LJ1KK6XY7G.jpg)

Smooth Union
smin(d1, d2, k) enables a &quot;smooth&quot;
union between shapes.
// A min function that interpolates the junction for a smooth SDF union
float smin(float a, float b, float k) {
float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
return mix(b, a, h) - k * h * (1.0 - h);
}
(The derivation process of this formula is on p129–130)
• d1: A smaller sphere
• d2: A larger sphere
• k: From left, 0.1, 0.3, 0.5
Sample code: mathShader_9_3.metal


# Page. 32

![Page Image](https://bcdn.docswell.com/page/GJWDDWN172.jpg)

Summary
• Using SDF allows for representing shapes with &quot;distance.&quot;
• → Enable Shape Animations with Simple Equations and
Functions.
Sample code on GitHub: shu223/Metal-SDF-Examples


