Animating Shapes with Simple Equations

1.7K Views

March 21, 24

スライド概要

yakatabune.swift での発表資料です。

profile-image

フリーランスiOSエンジニア 「エンジニアと人生」コミュニティ主宰

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

Animating Shapes with Simple Equations Shuichi Tsutsumi @shu223

2.

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

3.

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

4.

Examples of Animating Shapes

5.

3D

6.

2D

7.

How to create animations like these?

8.

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

9.

! too hard...

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

11.

! too difficult...

12.

! You don't need to do that

13.

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

15.

How can we achieve the animation with just ONE function?

16.

Explaining Step by Step

17.

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

18.

Representing Shapes with "Distance"

19.

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

20.

SDF of a Circle for P(x, y)

21.

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

22.
[beta]
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

24.

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; }

25.
[beta]
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

26.

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

27.

Controlling SDF Shapes

28.

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

29.
[beta]
Example of combining shapes using
min:
float d = 1.0;
for (float i = 0.0; i < 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.

30.

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

31.
[beta]
Smooth Union
smin(d1, d2, k) enables a "smooth"
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

32.

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