0% found this document useful (0 votes)
43 views163 pages

rwtexture3d in Unity Graphics

Uploaded by

hidane0v0
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
43 views163 pages

rwtexture3d in Unity Graphics

Uploaded by

hidane0v0
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Unity Graphics Programming

vol.3

IndieVisualLab

2018-10-08 IndieVisualLab

1
Unity Unity

tips
github
[Link]

Processing openFrameworks
3DCG Unity
3DCG

IndieVisualLab (& )
Unity
Unity
Unity

Compute Shader Geometry Shader


DirectX11 CPU
(C#)

github issue

2
Web [Link]
1FAIpQLSdxeansJvQGTWfZTBN_2RTuCK_kRqhA6QHTZKVXHCijQnC8zw/viewform
[Link]@[Link]

3
2

1 Baking Skinned Animation to Texture 7


1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2 SkinedMeshRenderer 5000 . . 8
1.3 SkinnedMeshRenderer
. . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4 . . . . . . . . . . . . . . . . . . . . 13
1.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.6 5000 . . . . . . . . . . . . . . 27
1.7 . . . . . . . . . . . . . . . . . . . . . . . . . . 28
1.8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

2 Gravitational N-Body Simulation 30


2.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.2 N-Body . . . . . . . . . . . . . . . . . . . . 31
2.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
2.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.6 . . . . . . . . . . . . . . . . . . . . . . . . . 43
2.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
2.8 . . . . . . . . . . . . . . . . . . . . 47
2.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
2.10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

3 ScreenSpaceFluidRendering 49
3.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3.2 Screen Space Fluid Rendering . . . . . . . . . . . . . . . . . 49
3.3 Deferred Rendering , 50

4
3.4 G-Buffer . . . . . . . . . . . . . . . . . . . 52
3.5 CommandBuffer . . . . . . . . . . . . . . . . . . . . . . . 53
3.6 . . . . . . . . . . . . . . . . . . . . . . . 53
3.7 . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
3.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

4 GPU-Based Cellular Growth Simulation 69


4.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
4.2 . . . . . . . . . . . . . . . . . . 70
4.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
4.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
4.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99

5 Reaction Diffusion 100


5.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
5.2 Reaction Diffusion . . . . . . . . . . . . . . . . . . . . . . . . 100
5.3 Unity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
5.4 . . . . . . . . . . . . . . . . . . . . . . . . 109
5.5 Surface Shader . . . . . . . . . . . . . . . . . . . . 113
5.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
5.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
5.8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

6 Strange Attractor 121


6.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
6.2 Strange Attractor . . . . . . . . . . . . . . . . . . . . . . . . 121
6.3 Lorenz Attractor . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
6.4 Thomas’ Cyclically Symmetric Attractor . . . . . . . . . . . . . . 127
6.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
6.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

7 Portal Unity 132


7.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
7.2 . . . . . . . . . . . . . . . . . . . . . . . . . . 132
7.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
7.4 VirtualCamera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
7.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143

5
7.6 . . . . . . . . . . . . . . . . . . . . . . . . . 145
7.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
7.8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149

8 150
8.1 . . . . . . . . . . . . . . . . . . . . . . . 151
8.2 . . . . . . . . . . . . . . . . . . . . . . . . . 151
8.3 . . . . . . . . . . . . . . . . . . . . . . . . . 153
8.4 . . . . . . . . . . . . . . . . . . . . . . . . . . 156
8.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

158

6
1

Baking Skinned Animation to


Texture

1.1

1.1

Unity Animator
SkinnedMeshRenderer

7
1 Baking Skinned Animation to Texture

Animator SkinnedMeshRenderer
GPU

SkinnedMeshRenderer
1

Twitter @sugi_cho
(._.)

1.2 SkinedMeshRenderer
5000
5000
1890
3D

8
1.2 SkinedMeshRenderer 5000

1.2

FPS 8.8
1.3

9
1 Baking Skinned Animation to Texture

1.3 5000

Unity
Window Profiler : Ctr+7
Add Profiler GPU GPU Usage
GPU Usage

GPU Usage

10
1.2 SkinedMeshRenderer 5000

1.4 Profiler Window (GPU Usage)

CPU GPU CPU


GPU 1.4 GPU
7 [Link]
[Link]
GPU
GPU CPU
Usage [Link] [Link]
nder
PlayerSettings GPU Skinning
GPU CPU CPU
FPS GPU CPU
GPU GPU
CPU CPU
GPU

11
1 Baking Skinned Animation to Texture

1.3 SkinnedMeshRenderer

SkinnedMeshRenderer
[Link](Mesh)

1.1 [Link]() Example

1: Animator animator;
2: SkinnedMeshRenderer skinedMesh;
3: List<Mesh> meshList;
4:
5: void Start(){
6: animator = GetComponent<Animator>();
7: skinnedMesh = GetComponentInChildren<SkinnedMeshRenderer>();
8: meshList = new List<Mesh>();
9: [Link]("Run");
10: }
11:
12: void Update(){
13: var mesh = new Mesh();
14: [Link](mesh);
15: //mesh
16: [Link](mesh);
17: }

Animator Run SkinnedMeshRenderer


Mesh meshList
1.1
meshList
[Link] SkinnedMeshRenderer

12
1.4

1.4
Mesh
[Link], [Link]

1.4.1 Vector3
Vector3

1.2

1.2 Update Mesh

1: Mesh objMesh;
2: List<Vector3>[] vertecesLists;
3: List<Vector3>[] normalsLists;
4: //
5: //[Link](List<Vector3>)
6:
7: void Start(){
8: objMesh = GetComponent<MeshFilter>().mesh;
9: [Link]();
10: }
11:
12: void Update(){
13: var frame = xx;
14: //
15:
16: [Link](vertecesLists[frame]);
17: [Link](normalsLists[frame]);
18: }

CPU

VertexTextureFetch

CPU

13
1 Baking Skinned Animation to Texture

1.4.2

Unity Mesh Unity 3D


UV [Link]
ices Vector3
1.1
Unity Texture2D ([Link])
[Link] (Color)
1.2
1.1 Vector3
x float x
y float y
z float z

1.2 Color
r float
g float
b float
a float

[Link] 1.1 x,y,z Texture2D


1.2 r,g,b EditorScript TextureAsset

1.3
1.3

1: public void CreateTex(Mesh sourceMesh)


2: {
3: var vertCount = [Link];
4: var width = [Link]([Link](vertCount));
5: var height = [Link]((float)vertCount / width);
6: // width,height
7:
8: posTex = new Texture2D(width, height, [Link], false);
9: normTex = new Texture2D(width, height, [Link], false);
10: //Color[] Texture2D

14
1.4

11: //[Link] Float


12:
13: var vertices = [Link];
14: var normals = [Link];
15: var posColors = new Color[width * height];
16: var normColors = new Color[width * height];
17: //
18:
19: for (var i = 0; i < vertCount; i++)
20: {
21: posColors[i] = new Color(
22: vertices[i].x,
23: vertices[i].y,
24: vertices[i].z
25: );
26: normColors[i] = new Color(
27: normals[i].x,
28: normals[i].y,
29: normals[i].z
30: );
31: }
32: // [Link] = [Link]
33: // (Color[])
34:
35: [Link](posColors);
36: [Link](normColors);
37: [Link]();
38: [Link]();
39: //
40: }

Mesh

15
1 Baking Skinned Animation to Texture

1.5 Mesh Texture

Index

1.5
Unity [Link](Color[]) ColorForm
at.RGBA32,ARGB32,RGB24,Alpha8
Fixed
RGBAHalf, RGBAFloat
1 Clamp
Color RGB
1/256

1.4.3 [Link]()
[Link]
(gameObject, time); GameObject

16
1.5

AnimationClip Animation
Animator Animation Animator

AnimationClip

1.5

• [Link]
• [Link]
• [Link]

AnimationClipTextureBaker Animation Animator Anima-


tionClip AnimationClip
ComputeBuffer AnimationClip Mesh
ComputeBuffer MeshInfo-
[Link]
ComputeShader
[Link]
Shader

17
1 Baking Skinned Animation to Texture

18

1.6 AnimationClipTextureBaker Inspector


1.5

AnimationClipTextureBaker
ComputeShader Sh
ader AnimationClip Clips
1.6

1.7

ContextMenuAttribute Unity

bake
texture Bake 1.6

1.4 [Link]

1: using [Link];
2: using [Link];
3: using UnityEngine;
4:
5: #if UNITY_EDITOR
6: using UnityEditor;

19
1 Baking Skinned Animation to Texture

7: using [Link];
8: #endif
9:
10: public class AnimationClipTextureBaker : MonoBehaviour
11: {
12:
13: public ComputeShader infoTexGen;
14: public Shader playShader;
15: public AnimationClip[] clips;
16:
17: //
18: public struct VertInfo
19: {
20: public Vector3 position;
21: public Vector3 normal;
22: }
23:
24: //Reset() GameObject
25: private void Reset()
26: {
27: var animation = GetComponent<Animation>();
28: var animator = GetComponent<Animator>();
29:
30: if (animation != null)
31: {
32: clips = new AnimationClip[[Link]()];
33: var i = 0;
34: foreach (AnimationState state in animation)
35: clips[i++] = [Link];
36: }
37: else if (animator != null)
38: clips = [Link];
39: //Animation Animator AnimationClip

40: }
41:
42: [ContextMenu("bake texture")]
43: void Bake()
44: {
45: var skin = GetComponentInChildren<SkinnedMeshRenderer>();
46: var vCount = [Link];
47: var texWidth = [Link](vCount);
48: var mesh = new Mesh();
49:
50: foreach (var clip in clips)
51: {
52: var frames = [Link]((int)([Link] / 0.05f));
53: var dt = [Link] / frames;
54: var infoList = new List<VertInfo>();
55:
56: var pRt = new RenderTexture(texWidth, frames,
57: 0, [Link]);
58: [Link] = [Link]("{0}.{1}.posTex", name, [Link]);
59: var nRt = new RenderTexture(texWidth, frames,
60: 0, [Link]);
61: [Link] = [Link]("{0}.{1}.normTex", name, [Link]);
62: foreach (var rt in new[] { pRt, nRt })
63: {

20
1.5

64: [Link] = true;


65: [Link]();
66: [Link] = rt;
67: [Link](true, true, [Link]);
68: }
69: //
70:
71: for (var i = 0; i < frames; i++)
72: {
73: [Link](gameObject, dt * i);
74: //AnimationClip GameObject
75: [Link](mesh);
76: //BakeMesh() Skinning
77:
78: [Link]([Link](0, vCount)
79: .Select(idx => new VertInfo()
80: {
81: position = [Link][idx],
82: normal = [Link][idx]
83: })
84: );
85: //
86: }
87: var buffer = new ComputeBuffer(
88: [Link],
89: [Link](
90: typeof(VertInfo)
91: )
92: );
93: [Link]([Link]());
94: // ComputeBuffer
95:
96: var kernel = [Link]("CSMain");
97: uint x, y, z;
98: [Link](
99: kernel,
100: out x,
101: out y,
102: out z
103: );
104:
105: [Link]("VertCount", vCount);
106: [Link](kernel, "Info", buffer);
107: [Link](kernel, "OutPosition", pRt);
108: [Link](kernel, "OutNormal", nRt);
109: [Link](
110: kernel,
111: vCount / (int)x + 1,
112: frames / (int)y + 1,
113: 1
114: );
115: //ComputeShader
116:
117: [Link]();
118:
119: //
120: #if UNITY_EDITOR
121: var folderName = "BakedAnimationTex";

21
1 Baking Skinned Animation to Texture

122: var folderPath = [Link]("Assets", folderName);


123: if (![Link](folderPath))
124: [Link]("Assets", folderName);
125:
126: var subFolder = name;
127: var subFolderPath = [Link](folderPath, subFolder);
128: if (![Link](subFolderPath))
129: [Link](folderPath, subFolder);
130:
131: var posTex = [Link](pRt);
132: var normTex = [Link](nRt);
133: [Link](pRt, posTex);
134: [Link](nRt, normTex);
135:
136: var mat = new Material(playShader);
137: [Link]("_MainTex", [Link]);
138: [Link]("_PosTex", posTex);
139: [Link]("_NmlTex", normTex);
140: [Link]("_Length", [Link]);
141: if ([Link] == [Link])
142: {
143: [Link]("_Loop", 1f);
144: [Link]("ANIM_LOOP");
145: }
146:
147: var go = new GameObject(name + "." + [Link]);
148: [Link]<MeshRenderer>().sharedMaterial = mat;
149: [Link]<MeshFilter>().sharedMesh = [Link];
150: // Prefab
151:
152: [Link](posTex,
153: [Link](subFolderPath, [Link] + ".asset"));
154: [Link](normTex,
155: [Link](subFolderPath, [Link] + ".asset"));
156: [Link](mat,
157: [Link](subFolderPath,
158: [Link]("{0}.{1}.[Link]", name, [Link])));
159: [Link](
160: [Link](folderPath, [Link] + ".prefab")
161: .Replace("\\", "/"), go);
162: [Link]();
163: [Link]();
164: #endif
165: }
166: }
167: }

RenderTexture GPU [Link](r


t,tex2d); Texture2D UnityAsset

1.4 119,120
ComputeShader
GPU

22
1.5

1.5

1.5 [Link]

1: #pragma kernel CSMain


2:
3: struct MeshInfo{
4: float3 position;
5: float3 normal;
6: };
7:
8: RWTexture2D<float4> OutPosition;
9: RWTexture2D<float4> OutNormal;
10: StructuredBuffer<MeshInfo> Info;
11: int VertCount;
12:
13: [numthreads(8,8,1)]
14: void CSMain (uint3 id : SV_DispatchThreadID)
15: {
16: int index = id.y * VertCount + id.x;
17: MeshInfo info = Info[index];
18:
19: OutPosition[[Link]] = float4([Link], 1.0);
20: OutNormal[[Link]] = float4([Link], 1.0);
21: // x ID y
22: }

1.8

1.8

x
y
uv.y

[Link] = Bilinear

23
1 Baking Skinned Animation to Texture

Shader

Run W
rapMode = Repeat

WrapMode = Clamp
Shader
1.6
1.6 [Link]

1: Shader "Unlit/TextureAnimPlayer"
2: {
3: Properties
4: {
5: _MainTex ("Texture", 2D) = "white" {}
6: _PosTex("position texture", 2D) = "black"{}
7: _NmlTex("normal texture", 2D) = "white"{}
8: _DT ("delta time", float) = 0e
9:
10: _Length ("animation length", Float) = 1
11: [Toggle(ANIM_LOOP)] _Loop("loop", Float) = 0
12: }
13: SubShader
14: {
15: Tags { "RenderType"="Opaque" }
16: LOD 100 Cull Off
17:
18: Pass
19: {
20: CGPROGRAM
21: #pragma vertex vert
22: #pragma fragment frag
23: #pragma multi_compile ___ ANIM_LOOP
24: //
25:
26: #include "[Link]"
27:
28: #define ts _PosTex_TexelSize
29:
30: struct appdata
31: {
32: float2 uv : TEXCOORD0;
33: };
34:
35: struct v2f
36: {
37: float2 uv : TEXCOORD0;
38: float3 normal : TEXCOORD1;

24
1.5

39: float4 vertex : SV_POSITION;


40: };
41:
42: sampler2D _MainTex, _PosTex, _NmlTex;
43: float4 _PosTex_TexelSize;
44: float _Length, _DT;
45:
46: v2f vert (appdata v, uint vid : SV_VertexID)
47: //SV_VertexID ID
48: {
49: float t = (_Time.y - _DT) / _Length;
50: #if ANIM_LOOP
51: t = fmod(t, 1.0);
52: #else
53: t = saturate(t);
54: #endif
55:
56: float x = (vid + 0.5) * ts.x;
57: float y = t;
58: //uv.x ID
59: //uv.y (t)
60:
61: float4 pos = tex2Dlod(
62: _PosTex,
63: float4(x, y, 0, 0)
64: );
65: float3 normal = tex2Dlod(
66: _NmlTex,
67: float4(x, y, 0, 0)
68: );
69: //
70:
71: v2f o;
72: [Link] = UnityObjectToClipPos(pos);
73: [Link] = UnityObjectToWorldNormal(normal);
74: [Link] = [Link];
75: return o;
76: }
77:
78: half4 frag (v2f i) : SV_Target
79: {
80: half diff = dot(
81: [Link],
82: float3(0, 1, 0)
83: ) * 0.5 + 0.5;
84: half4 col = tex2D(_MainTex, [Link]);
85: return diff * col;
86: }
87: ENDCG
88: }
89: }
90: }

Shader VertexTextureFetch VTF

25
1 Baking Skinned Animation to Texture

ID SV_Ve
rtexID
appdata uv appdata P
OSITION,NORMAL
UV uv.y
0 1.0
uv.x vid uv.x = (vid + 0.5) * _TexelSize.
x 0.5
Bilinear (n + 0.5) /
ID
0.5

{TextureName}_TexelSize float4
1.7 (Unity )

x 1.0/width
y 1.0/height
z width
w height

26
1.6 5000

1.6 5000

1.9 5000

SkinnedMeshRenderer Renderer
FPS
8 56.4 1.9
PC GPU GeForce MX150 NVIDIA Pascal GPU

27
1 Baking Skinned Animation to Texture

SkinnedMeshRenderer GPU
Shader

Grap
[Link]() 4000
Shader GitHub

1.7

Shader AnimatorController

4K 8K 16K
1

VertexShader
[Link] C
[Link]

AnimatorController Unity

28
1.8

1.8


• GPU GPU

29
2

Gravitational N-Body
Simulation

2.1

Gravitational N-Body Simulation GPU

2.1 Result

[Link]

30
2.2 N-Body

Assets/NBodySimulation

2.2 N-Body
N N-Body
N-Body

N-Body

N-Body



2.3

Mm
f =G (2.1)
r2
f G M, m 2
r 2 ( )

Unity 3
2 ( i, j )

m i mj r ij
f ij = G · (2.2)
∥r ij ∥2 ∥r ij ∥

f ij i j mi , m j 2
rij j i

31
2 Gravitational N-Body Simulation

2 1 (i)
Fi
! ! mj r ij
Fi = f ij = Gmi · (2.3)
∥r ij ∥3
j∈N j∈N

Softening ε

! mj r ij
F i ≃ Gmi · 3 (2.4)
j∈N (∥r ij ∥2 + ε) 2

( 0 )
ma = f

Fi
mi ai = F i =⇒ ai = (2.5)
mi

! mj r ij
ai ≃ G · 3 (2.6)
j∈N (∥r ij ∥2 + ε) 2

32
2.4

2.4
(2.6)

2.2

2.4.1
f (t)

df f (t + ∆t) − f (t)
= lim (2.7)
dt ∆t→0 ∆t

33
2 Gravitational N-Body Simulation

f(t)

傾き = 微分値

fn

fn

∆t
t
tn tn

2.3

tn
∆t
(2.7)

2.4.2

∆t

df f (t + ∆t) − f (t)
≃ (2.8)
dt ∆t
∆t
∆t

2.2

34
2.5

dx dx
x(t) dt
v(t) dt
a(t)
2.4 ( )

(2.8) 2.4

dx x(t + ∆t) − x(t)


≃ = v(t) (2.9)
dt ∆t
dv v(t + ∆t) − v(t)
≃ = a(t) (2.10)
dt ∆t
(2.9), (2.10)

x(t + ∆t) = x(t) + v(t + ∆t)∆t = x(t) + (v(t) + a(t)∆t)∆t (2.11)

t ∆t

( )
∆t (
) 1 (60fps 1/60 )

2.5
SimpleNBodySimula-
[Link]

2.5.1 CPU

(2.7) 1

[Link]

35
2 Gravitational N-Body Simulation

public struct Body


{
public Vector3 position;
public Vector3 velocity;
public float mass;
}

Byte [Link]
[Link](Type t)
[Link]

void InitBuffer()
{
// (Read/Write )
bodyBuffers = new ComputeBuffer[2];

// Body
bodyBuffers[READ] = new ComputeBuffer(numBodies,
[Link](typeof(Body)));

bodyBuffers[WRITE] = new ComputeBuffer(numBodies,


[Link](typeof(Body)));
}

0
*1

[Link]

void DistributeBodies()
{
[Link](seed);

//

*1

36
2.5

float scale = positionScale


* [Link](1, numBodies / DEFAULT_PARTICLE_NUM);

//
Body[] bodies = new Body[numBodies];

int i = 0;
while (i < numBodies)
{
//
Vector3 pos = [Link];

//
bodies[i].position = pos * scale;
bodies[i].velocity = [Link];
bodies[i].mass = [Link](0.1f, 1.0f);

i++;
}

//
bodyBuffers[READ].SetData(bodies);
bodyBuffers[WRITE].SetData(bodies);

ComputeShader ∆t
Unity [Link] GPU

[Link]

void Update()
{
//
// t
[Link]("_DeltaTime", [Link]);
//
[Link]("_Damping", damping);
// Softening
[Link]("_SofteningSquared", softeningSquared);
//
[Link]("_NumBodies", numBodies);

37
2 Gravitational N-Body Simulation

//
[Link]("_ThreadDim",
new Vector4(SIMULATION_BLOCK_SIZE, 1, 1, 0));

//
[Link]("_GroupDim",
new Vector4([Link](numBodies / SIMULATION_BLOCK_SIZE), 1, 1, 0));

//
[Link](0, "_BodiesBufferRead", bodyBuffers[READ]);
[Link](0, "_BodiesBufferWrite", bodyBuffers[WRITE]);

//
[Link](0,
[Link](numBodies / SIMULATION_BLOCK_SIZE), 1, 1);

// Read/Write ( )
Swap(bodyBuffers);
}

[Link]

void OnRenderObject()
{
[Link](0);
[Link]("_Particles"", bodyBuffers[READ]);

[Link]([Link], numBodies);
}

2.5.2 GPU
N-Body
O(n2 )
UnityGraphicsProgramming Vol1 3
SharedMemory( )

38
2.5

I/O

2.5

(DispatchThreadID)

1
( /
) 256 (SIMULA-

39
2 Gravitational N-Body Simulation

TION_BLOCK_SIZE) 5x5
256x256

Sync (Sync
) Sync

CPU ComputeShader

Body
[Link] cginc

[Link]

#include "[Link]"

//
cbuffer cb {
float _SofteningSquared, _DeltaTime, _Damping;
uint _NumBodies;
float4 _GroupDim, _ThreadDim;
};

//
StructuredBuffer<Body> _BodiesBufferRead;
RWStructuredBuffer<Body> _BodiesBufferWrite;

// ( )
groupshared Body sharedBody[SIMULATION_BLOCK_SIZE];

[Link]

float3 computeBodyForce(Body body, uint3 groupID, uint3 threadID)


{

uint start = 0; //
uint finish = _NumBodies;

float3 acc = (float3)0;

40
2.5

int currentTile = 0;

// ( )
for (uint i = start; i < finish; i += SIMULATION_BLOCK_SIZE)
{
//
// sharedBody[ ID]
// = _BodiesBufferRead[ ID * + ID]
sharedBody[threadID.x]
= _BodiesBufferRead[wrap(groupID.x + currentTile, _GroupDim.x)
* SIMULATION_BLOCK_SIZE + threadID.x];

//
GroupMemoryBarrierWithGroupSync();

//
acc = gravitation(body, acc, threadID);

GroupMemoryBarrierWithGroupSync();

currentTile++; //
}

return acc;

for

2.6 ID for

41
2 Gravitational N-Body Simulation

for
[Link]

float3 gravitation(Body body, float3 accel, uint3 threadID)


{

//
//
for (uint i = 0; i < SIMULATION_BLOCK_SIZE;)
{
accel = bodyBodyInteraction(accel, sharedBody[i], body);
i++;
}

return accel;
}

return

(2.2)
[Link]

//
float3 bodyBodyInteraction(float3 acc, Body b_i, Body b_j)
{
float3 r = b_i.position - b_j.position;

// distSqr = dot(r_ij, r_ij) + EPS^2


float distSqr = r.x * r.x + r.y * r.y + r.z * r.z;
distSqr += _SofteningSquared;

// invDistCube = 1/distSqr^(3/2)
float distSixth = distSqr * distSqr * distSqr;
float invDistCube = 1.0f / sqrt(distSixth);

// s = m_j * invDistCube
float s = b_j.mass * invDistCube;

// a_i = a_i + s * r_ij


acc += r * s;

return acc;
}

42
2.6

[Link]

[numthreads(SIMULATION_BLOCK_SIZE,1,1)]
void CSMain (
uint3 groupID : SV_GroupID, // ID
uint3 threadID : SV_GroupThreadID, // ID
uint3 DTid : SV_DispatchThreadID // ID
) {

//
uint index = DTid.x;

//
Body body = _BodiesBufferRead[index];

float3 force = computeBodyForce(body, groupID, threadID);

[Link] += force * _DeltaTime;


[Link] *= _Damping;

//
[Link] += [Link] * _DeltaTime;

_BodiesBufferWrite[index] = body;

2.6
*2 GPU

2.6.1

*2 Unity Graphics Programming Vol.1 - 5 SPH

43
2 Gravitational N-Body Simulation

( 2.8 )

Quad
1 xy Quad
*3

2.7 GeometryShader Quad

Quad *4

Quad

*3 UnityGraphicsProgramming Vol.1

*4

44
2.6

x
x y y
x
x
y

2.8

[Link]

45
2 Gravitational N-Body Simulation

[maxvertexcount(4)]
void geom(point v2g input[1], inout TriangleStream<g2f> outStream) {
g2f o;

float4 pos = input[0].pos;

float4x4 billboardMatrix = UNITY_MATRIX_V;

//
billboardMatrix._m03 = billboardMatrix._m13 =
billboardMatrix._m23 = billboardMatrix._m33 = 0;

for (int x = 0; x < 2; x++) {


for (int y = 0; y < 2; y++) {
float2 uv = float2(x, y);
[Link] = uv;

[Link] = pos
+ mul(transpose(billboardMatrix), float4((uv * 2 - float2(1, 1))
* _Scale, 0, 1));

[Link] = mul(UNITY_MATRIX_VP, [Link]);

[Link] = input[0].id;

[Link](o);
}
}

[Link]();
}

2.7

46
2.8

2.9 ( ...)

2.8
[Link] 1

[Link]

float3 computeBodyForce(Body body, uint3 groupID, uint3 threadID)


{

uint finish = _NumBodies / div; //

2.1

47
2 Gravitational N-Body Simulation

2.9
Gravitational N-Body Simulation GPU
N-Body
Unity

2.10
• GPU Gems 3 - Chapter 31. Fast N-Body Simulation with CUDA
• N -
[Link]
proceeding/galaxy_fujii.pdf
• - [Link] [Link]
html

48
3

ScreenSpaceFluidRendering

3.1
Deferred Shading
Screen Space Fluid Rendering

3.2 Screen Space Fluid Rendering

Screen Space Fluid Rendering

3.1 Screen Space Fluid Rendering

49
3 ScreenSpaceFluidRendering

3.1

Deferred Rendering

3.3 Deferred Rendering ,

2
Forward Rendering
3.2 Forward Rendering Deferred Rendering

3.2 Foward Rendering Deferred Rendering

50
3.3 Deferred Rendering ,

Forward Rendering 1
Deferred Rendering
2 G-Buffer
2

2 "Deferred " Rendering


Deferred Rendering



• G Buffer PostEffect SSAO


• MSAA


• Orthographic

Deferred Rendering Unity


Deferred Rendering

• Unity Pro
• MRT
• 3.0
• two-sided

Deferred Rendering Orthographic


Orthographic
Forward Rendering

51
3 ScreenSpaceFluidRendering

3.4 G-Buffer

2 G-Buffer Unity
G-Buffer
G-Buffer

render target format datat type


RT0 ARGB32 Diffuse color (RGB), Occulusion (A)
RT1 ARGB32 Specular color (RGB), Roughness (A)
RT2 ARGB2101010 World space normal (RGB)
RT3 ARGB2101010 Emission + (Ambient + Reflections + Lightmaps)
Z-buffer Depth + Stencil

G-Buffer

shader property name data type


_CameraGBufferTexture0 Diffuse color (RGB), occulusion (A)
_CameraGBufferTexture1 Specular color (RGB)
_CameraGBufferTexture2 World space normal (RGB)
_CameraGBufferTexture3 Emission + (Ambient + Reflections + Lightmaps)
_CameraDepthTexture Depth + Stencil

Assets/ScreenSpaceFluidRendering/Scenes/ShowG-
BufferTest G-Buffer

52
3.5 CommandBuffer

3.3 G-Buffer

3.5 CommandBuffer
CommandBuffer Unity API

CPU
GPU
GPU

Unity [Link](),
[Link]()
Unity API CommandBuffer Unity

Unity
CommandBuffer

[Link]

3.6
3DCG

53
3 ScreenSpaceFluidRendering

Homogeneous Coordinates
3 (x,y,z) (x,y,z,w) 4
Homogeneous Coordinates
4 4x4 Matrix
4x4 Matrix
4
(x/w, y/w, z/w, 1) =
(x, y, z, w)

Object Space ( , , )

World Space ,
World Space
World Space
Modeling Transform Object Space

Eye(View) Space ,
Eye Space

View Matrix View Transform World


Space

Clip Space ,
Clip Space View Matrix
field of view(FOV) near clip far clip Projection
Matrix View Space
Projection Transform

Normalized Device Coordinates


Clip Space xyz w
-1<=x<=1 -1<=y<=1 0<=z<=1
Normalized Device Coordinates
NDC Persepective Devide

54
3.7

Screen(Window) Space
Normalized Device Coordinates
Direct3D
Deferred Rendering

3.3 3DCG

3.4

3.7

Assets/ScreenSpaceFluidRendering/Scenes/ScreenSpaceFluidRendering

55
3 ScreenSpaceFluidRendering

3.7.1
Screen Space Fluid Rendering

1.
2.
3.
4.

3.7.2

[Link]
[Link]
[Link]
[Link]
RenderGBuff[Link] G-Buffer

3.7.3 CommandBuffer
[Link] OnWillRenderObject
CommandBuffer Com-
mandBuffer

[Link]

// (MeshRenderer)
void OnWillRenderObject()
{
//
var act = [Link] && enabled;
if (!act)
{
CleanUp();
return;
}
//
var cam = [Link];
if (!cam)
{
return;

56
3.7

//
// CommandBuffer
if (!_cameras.ContainsKey(cam))
{
// CommandBuffer
var buf = new CmdBufferInfo();
[Link] = [Link];
[Link] = new CommandBuffer();
[Link] = "Screen Space Fluid Renderer";
// G-Buffer
// CommandBuffer
[Link]([Link], [Link]);

// CommandBuffer
_cameras.Add(cam, buf);
}

[Link]ffer(CameraEvent evt, Render-


[Link]ffer buffer)
[Link]ffer
G-Buffer

Disable RemoveCommandBuffer
Cleanup

CommandBuffer
CommandBuff[Link]

3.7.4

[Link]

// --------------------------------------------------------------------
// 1.
// --------------------------------------------------------------------
// ID
int depthBufferId = [Link]("_DepthBuffer");
// RenderTexture

57
3 ScreenSpaceFluidRendering

[Link](depthBufferId, -1, -1, 24,


[Link], [Link]);

//
[Link]
(
new RenderTargetIdentifier(depthBufferId), //
new RenderTargetIdentifier(depthBufferId) //
);
//
[Link](true, true, [Link]);

//
_renderParticleDepthMaterial.SetFloat ("_ParticleSize", _particleSize);
// ComputeBuffer
_renderParticleDepthMaterial.SetBuffer("_ParticleDataBuffer",
_particleControllerScript.GetParticleDataBuffer());

//
[Link]
(
[Link],
_renderParticleDepthMaterial,
0,
[Link],
_particleControllerScript.GetMaxParticleNum()
);

[Link]

// --------------------------------------------------------------------
// Vertex Shader
// --------------------------------------------------------------------
v2g vert(uint id : SV_VertexID)
{
v2g o = (v2g)0;
FluidParticle fp = _ParticleDataBuffer[id];
[Link] = float4([Link], 1.0);
return o;
}

// --------------------------------------------------------------------
// Geometry Shader
// --------------------------------------------------------------------
//
static const float3 g_positions[4] =
{
float3(-1, 1, 0),
float3( 1, 1, 0),
float3(-1,-1, 0),
float3( 1,-1, 0),
};
// UV
static const float2 g_texcoords[4] =
{
float2(0, 1),

58
3.7

float2(1, 1),
float2(0, 0),
float2(1, 0),
};

[maxvertexcount(4)]
void geom(point v2g In[1], inout TriangleStream<g2f> SpriteStream)
{
g2f o = (g2f)0;
//
float3 vertpos = In[0].[Link];
// 4
[unroll]
for (int i = 0; i < 4; i++)
{
//
float3 pos = g_positions[i] * _ParticleSize;
pos = mul(unity_CameraToWorld, pos) + vertpos;
[Link] = UnityObjectToClipPos(float4(pos, 1.0));
// UV
[Link] = g_texcoords[i];
//
[Link] = UnityObjectToViewPos(float4(pos, 1.0)).xyz * float3(1, 1, 1);
//
[Link] = _ParticleSize;

[Link](o);
}
[Link]();
}

// --------------------------------------------------------------------
// Fragment Shader
// --------------------------------------------------------------------
struct fragmentOut
{
float depthBuffer : SV_Target0;
float depthStencil : SV_Depth;
};

fragmentOut frag(g2f i)
{
//
float3 N = (float3)0;
[Link] = [Link] * 2.0 - 1.0;
float radius_sq = dot([Link], [Link]);
if (radius_sq > 1.0) discard;
N.z = sqrt(1.0 - radius_sq);

//
float4 pixelPos = float4([Link] + N * [Link], 1.0);
float4 clipSpacePos = mul(UNITY_MATRIX_P, pixelPos);
//
float depth = clipSpacePos.z / clipSpacePos.w; //

fragmentOut o = (fragmentOut)0;
[Link] = depth;
[Link] = depth;

59
3 ScreenSpaceFluidRendering

return o;
}

C#
RenderTexture Command-
Buff[Link] RenderTexture
GetTemporaryRT
ID
ID Unity
int ID [Link]
ID

GetTemporaryRT 2,3 -1
Camera pixel
width, height
4 _DepthBuffer
+ 0
RenderTexture CommandBuff[Link]
ClearRenderTarget

CommandBuff[Link]

3.5

60
3.7

Vertex Geometry
Fragment
UV

3.6

3.7.5

61
3 ScreenSpaceFluidRendering

3.7

3.7.6
X Y

3.8

[Link]

62
3.7

// --------------------------------------------------------------------
// Fragment Shader
// --------------------------------------------------------------------
// UV
float3 uvToEye(float2 uv, float z)
{
float2 xyPos = uv * 2.0 - 1.0;
//
float4 clipPos = float4([Link], z, 1.0);
//
float4 viewPos = mul(unity_CameraInvProjection, clipPos);
//
[Link] = [Link] / viewPos.w;

return [Link];
}

//
float sampleDepth(float2 uv)
{
#if UNITY_REVERSED_Z
return 1.0 - tex2D(_DepthBuffer, uv).r;
#else
return tex2D(_DepthBuffer, uv).r;
#endif
}

//
float3 getEyePos(float2 uv)
{
return uvToEye(uv, sampleDepth(uv));
}

float4 frag(v2f_img i) : SV_Target


{
// UV
float2 uv = [Link];
//
float depth = tex2D(_DepthBuffer, uv);

//
#if UNITY_REVERSED_Z
if (Linear01Depth(depth) > 1.0 - 1e-3)
discard;
#else
if (Linear01Depth(depth) < 1e-3)
discard;
#endif
//
float2 ts = _DepthBuffer_TexelSize.xy;

// uv
float3 posEye = getEyePos(uv);

// x
float3 ddx = getEyePos(uv + float2(ts.x, 0.0)) - posEye;
float3 ddx2 = posEye - getEyePos(uv - float2(ts.x, 0.0));
ddx = abs(ddx.z) > abs(ddx2.z) ? ddx2 : ddx;

63
3 ScreenSpaceFluidRendering

// y
float3 ddy = getEyePos(uv + float2(0.0, ts.y)) - posEye;
float3 ddy2 = posEye - getEyePos(uv - float2(0.0, ts.y));
ddy = abs(ddy.z) > abs(ddy2.z) ? ddy2 : ddy;

//
float3 N = normalize(cross(ddx, ddy));

//
float4x4 vm = _ViewMatrix;
N = normalize(mul(vm, float4(N, 0.0)));

// (-1.0 1.0) (0.0 1.0)


float4 col = float4(N * 0.5 + 0.5, 1.0);

return col;
}

3.9

3.7.7
G-Buffer
G-Buffer

64
3.7

[Link]

// --------------------------------------------------------------------
// 4. G-Buffer
// --------------------------------------------------------------------
[Link]("_NormalBuffer", normalBufferId); //
[Link]("_DepthBuffer", depthBufferId); //

//
_renderGBufferMaterial.SetColor("_Diffuse", _diffuse );
_renderGBufferMaterial.SetColor("_Specular",
new Vector4(_specular.r, _specular.g, _specular.b, 1.0f - _roughness));
_renderGBufferMaterial.SetColor("_Emission", _emission);

// G-Buffer
[Link]
(
new RenderTargetIdentifier[4]
{
BuiltinRenderTextureType.GBuffer0, // Diffuse
BuiltinRenderTextureType.GBuffer1, // Specular + Roughness
BuiltinRenderTextureType.GBuffer2, // World Normal
BuiltinRenderTextureType.GBuffer3 // Emission
},
[Link] // Depth
);
// G-Buffer
[Link](quad, [Link], _renderGBufferMaterial);

[Link]

// GBuffer
struct gbufferOut
{
half4 diffuse : SV_Target0; //
half4 specular : SV_Target1; //
half4 normal : SV_Target2; //
half4 emission : SV_Target3; //
float depth : SV_Depth; //
};

sampler2D _DepthBuffer; //
sampler2D _NormalBuffer;//

fixed4 _Diffuse; //
fixed4 _Specular; //
float4 _Emission; //

void frag(v2f i, out gbufferOut o)


{
float2 uv = [Link] * 0.5 + 0.5;

65
3 ScreenSpaceFluidRendering

float d = tex2D(_DepthBuffer, uv).r;


float3 n = tex2D(_NormalBuffer, uv).xyz;

#if UNITY_REVERSED_Z
if (Linear01Depth(d) > 1.0 - 1e-3)
discard;
#else
if (Linear01Depth(d) < 1e-3)
discard;
#endif

[Link] = _Diffuse;
[Link] = _Specular;
[Link] = float4([Link] , 1.0);

[Link] = _Emission;
#ifndef UNITY_HDR_ON
[Link] = exp2(-[Link]);
#endif

[Link] = d;
}

SetRenderTarget G-Buffer
1 BuiltinRender-
TextureType GBuffer0 GBuffer1 GBuffer2 GBuffer3
RenderTargetIdentifier 2
CameraTarget G-Buffer

DrawMesh

3.7.8 RenderTexture
GetTemporaryRT RenderTexture Re-
leaseTemporaryRT

66
3.8

3.7.9

3.10

3.8
Deferred Shading

Deferred Rendering Unity

3DCG
Unity Deferred Rendering
CG
Forward
Rendering CG

67
3 ScreenSpaceFluidRendering

3.9
• GDC Screen Space Fluid Rendering for Games, Simon Green, NVIDIA

[Link]

• , Satoshi Kodaira

[Link]

68
4

GPU-Based Cellular Growth


Simulation

4.1
Processing*1
iGeo*2 Cell Division and Growth Algorithm
1 *3 GPU

[Link]
CellularGrowth
GPU

• Append/ConsumeStructuredBuffer GPU

• GPU
• Atomic

*1 [Link]
*2 [Link]
*3 [Link]

69
4 GPU-Based Cellular Growth Simulation

4.1 [Link]

Particle Edge

4.2
Particle Edge
2
1 Particle 1

• Growth( ):
• Repulsion( ): Particle
• Division( ): 2 Particle

70
4.3

4.2

Edge Particle Edge


Particle

4.3 Edge Particle

4.3

71
4 GPU-Based Cellular Growth Simulation

4.3.1 Particle ([Link])


Particle [Link]
Particle
Particle
[Link]

[StructLayout([Link])]
public struct Particle_t {
public Vector2 position; //
public Vector2 velocity; //
float radius; //
float threshold; //
int links; // Edge ( scene )
uint alive; //
}

Particle
Append/ConsumeStructuredBuffer GPU

Append/ConsumeStructuredBuffer
Append/ConsumeStructuredBuffer*4 *5 Direct3D11
GPU LIFO(Last In First Out : )
AppendStructuredBuffer ConsumeStructuredBuffer

GPU

Particle
[Link]

protected void Start () {


// Particle
particleBuffer = new PingPongBuffer(count, typeof(Particle_t));

*4 [Link]
appendstructuredbuffer
*5 [Link]
consumestructuredbuffer

72
4.3

//
poolBuffer = new ComputeBuffer(
count,
[Link](typeof(int)),
[Link]
);
[Link](0);
countBuffer = new ComputeBuffer(
4,
[Link](typeof(int)),
[Link]
);
[Link](countArgs);

//
dividablePoolBuffer = new ComputeBuffer(
count,
[Link](typeof(int)),
[Link]
);
[Link](0);

// Particle ( )
InitParticlesKernel();

...
}

particleBuffer PingPongBuffer
2 Particle

poolBuffer dividablePoolBuffer Append/ConsumeStructuredBuffer


ComputeBufferType ComputeBuff[Link]
Append/ConsumeStructuredBuffer

int Append/ConsumeStructuredBuffer poolBuffer

1. Particle index poolBuffer (Stack


Push)
2. Particle poolBuffer index (Stack
Pop) index particleBuffer Particle alive on

poolBuffer
int Particle index

( 4.4)

73
4 GPU-Based Cellular Growth Simulation

4.4 particleBuffer poolBuffer


particleBuffer Particle Particle
poolBuffer Particle index index
Particle

countBuffer int

Start InitParticlesKernel Particle


GPU
[Link]

protected void InitParticlesKernel()


{
var kernel = [Link]("InitParticles");
[Link](kernel, "_Particles", [Link]);

// AppendStructuredBuffer
[Link](kernel, "_ParticlePoolAppend", poolBuffer);

Dispatch1D(kernel, count);
}

[Link]

74
4.3

THREAD
void InitParticles(uint3 id : SV_DispatchThreadID)
{
uint idx = id.x;

uint count, strides;


_Particles.GetDimensions(count, strides);
if (idx >= count)
return;

// Particle
Particle p = create();
[Link] = false; // Particle
_Particles[idx] = p;

// Particle index
_ParticlePoolAppend.Append(idx);
}

particleBuffer Particle
poolBuffer Particle index

Particle
Particle Particle CellularGrowthPar-
[Link] Particle
[Link]

protected void Update() {


...
if([Link](0))
{
EmitParticlesKernel(GetMousePoint());
}
...
}

EmitParticlesKernel Particle

[Link]

protected void EmitParticlesKernel(Vector2 point, int emitCount = 32)


{
// emitCount
// _ParticlePoolConsume.Consume()

emitCount = [Link](
0,
[Link](emitCount, CopyPoolSize(poolBuffer))

75
4 GPU-Based Cellular Growth Simulation

);
if (emitCount <= 0) return;

var kernel = [Link]("EmitParticles");


[Link](kernel, "_Particles", [Link]);

// ConsumeStructuredBuffer
[Link](kernel, "_ParticlePoolConsume", poolBuffer);

[Link]("_Point", point);
[Link]("_EmitCount", emitCount);

Dispatch1D(kernel, emitCount);
}

InitParticlesKernel _ParticlePoolAppend pool-


Buffer EmitParticlesKernel _ParticlePoolConsume
Append/ConsumeStructuredBuffer

GPU (AppendStructured-
Buffer) (ConsumeStructuredBuffer)
CPU GPU
EmitParticlesKernel emitCount GetPoolSize

index
index (GPU
_ParticlePoolConsume.Consume )

[Link]

THREAD
void EmitParticles(uint3 id : SV_DispatchThreadID)
{
// _EmitCount Particle
if (id.x >= (uint) _EmitCount)
return;

// Particle index
uint idx = _ParticlePoolConsume.Consume();

Particle c = create();

// Particle
float2 offset = random_point_on_circle([Link] + float2(0, _Time));
[Link] = _Point.xy + offset;
[Link] = nrand([Link] + float2(_Time, 0));

// Particle index
_Particles[idx] = c;

76
4.3

EmitParticles Particle index


Particle particleBuffer index
Particle

Particle
Particle Particle

4.2

• Growth : Particle
• Repulsion : Particle
• Division : Particle

Growth Repulsion
Growth Repulsion Update
[Link]

protected void Update() {


...
UpdateParticlesKernel();
...
}
...
protected void UpdateParticlesKernel()
{
var kernel = [Link]("UpdateParticles");

//
[Link](kernel, "_ParticlesRead", [Link]);

//
[Link](kernel, "_Particles", [Link]);

[Link]("_Drag", drag); //
[Link]("_Limit", limit); //
[Link]("_Repulsion", repulsion); //
[Link]("_Grow", grow); //

Dispatch1D(kernel, count);

// (Ping Pong)
[Link]();

77
4 GPU-Based Cellular Growth Simulation

UpdateParticles
[Link]

THREAD
void UpdateParticles(uint3 id : SV_DispatchThreadID)
{
uint idx = id.x;

uint count, strides;


_ParticlesRead.GetDimensions(count, strides);
if (idx >= count)
return;

Particle p = _ParticlesRead[idx];

// Particle
if ([Link])
{
// Grow : Particle
[Link] = min([Link], [Link] + _DT * _Grow);

// Repulsion : Particle
for (uint i = 0; i < count; i++)
{
Particle other = _ParticlesRead[i];
if(i == idx || ![Link]) continue;

// Particle
float2 dir = [Link] - [Link];
float l = length(dir);

// Particle *_Repulsion
//
float r = ([Link] + [Link]) * _Repulsion;
if (l < r)
{
[Link] += normalize(dir) * (r - l);
}
}

float2 vel = [Link] * _DT;


float vl = length(vel);
// check if velocity length over than zero to avoid NaN position
if (vl > 0)
{
[Link] += normalize(vel) * min(vl, _Limit);

// _Drag velocity
[Link] =
normalize([Link]) *
min(

78
4.3

length([Link]) * _Drag,
_Limit
);
}
else
{
[Link] = float2(0, 0);
}
}

_Particles[idx] = p;
}

UpdateParticles Particle
(_ParticlesRead) (_Particles)

GPU
Particle
Particle
( )

UpdateParticles

(
Ping Pong )

Division
Particle
Particle

1. Particle index dividablePoolBuffer


2. dividablePoolBuffer Particle

[Link]

protected void Start() {


...
StartCoroutine(IDivider());
}

...

79
4 GPU-Based Cellular Growth Simulation

protected IEnumerator IDivider()


{
yield return 0;
while(true)
{
yield return new WaitForSeconds(divideInterval);
Divide();
}
}

protected void Divide() {


GetDividableParticlesKernel();
DivideParticlesKernel(maxDivideCount);
}

...

// Particle dividablePoolBuffer
protected void GetDividableParticlesKernel()
{
// dividablePoolBuffer
[Link](0);

var kernel = [Link]("GetDividableParticles");


[Link](kernel, "_Particles", [Link]);
[Link](kernel, "_DividablePoolAppend", dividablePoolBuffer);

Dispatch1D(kernel, count);
}

protected void DivideParticlesKernel(int maxDivideCount = 16)


{
// (maxDivideCount)
// Particle (dividablePoolBuffer )
maxDivideCount = [Link](
CopyPoolSize(dividablePoolBuffer),
maxDivideCount
);

// (maxDivideCount)
// Particle (poolBuffer )
maxDivideCount = [Link](CopyPoolSize(poolBuffer), maxDivideCount);

if (maxDivideCount <= 0) return;

var kernel = [Link]("DivideParticles");


[Link](kernel, "_Particles", [Link]);
[Link](kernel, "_ParticlePoolConsume", poolBuffer);
[Link](kernel, "_DividablePoolConsume", dividablePoolBuffer);
[Link]("_DivideCount", maxDivideCount);

Dispatch1D(kernel, count);
}

GetDividableParticles dividablePoolBuffer Par-


ticle(active Particle)
DivideParticles

80
4.3

DivideParticlesKernel

• maxDivideCount
• dividablePoolBuffer Particle
• poolBuffer Particle

[Link]

// Particle
//
bool dividable_particle(Particle p, uint idx)
{
//
float rate = ([Link] / [Link]);
return rate >= 0.95;

//
// return nrand(float2(idx, _Time)) < 0.1;
}

// Particle
uint divide_particle(uint idx, float2 offset)
{
Particle parent = _Particles[idx];
Particle child = create();

//
float rh = [Link] * 0.5;
rh = max(rh, 0.1);
[Link] = [Link] = rh;

//
float2 center = [Link];
[Link] = center - offset;
[Link] = center + offset;

//
float x = nrand(float2(_Time, idx));
[Link] = rh * lerp(1.25, 2.0, x);

// index Particle
uint cidx = _ParticlePoolConsume.Consume();
_Particles[cidx] = child;

// Particle
_Particles[idx] = parent;

return cidx;
}

uint divide_particle(uint idx)

81
4 GPU-Based Cellular Growth Simulation

{
Particle parent = _Particles[idx];

//
float2 offset =
random_point_on_circle(float2(idx, _Time)) *
[Link] * 0.25;

return divide_particle(idx, offset);


}

...

THREAD
void GetDividableParticles(uint3 id : SV_DispatchThreadID)
{
uint idx = id.x;
uint count, strides;
_Particles.GetDimensions(count, strides);
if (idx >= count)
return;

Particle p = _Particles[idx];
if ([Link] && dividable_particle(p, idx))
{
_DividablePoolAppend.Append(idx);
}
}

THREAD
void DivideParticles(uint3 id : SV_DispatchThreadID)
{
if (id.x >= _DivideCount)
return;

uint idx = _DividablePoolConsume.Consume();


divide_particle(idx);
}

82
4.3

4.5 [Link]

4.3.2 ([Link])
Particle Edge

[Link]
Edge Particle Particle

Edge
[Link]

[StructLayout([Link])]
public struct Edge_t
{
public int a, b; // Edge 2 Particle index
public Vector2 force; // 2 Particle
uint alive; //
}

Edge Particle Append/ConsumeStructuredBuffer

83
4 GPU-Based Cellular Growth Simulation

Division

1. Edge dividablePoolBuffer
2. Edge Edges 0 Particle(links 0
Particle) 2 Particle Edge
3. Edge dividablePoolBuffer Edge

Particle " Edge"


Particle
Edge Edge

Particle

Edge [Link]

[Link]

protected IEnumerator IDivider()


{
yield return 0;
while(true)
{
yield return new WaitForSeconds(divideInterval);
Divide();
}
}

protected void Divide()


{
// 1. Edge dividablePoolBuffer
GetDividableEdgesKernel();

int dividableEdgesCount = CopyPoolSize(dividablePoolBuffer);


if(dividableEdgesCount == 0)
{
// 2. Edge
// Edges 0 Particle(links 0 Particle)
// 2 Particle Edge
DivideUnconnectedParticles();
} else
{
// 3. Edge dividablePoolBuffer Edge

// ( ) Edge
switch(pattern)

84
4.3

{
case [Link]:
//
DivideEdgesClosedKernel(
dividableEdgesCount,
maxDivideCount
);
break;
case [Link]:
//
DivideEdgesBranchKernel(
dividableEdgesCount,
maxDivideCount
);
break;
}
}
}

...

protected void GetDividableEdgesKernel()


{
// Edge
[Link](0);

var kernel = [Link]("GetDividableEdges");


[Link](
kernel, "_Particles",
[Link]
);
[Link](kernel, "_Edges", [Link]);
[Link](kernel, "_DividablePoolAppend", dividablePoolBuffer);

// Particle
[Link]("_MaxLink", maxLink);

Dispatch1D(kernel, count);
}

...

protected void DivideUnconnectedParticles()


{
var kernel = [Link]("DivideUnconnectedParticles");
[Link](
kernel, "_Particles",
[Link]
);
[Link](
kernel, "_ParticlePoolConsume",
[Link]
);
[Link](kernel, "_Edges", [Link]);
[Link](kernel, "_EdgePoolConsume", [Link]);

Dispatch1D(kernel, count);
}

85
4 GPU-Based Cellular Growth Simulation

Edge (GetDividableEdges)
[Link]

//
bool dividable_edge(Edge e, uint idx)
{
Particle pa = _Particles[e.a];
Particle pb = _Particles[e.b];

// Particle (_MaxLink)
// dividable_particle
return
!([Link] >= _MaxLink && [Link] >= _MaxLink) &&
(dividable_particle(pa, e.a) && dividable_particle(pb, e.b));
}

...

// Edge
THREAD
void GetDividableEdges(uint3 id : SV_DispatchThreadID)
{
uint idx = id.x;
uint count, strides;
_Edges.GetDimensions(count, strides);
if (idx >= count)
return;

Edge e = _Edges[idx];
if ([Link] && dividable_edge(e, idx))
{
_DividablePoolAppend.Append(idx);
}
}

Edge Edge Particle


(DivideUnconnectedParticles)
[Link]

// index a Particle b Particle Edge


void connect(int a, int b)
{
// Edge Edge index
uint eidx = _EdgePoolConsume.Consume();

// Atomic ( )
// Particle
InterlockedAdd(_Particles[a].links, 1);
InterlockedAdd(_Particles[b].links, 1);

Edge e;
e.a = a;
e.b = b;
[Link] = float2(0, 0);

86
4.3

[Link] = true;
_Edges[eidx] = e;
}

...

// Edge Particle
THREAD
void DivideUnconnectedParticles(uint3 id : SV_DispatchThreadID)
{
uint count, stride;
_Particles.GetDimensions(count, stride);
if (id.x >= count)
return;

uint idx = id.x;


Particle parent = _Particles[idx];
if (![Link] || [Link] > 0)
return;

// Particle Particle
uint cidx = divide_particle(idx);

// Particle Particle Edge


connect(idx, cidx);
}

Particle Edge connect Atomic


Particle

87
4 GPU-Based Cellular Growth Simulation

Atomic (InterlockedAdd )

(
( )
)
Atomic ( )
GPU

a
HLSL Interlocked prefix
InterlockedAdd
InterlockedAdd
_Particles[index].links 1

a [Link]
advanced-stages-cs-atomic-functions

Edge dividablePoolBuffer Edge


DividePattern enum

([Link])

([Link])

88
4.3

4.6 ([Link])

[Link]

protected void DivideEdgesClosedKernel(


int dividableEdgesCount,
int maxDivideCount = 16
)
{
//
var kernel = [Link]("DivideEdgesClosed");
DivideEdgesKernel(kernel, dividableEdgesCount, maxDivideCount);
}

//
protected void DivideEdgesKernel(
int kernel,
int dividableEdgesCount,
int maxDivideCount
)
{
// Consume
// maxDivideCount
maxDivideCount = [Link](dividableEdgesCount, maxDivideCount);
maxDivideCount = [Link]([Link](), maxDivideCount);
maxDivideCount = [Link]([Link](), maxDivideCount);
if (maxDivideCount <= 0) return;

89
4 GPU-Based Cellular Growth Simulation

[Link](
kernel, "_Particles",
[Link]
);
[Link](
kernel, "_ParticlePoolConsume",
[Link]
);
[Link](kernel, "_Edges", [Link]);
[Link](kernel, "_EdgePoolConsume", [Link]);

[Link](kernel, "_DividablePoolConsume", dividablePoolBuffer);


[Link]("_DivideCount", maxDivideCount);

Dispatch1D(kernel, maxDivideCount);
}

GPU (DivideEdgesClosed)
divide_edge_closed Particle Edge

Particle 1 Particle 3
Particle 3 Edge ( 4.7)

4.7 2 Particle Particle 3

Particle 2 Particle
Edge Particle Edge
( 4.8)

90
4.3

4.8 Particle 2 Particle


Edge

[Link]

//
void divide_edge_closed(uint idx)
{
Edge e = _Edges[idx];

Particle pa = _Particles[e.a];
Particle pb = _Particles[e.b];

if (([Link] == 1) || ([Link] == 1))


{
// 3 Particle Edge
uint cidx = divide_particle(e.a);
connect(e.a, cidx);
connect(cidx, e.b);
}
else
{
// 2 Particle Particle
// Edge
float2 dir = [Link] - [Link];
float2 offset = normalize(dir) * [Link] * 0.25;
uint cidx = divide_particle(e.a, offset);

// Particle Particle
connect(e.a, cidx);

// 2 Particle Edge
// Particle Edge
InterlockedAdd(_Particles[e.a].links, -1);
InterlockedAdd(_Particles[cidx].links, 1);
e.a = cidx;
}

_Edges[idx] = e;
}

...

91
4 GPU-Based Cellular Growth Simulation

//
THREAD
void DivideEdgesClosed(uint3 id : SV_DispatchThreadID)
{
if (id.x >= _DivideCount)
return;

// Edge index
uint idx = _DividablePoolConsume.Consume();
divide_edge_closed(idx);
}

Edge

Edge 2 Particle

1. Edge 2 Particle
2. Particle Edge

[Link]

protected void Update() {


...
UpdateEdgesKernel();
SpringEdgesKernel();
...
}

...

protected void UpdateEdgesKernel()


{
// Edge
var kernel = [Link]("UpdateEdges");
[Link](
kernel, "_Particles",
[Link]
);
[Link](kernel, "_Edges", [Link]);
[Link]("_Spring", spring);

Dispatch1D(kernel, count);
}

protected void SpringEdgesKernel()


{
// Particle Edge
var kernel = [Link]("SpringEdges");
[Link](
kernel, "_Particles",

92
4.3

[Link]
);
[Link](kernel, "_Edges", [Link]);

Dispatch1D(kernel, count);
}

[Link]

THREAD
void UpdateEdges(uint3 id : SV_DispatchThreadID)
{
uint idx = id.x;
uint count, strides;
_Edges.GetDimensions(count, strides);
if (idx >= count)
return;

Edge e = _Edges[idx];

//
[Link] = float2(0, 0);

if (![Link])
{
_Edges[idx] = e;
return;
}

Particle pa = _Particles[e.a];
Particle pb = _Particles[e.b];
if (![Link] || ![Link])
{
_Edges[idx] = e;
return;
}

// 2 Particle
//
float2 dir = [Link] - [Link];
float r = [Link] + [Link];
float len = length(dir);
if (abs(len - r) > 0)
{
// ( )
float l = ((len - r) / r);
float2 f = normalize(dir) * l * _Spring;
[Link] = f;
}

_Edges[idx] = e;
}

THREAD
void SpringEdges(uint3 id : SV_DispatchThreadID)

93
4 GPU-Based Cellular Growth Simulation

{
uint idx = id.x;
uint count, strides;
_Particles.GetDimensions(count, strides);
if (idx >= count)
return;

Particle p = _Particles[idx];
if (![Link] || [Link] <= 0)
return;

//
float dif = 1.0 / [Link];

int iidx = (int)idx;

_Edges.GetDimensions(count, strides);

// Edge Particle
for (uint i = 0; i < count; i++)
{
Edge e = _Edges[i];
if (![Link])
continue;

// Edge
if (e.a == iidx)
{
[Link] -= [Link] * dif;
}
else if (e.b == iidx)
{
[Link] += [Link] * dif;
}
}

_Particles[idx] = p;
}

4.3.3
Edge (dividable_edge )

[Link] enum

([Link])
4.9

94
4.3

Particle Particle

4.9

[Link]

protected void DivideEdgesBranchKernel(


int dividableEdgesCount,
int maxDivideCount = 16
)
{
//
var kernel = [Link]("DivideEdgesBranch");
DivideEdgesKernel(kernel, dividableEdgesCount, maxDivideCount);
}

[Link]

//
void divide_edge_branch(uint idx)
{
Edge e = _Edges[idx];
Particle pa = _Particles[e.a];
Particle pb = _Particles[e.b];

// Particleindex
uint i = lerp(e.b, e.a, step([Link], [Link]));

uint cidx = divide_particle(i);


connect(i, cidx);
}

...

//
THREAD

95
4 GPU-Based Cellular Growth Simulation

void DivideEdgesBranch(uint3 id : SV_DispatchThreadID)


{
if (id.x >= _DivideCount)
return;

// Edge index
uint idx = _DividablePoolConsume.Consume();
divide_edge_branch(idx);
}

Edge
dividable_edge Particle
(_MaxLink)

4.10 _MaxLink 2 ([Link])

96
4.3

4.11 _MaxLink 3 ([Link])

97
4 GPU-Based Cellular Growth Simulation

4.12 _MaxLink 3 2
([Link])

4.4
GPU

CG Andy Lomas*6
Morphogenetic Creations [Link]*7
Computational Biology

Maxime Causeret*8 Max Cooper *9

(
Houdini )

*6 [Link]
*7 [Link]
*8 [Link]
*9 [Link]

98
4.5

2 iGeo
*10 3
3 3
3
[Link]

4.5
• [Link]
• [Link]

*10 [Link]

99
5

Reaction Diffusion

5.1

Unity ComputeShader

ComputeShader UnityGraphicsProgramming vol.1


2 ComputeShader

[Link]
ReactionDiffusion

5.2 Reaction Diffusion


Reaction Diffusion

Reaction Diffusion
Gray-Scott
Gray-Scott 1983 [Link] [Link]
U V 2

5.1 Gray-Scott Reaction

100
5.2 Reaction Diffusion

5.1 Gray-Scott Reaction

1. U Feed
2. V U Reaction V
3. V V Kill

5.2 U V

5.2 Gray-Scott Diffusion

U V
U V

∂u
= Du∆u − uv 2 + f(1−u)
∂t

∂v
= Dv∆v + uv 2 − (f + k)
∂t

101
5 Reaction Diffusion

U u V v
Du∆u Dv∆v Du Dv u v
∆u ∆v U V
Diffusion
uv 2 U V Reaction U
V
+f(1−u) U Feed
−(f + k)
V Kill
U V U V
U V U +f(1−u)
V −(f + k)
U V Du∆u Dv∆v

5.3 Unity
Unity
ReactionDiffusion2D_1

5.3.1
U V
ComputeShader ComputeBuffer

[Link]

public struct RDData


{
public float u; // U
public float v; // V
}

5.3.2
[Link]

/// <summary>
///
/// </summary>
void Initialize()

102
5.3 Unity

{
...

int wh = texWidth * texHeight; //


buffers = new ComputeBuffer[2]; // ComputeBuffer

for (int i = 0; i < [Link]; i++)


{
//
buffers[i] = new ComputeBuffer(wh, [Link](typeof(RDData)));
}

//
bufData = new RDData[wh];
bufData2 = new RDData[wh];

//
ResetBuffer();

// Seed
inputData = new Vector2[inputMax];
inputIndex = 0;
inputBuffer = new ComputeBuffer(
inputMax, [Link](typeof(Vector2))
);
}

ComputeBuffer buffers
ComputeShader

5.3.3

[Link]

//
void UpdateBuffer()
{
[Link]("_TexWidth", texWidth);
[Link]("_TexHeight", texHeight);
[Link]("_DU", du);
[Link]("_DV", dv);

[Link]("_Feed", feed);
[Link]("_K", kill);

[Link](kernelUpdate, "_BufferRead", buffers[0]);

103
5 Reaction Diffusion

[Link](kernelUpdate, "_BufferWrite", buffers[1]);


[Link](kernelUpdate,
[Link]((float)texWidth / THREAD_NUM_X),
[Link]((float)texHeight / THREAD_NUM_X),
1);

SwapBuffer();
}

C# ComputeShader
ComputeShader

[Link]

//
[numthreads(THREAD_NUM_X, THREAD_NUM_X, 1)]
void Update(uint3 id : SV_DispatchThreadID)
{

int idx = GetIndex(id.x, id.y);


float u = _BufferRead[idx].u;
float v = _BufferRead[idx].v;
float uvv = u * v * v;
float f, k;

f = _Feed;
k = _K;

_BufferWrite[idx].u = saturate(
u + (_DU * LaplaceU(id.x, id.y) - uvv + f * (1.0 - u))
);
_BufferWrite[idx].v = saturate(
v + (_DV * LaplaceV(id.x, id.y) + uvv - (k + f) * v)
);
}

GetIndex()
ComputeBuffer
[Link]

//
int GetIndex(int x, int y) {
x = (x < 0) ? x + _TexWidth : x;
x = (x >= _TexWidth) ? x - _TexWidth : x;

y = (y < 0) ? y + _TexHeight : y;
y = (y >= _TexHeight) ? y - _TexHeight : y;

return y * _TexWidth + x;
}

104
5.3 Unity

_BufferRead u v
LaplaceU LaplaceV U V

[Link]

// U
float LaplaceU(int x, int y) {
float sumU = 0;

for (int i = 0; i < 9; i++) {


int2 pos = laplaceIndex[i];
int idx = GetIndex(x + pos.x, y + pos.y);
sumU += _BufferRead[idx].u * laplacePower[i];
}

return sumU;
}

// V
float LaplaceV(int x, int y) {
float sumV = 0;

for (int i = 0; i < 9; i++) {


int2 pos = laplaceIndex[i];
int idx = GetIndex(x + pos.x, y + pos.y);
sumV += _BufferRead[idx].v * laplacePower[i];
}

return sumV;
}

u v _BufferWrite saturate 0 1

5.3.4
A C U V
A SeedNum
Seed C
[Link]

/// <summary>
/// Seed
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
void AddSeed(int x, int y)
{

105
5 Reaction Diffusion

if (inputIndex < inputMax)


{
inputData[inputIndex].x = x;
inputData[inputIndex].y = y;
inputIndex++;
}
}

inputData
[Link]

/// <summary>
/// Seed ComputeShader
/// </summary>
void AddSeedBuffer()
{
if (inputIndex > 0)
{
[Link](inputData);
[Link]("_InputNum", inputIndex);
[Link]("_TexWidth", texWidth);
[Link]("_TexHeight", texHeight);
[Link]("_SeedSize", seedSize);
[Link](kernelAddSeed, "_InputBufferRead", inputBuffer);
[Link](kernelAddSeed, "_BufferWrite", buffers[0]); // update
0
[Link](kernelAddSeed,
[Link]((float)inputIndex / (float)THREAD_NUM_X),
1,
1);
inputIndex = 0;
}
}

inputBuffer inputeData
ComputeShader
[Link]

//
[numthreads(THREAD_NUM_X, 1, 1)]
void AddSeed(uint id : SV_DispatchThreadID)
{
if (_InputNum <= id) return;

int w = _SeedSize;
int h = _SeedSize;
float radius = _SeedSize * 0.5;

int centerX = _InputBufferRead[id].x;


int centerY = _InputBufferRead[id].y;
int startX = _InputBufferRead[id].x - w / 2;
int startY = _InputBufferRead[id].y - h / 2;
for (int x = 0; x < w; x++)

106
5.3 Unity

{
for (int y = 0; y < h; y++)
{
float dis = distance(
float2(centerX, centerY),
float2(startX + x, startY + y)
);
if (dis <= radius) {
_BufferWrite[GetIndex((centerX + x), (centerY + y))].v = 1;
}
}
}
}

C# inputBuffer v 1

5.3.5 RenderTexture
RenderTexture
RenderTexture u v
RenderTexture 1
RenderTextureFormat RFloat RenderTextureFor-
[Link] 1 float RenderTexture

[Link]

/// <summary>
/// RenderTexture
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
/// <returns></returns>
RenderTexture CreateRenderTexture(int width, int height)
{
RenderTexture tex = new RenderTexture(width, height, 0,
[Link],
[Link]);
[Link] = true;
[Link] = [Link];
[Link] = [Link];
[Link]();

return tex;
}

ComputeShader RenderTexture C#
[Link]

107
5 Reaction Diffusion

/// <summary>
/// ReactionDiffusion
/// </summary>
void DrawTexture()
{
[Link]("_TexWidth", texWidth);
[Link]("_TexHeight", texHeight);
[Link](kernelDraw, "_BufferRead", buffers[0]);
[Link](kernelDraw, "_HeightMap", resultTexture);
[Link](kernelDraw,
[Link]((float)texWidth / THREAD_NUM_X),
[Link]((float)texHeight / THREAD_NUM_X),
1);
}

ComputeShader u v

[Link]

//
float GetValue(int x, int y) {
int idx = GetIndex(x, y);
float u = _BufferRead[idx].u;
float v = _BufferRead[idx].v;
return 1 - clamp(u - v, 0, 1);
}

...

//
[numthreads(THREAD_NUM_X, THREAD_NUM_X, 1)]
void Draw(uint3 id : SV_DispatchThreadID)
{
float c = GetValue(id.x, id.y);

// height map
_HeightMap[[Link]] = c;

5.3.6
Unlit Shader

[Link]

/// <summary>
///
/// </summary>
void UpdateMaterial()

108
5.4

{
[Link]("_MainTex", resultTexture);

[Link]("_Color0", bottomColor);
[Link]("_Color1", topColor);
}

[Link]

fixed4 frag (v2f i) : SV_Target


{
// sample the texture
fixed4 col = lerp(_Color0, _Color1, tex2D(_MainTex, [Link]).r);
return col;
}

5.3

5.4
Feed Kill

109
5 Reaction Diffusion

5.4.1
Feed:0.037 / Kill:0.06

5.4

5.4.2
Feed:0.03 / Kill:0.062

5.5

110
5.4

5.4.3
Feed:0.0263 / Kill:0.06

5.6

5.4.4
Feed:0.077 / Kill:0.0615

5.7

111
5 Reaction Diffusion

5.4.5
Feed:0.039 / Kill:0.058

5.8

5.4.6
Feed:0.026 / Kill:0.051

5.9

112
5.5 Surface Shader

5.4.7
Feed:0.014 / Kill:0.0477

5.10

5.5 Surface Shader


Surface Shader Unity
ReactionDiffusion2D_2

5.5.1
ReactionDiffusion

[Link] XYZ
[Link]

[Link]

void Initialize()
{
...
heightMapTexture = CreateRenderTexture(texWidth, texHeight,
[Link]); //
normalMapTexture = CreateRenderTexture(texWidth, texHeight,

113
5 Reaction Diffusion

[Link]); //
...
}

/// <summary>
/// RenderTexture
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="texFormat"></param>
/// <returns></returns>
RenderTexture CreateRenderTexture(
int width,
int height,
RenderTextureFormat texFormat)
{
RenderTexture tex = new RenderTexture(width, height, 0,
texFormat, [Link]);
[Link] = true;
[Link] = [Link];
[Link] = [Link];
[Link]();

return tex;
}

...

void DrawTexture()
{
...
[Link](kernelDraw, "_HeightMap", heightMapTexture);
[Link](kernelDraw, "_NormalMap", normalMapTexture); //

[Link](kernelDraw,
[Link]((float)texWidth / THREAD_NUM_X),
[Link]((float)texHeight / THREAD_NUM_X),
1);
}

ComputeShader

[Link]

float3 GetNormal(int x, int y) {


float3 normal = float3(0, 0, 0);
float c = GetValue(x, y);
normal.x = ((GetValue(x - 1, y) - c) - (GetValue(x + 1, y) - c));
normal.y = ((GetValue(x, y - 1) - c) - (GetValue(x, y + 1) - c));
normal.z = 1;
normal = normalize(normal) * 0.5 + 0.5;
return normal;
}

...

114
5.5 Surface Shader

//
[numthreads(THREAD_NUM_X, THREAD_NUM_X, 1)]
void Draw(uint3 id : SV_DispatchThreadID)
{
float c = GetValue(id.x, id.y);

// height map
_HeightMap[[Link]] = c;

// normal map
_NormalMap[[Link]] = float4(GetNormal(id.x, id.y), 1);
}

Surface Shader Surface


Shader Unity
surf SurfaceOutputStandard

SurfaceOutputStandard

struct SurfaceOutputStandard
{
fixed3 Albedo; // ( )
fixed3 Normal; //
half3 Emission; //
half Metallic; // 0= , 1=
half Smoothness; // 0= , 1=
half Occlusion; // ( 1)
fixed Alpha; //
};

[Link]

void surf(Input IN, inout SurfaceOutputStandard o) {

float2 uv = IN.uv_MainTex;

//
half v0 = tex2D(_MainTex, uv).x;

//
float3 norm = UnpackNormal(tex2D(_NormalTex, uv));

// A B
half p = smoothstep(_Threshold, _Threshold + _Fading, v0);

[Link] = lerp(_Color0.rgb, _Color1.rgb, p); //


[Link] = lerp(_Color0.a, _Color1.a, p); //
[Link] = lerp(_Smoothness0, _Smoothness1, p); //
[Link] = lerp(_Metallic0, _Metallic1, p); //
[Link] = normalize(float3(norm.x, norm.y, 1 - _NormalStrength)); //

115
5 Reaction Diffusion

[Link] = lerp(_Emit0 * _EmitInt0, _Emit1 * _EmitInt1, p).rgb; //

Unity unpackNormal
SurfaceOutputStandard

5.11 SurfaceShader

RGB

116
5.6

5.6
Reaction Diffusion

RenderTexture ComputeBuffer
ReactionDiffusion3D

5.6.1
RenderTexture

[Link]

RenderTexture CreateTexture(int width, int height, int depth)


{
RenderTexture tex = new RenderTexture(width, height, 0,
[Link], [Link]);
[Link] = depth;
[Link] = true;
[Link] = [Link].Tex3D;
[Link] = [Link];
[Link] = [Link];
[Link]();

return tex;
}

[Link] [Link]
[Link].Tex3D
RenderTexture
RenderTexture
Reaction Diffusion ComputeBuffer

[Link]

void Initialize()
{
...
int whd = texWidth * texHeight * texDepth;
buffers = new ComputeBuffer[2];
...
for (int i = 0; i < [Link]; i++)
{

117
5 Reaction Diffusion

buffers[i] = new ComputeBuffer(whd, [Link](typeof(RDData)));


}
...
}

5.6.2
ComputeShader RenderTex-
ture ComputeShader RWTex-
ture2D<float> RWTexture3D<float>
[Link]

RWTexture3D<float> _HeightMap; //

laplacePower

[Link]

//
static const int3 laplaceIndex[27] = {
int3(-1,-1,-1), int3(0,-1,-1), int3( 1,-1,-1),
int3(-1, 0,-1), int3(0, 0,-1), int3(1, 0,-1),
int3(-1, 1,-1), int3(0, 1,-1), int3(1, 1,-1),

int3(-1,-1, 0), int3(0,-1, 0), int3(1,-1, 0),


int3(-1, 0, 0), int3(0, 0, 0), int3(1, 0, 0),
int3(-1, 1, 0), int3(0, 1, 0), int3(1, 1, 0),

int3(-1,-1, 1), int3(0,-1, 1), int3(1,-1, 1),


int3(-1, 0, 1), int3(0, 0, 1), int3(1, 0, 1),
int3(-1, 1, 1), int3(0, 1, 1), int3(1, 1, 1),
};

//
static const float laplacePower[27] = {
0.02, 0.02, 0.02,
0.02, 0.1, 0.02,
0.02, 0.02, 0.02,

0.02, 0.1, 0.02,


0.1, -1.0, 0.1,
0.02, 0.1, 0.02,

0.02, 0.02, 0.02,


0.02, 0.1, 0.02,
0.02, 0.02, 0.02
};

118
5.6

//
int GetIndex(int x, int y, int z) {
x = (x < 0) ? x + _TexWidth : x;
x = (x >= _TexWidth) ? x - _TexWidth : x;

y = (y < 0) ? y + _TexHeight : y;
y = (y >= _TexHeight) ? y - _TexHeight : y;

z = (z < 0) ? z + _TexDepth : z;
z = (z >= _TexDepth) ? z - _TexDepth : z;

return z * _TexWidth * _TexHeight + y * _TexWidth + x;


}

// U
float LaplaceU(int x, int y, int z) {
float sumU = 0;

for (int i = 0; i < 27; i++) {


int3 pos = laplaceIndex[i];

int idx = GetIndex(x + pos.x, y + pos.y, z + pos.z);


sumU += _BufferRead[idx].u * laplacePower[i];
}
return sumU;
}

// V
float LaplaceV(int x, int y, int z) {
float sumV = 0;

for (int i = 0; i < 27; i++) {


int3 pos = laplaceIndex[i];
int idx = GetIndex(x + pos.x, y + pos.y, z + pos.z);
sumV += _BufferRead[idx].v * laplacePower[i];
}
return sumV;
}

5.6.3
RenderTexture
Unlit Shader Surface Shader

Unity Graphics Programming Vol.1

119
5 Reaction Diffusion

*1

5.12 Reaction Diffusion

5.7
Gray-Scott Feed
Kill

Reaction Diffusion Nakama Kouhei DIFFU-


SION *2 Kitahara Nobutaka Reaction-Diffusion *3
Reaction Diffusion

5.8
• Reaction-Diffusion Tutorial [Link]
• Reaction diffusion system Gray-Scott model
[Link]

*1 Tips [Link]
*2 DIFFUSION [Link]
*3 Reaction-Diffusion [Link]

120
6

Strange Attractor

6.1
Strange Attractor
Unity GPU

[Link]
StrangeAttractors

6.1.1
• ComputeShader 5.0
• Unity2018.2.9f1

6.2 Strange Attractor

Attractor

Strange Attractor
*1 Lorenz Attractor *2 Thomas’ Cyclically
Symmetric Attractor

*1 Lorenz, E. N. Deterministic Nonperiodic Flow, Journal of Atmospheric Sciences, Vol.20,


pp.130-141, 1963.
*2 Thomas, Ren 1999 . "Deterministic chaos seen in terms of feedback circuits: Analysis,
synthesis, ’labyrinth chaos’". Int. J. Bifurcation and Chaos. 9 10 : 1889 1905.

121
6 Strange Attractor

6.3 Lorenz Attractor


Edward N
Lorenz 1972 *3 1

Lorenz 1963 Lorenz Attractor

6.1 Lorenz attractor

*3 [Link]

122
6.3 Lorenz Attractor

6.2 Lorenz attractor

6.3.1 Lorenz
Lorenz

dx
= −px + py
dt
dy
= −xz + rx − y
dt
dz
= xy − bz
dt

p r b p=10 r=28 b=8/3


Strange Attractor

123
6 Strange Attractor

6.3.2 Lorenz Attractor


Lorenz

[Link]

protected struct Params


{
Vector3 emitPos;
Vector3 position;
Vector3 velocity; // xyz = velocity, w = velocity coef;
float life;
Vector2 size; // x = current size, y = target size.
Vector4 color;

public Params(Vector3 emitPos, float size, Color color)


{
[Link] = emitPos;
[Link] = [Link];
[Link] = [Link];
[Link] = 0;
[Link] = new Vector2(0, size);
[Link] = color;
}
}

Strange Attractor
[Link]

ComputeBuffer

[Link]

protected sealed override void InitializeComputeBuffer()


{
if (cBuffer != null) [Link]();

cBuffer = new ComputeBuffer(instanceCount, [Link](typeof(Params)));


Params[] parameters = new Params[[Link]];
for (int i = 0; i < instanceCount; i++)
{
var normalize = (float)i / instanceCount;
var color = [Link](normalize);
parameters[i] = new Params([Link] *
emitterSize * normalize, particleSize, color);
}
[Link](parameters);
}

124
6.3 Lorenz Attractor

[Link] InitializeCompute-
Buffer [Link]
Unity
gradient emitterSize particleSize
Params ComputeBuffer cBuffer SetData
id
id
Strange Attractor

LorenzAttrator p r b

[Link]

[SerializeField, Tooltip("Default is 10")]


float p = 10f;
[SerializeField, Tooltip("Default is 28")]
float r = 28f;
[SerializeField, Tooltip("Default is 8/3")]
float b = 2.666667f;

private int pId, rId, bId;


private string pProp = "p", rProp = "r", bProp = "b";

protected override void InitializeShaderUniforms()


{
pId = [Link](pProp);
rId = [Link](rProp);
bId = [Link](bProp);
}

protected override void UpdateShaderUniforms()


{
[Link](pId, p);
[Link](rId, r);
[Link](bId, b);
}

[Link]

#pragma kernel Emit


#pragma kernel Iterator

125
6 Strange Attractor

#define THREAD_X 128


#define THREAD_Y 1
#define THREAD_Z 1
#define DT 0.022

struct Params
{
float3 emitPos;
float3 position;
float3 velocity; //xyz = velocity
float life;
float2 size; // x = current size, y = target size.
float4 color;
};

RWStructuredBuffer<Params> buf;

[numthreads(THREAD_X, THREAD_Y, THREAD_Z)]


void Emit(uint id : SV_DispatchThreadID)
{
Params p = buf[id];
[Link] = (float)id * -1e-05;
[Link] = [Link];
[Link].x = 0.0;
buf[id] = p;
}

Emit [Link]
id
id

[Link] 0

[Link]

#define DT 0.022

// Lorenz Attractor parameters


float p;
float r;
float b;

//Lorenz
float3 LorenzAttractor(float3 pos)
{

126
6.4 Thomas’ Cyclically Symmetric Attractor

float dxdt = (p * (pos.y - pos.x));


float dydt = (pos.x * (r - pos.z) - pos.y);
float dzdt = (pos.x * pos.y - b * pos.z);
return float3(dxdt, dydt, dzdt) * DT;
}

[numthreads(THREAD_X, THREAD_Y, THREAD_Z)]


void Iterator(uint id : SV_DispatchThreadID)
{
Params p = buf[id];
[Link].x += DT;
// 0 1

[Link].x = [Link].y * saturate(length([Link]));


if ([Link].x > 0)
{
[Link] = LorenzAttractor([Link]);
[Link] += [Link];
}
buf[id] = p;
}

LorenzAttractor Lorenz
x,y,z

Unity

Unity [Link]

Strange Attractor

2 DT

6.4 Thomas’ Cyclically Symmetric Attractor


Ren Thomas Thomas’ Cyclically Sym-
metric Attractor

127
6 Strange Attractor

6.3 Thomas’ Cyclically Symmetric Attractor

6.4.1 Thomas’ Cyclically Symmetric

dx
= sin y − bx
dt
dy
= sin z − by
dt
dz
= sin x − bz
dt

b b ≃ 0.208186
Strange Attractor b≃0

128
6.4 Thomas’ Cyclically Symmetric Attractor

6.4.2 Thomas’ Cyclically Symmetric Attractor


Thomas’ Cyclically Symmetric

Lorenz Attractor

CPU

[Link]

protected sealed override void InitializeComputeBuffer()


{
if (cBuffer != null) [Link]();

cBuffer = new ComputeBuffer(instanceCount, [Link](typeof(Params)));


Params[] parameters = new Params[[Link]];
for (int i = 0; i < instanceCount; i++)
{
var normalize = (float)i / instanceCount;
var color = [Link](normalize);
parameters[i] = new Params([Link] *
emitterSize * normalize, particleSize, color);
}
[Link](parameters);
}

[Link]

//Thomas Attractor parameters


float b;

float3 ThomasAttractor(float3 pos)


{
float dxdt = -b * pos.x + sin(pos.y);
float dydt = -b * pos.y + sin(pos.z);
float dzdt = -b * pos.z + sin(pos.x);
return float3(dxdt, dydt, dzdt) * DT;
}

[numthreads(THREAD_X, THREAD_Y, THREAD_Z)]

129
6 Strange Attractor

void Emit(uint id : SV_DispatchThreadID)


{
Params p = buf[id];
[Link] = (float)id * -1e-05;
[Link] = [Link];
[Link].x = [Link].y;
buf[id] = p;
}

[numthreads(THREAD_X, THREAD_Y, THREAD_Z)]


void Iterator(uint id : SV_DispatchThreadID)
{
Params p = buf[id];
[Link].x += DT;
if ([Link].x > 0)
{
[Link] = ThomasAttractor([Link]);
[Link] += [Link];
}
buf[id] = p;
}

ThomasAttractor Thomas’ Cyclically Symmetric

Emit LorenzAttrator

6.5
Strange Attractor GPU

Strange Attractor

*4 UedaAttractor 2 *5 AizawaAttractor

6.6
• [Link]

*4 [Link]
*5 [Link]

130
6.6

• [Link]
• Lorenz, E. N. Deterministic Nonperiodic Flow, Journal of Atmospheric
Sciences, Vol.20, pp.130-141, 1963.
• Thomas, Ren 1999 . "Deterministic chaos seen in terms of feedback
circuits: Analysis, synthesis, ’labyrinth chaos’". Int. J. Bifurcation and
Chaos. 9 10 : 1889 1905.

131
7

Portal Unity

7.1
Portal*1 2007 Valve

Unity

[Link]
PortalGateSystem

7.2



Unity
Adam*2
E

*1 [Link]
*2 [Link]
adam-guard-lu-74842

132
7.3

• WASD


• E

Portal-
Gate

7.2.1
Unity Standard Assets *3 FirstPerson-
Character ThirdPersonChracter

Player Player
CullingMask

7.2.2
unity3d-jp playGROWnd*4
Portal

StageColl

7.3
XY
Z+

*3 [Link]
*4 [Link]

133
7 Portal Unity

7.1

Portal

[Link]

void Shot(int idx)


{
RaycastHit hit;
if ([Link]([Link],
[Link],
out hit,
[Link],
[Link](new[] { "StageColl" })))
{
var gate = gatePair[idx];
if (gate == null)
{
var go = Instantiate(gatePrefab);
gate = gatePair[idx] = [Link]<PortalGate>();

var pair = gatePair[(idx + 1) % 2];


if (pair != null)
{
[Link](pair);
[Link](gate);
}
}

[Link] = [Link];

var trans = [Link];


var normal = [Link];

134
7.3

var up = normal.y >= 0f ? [Link] : [Link];

[Link] = [Link] + normal * gatePosOffset;


[Link] = [Link](-normal, up);

[Link]();
}
}

StageColl [Link]

[Link]
Z

[Link]() normal.y
[Link]
PortalGate Y
Portal

7.2

135
7 Portal Unity

7.3

7.4 VirtualCamera
7.4.1

(VirtualCamera) RenderTexture
PortalGate
VirtualCamera

136
7.4 VirtualCamera

7.4 VirtualCamera

[Link]()
VirtualCamera
[Link]

private void OnWillRenderObject()


{

VirtualCamera pairVC;
if (![Link](cam, out pairVC))
{
if ((vc == null) || [Link] < maxGeneration)
{
pairVC = pairVCTable[cam] = CreateVirtualCamera(cam, vc);
return;
}
}

137
7 Portal Unity

7.5

1. VirtualCamera
2. VirtualCamera VirtualCamera
3. VirtualCamera VirtualCamera
4.

VirtualCamera
[Link]

[Link]

VirtualCamera CreateVirtualCamera(Camera parentCam, VirtualCamera parentVC)


{
var rootCam = parentVC?.rootCamera ?? parentCam;
var generation = parentVC?.generation + 1 ?? 1;

var go = Instantiate(virtualCameraPrefab);
[Link] = [Link] + "_virtual" + generation;
[Link](transform);

var vc = [Link]<VirtualCamera>();
[Link] = rootCam;
[Link] = parentCam;

138
7.4 VirtualCamera

[Link] = this;
[Link] = generation;

[Link]();

return vc;
}

[Link] VirtualCamera

[Link]

public void Init()


{
camera_.aspect = [Link];
camera_.fieldOfView = [Link];
camera_.nearClipPlane = [Link];
camera_.farClipPlane = [Link];
camera_.cullingMask |= [Link](new[] { PlayerLayerName });
camera_.depth = [Link] - 1;

camera_.targetTexture = tex0;
currentTex0 = true;
}

[Link]() Vir-
tualCamera CullingMask Player
[Link]
h - 1
[Link]() CommandBuffer
PostProcessingStack*5

7.4.2
VirtualCamera [Link]

[Link]

private void LateUpdate()


{
// PreviewCamera null
if (parentCamera == null)
{

*5 [Link]

139
7 Portal Unity

Destroy(gameObject);
return;
}

camera_.enabled = [Link](parentCamera);
if (camera_.enabled)
{
var parentCamTrans = [Link];
var parentGateTrans = [Link];

[Link](
transform,
[Link],
[Link]
);

UpdateCamera();
}
}

VirtualCamera
[Link]

public bool IsVisible(Camera camera)


{
var ret = false;

var pos = [Link];


var camPos = [Link];

var camToGateDir = (pos - camPos).normalized;


var dot = [Link](camToGateDir, [Link]);
if (dot > 0f)
{
var planes = [Link](camera);
ret = [Link](planes, [Link]);
}

return ret;
}

1.
Z+
2. Unity

140
7.4 VirtualCamera

[Link]()
transform

[Link]

public void UpdateTransformOnPair(


Transform trans,
Vector3 worldPos,
Quaternion worldRot
)
{
var localPos = [Link](worldPos);
var localRot = [Link]([Link]) * worldRot;

var pairGateTrans = [Link];


var gateRot = [Link];
var pos = [Link](gateRot * localPos);
var rot = [Link] * gateRot * localRot;

[Link](pos, rot);
}

1.
2. gateRot
3.
4.

gateRot

public Quaternion gateRot { get; } = [Link](0f, 180f, 0f);

Y 180 Z

public Quaternion gateRot { get; } = [Link](180f, 0f, 0f);

141
7 Portal Unity

[Link]

void UpdateCamera()
{
var pair = [Link];
var pairTrans = [Link];
var mesh = [Link]<MeshFilter>().sharedMesh;
var vtxList = [Link]
.Select(vtx => [Link](vtx)).ToList();

[Link](camera_, vtxList);

// Oblique
// pairGate = nearClipPlane pairGate
var pairGateTrans = [Link];
var clipPlane = CalcPlane(camera_,
[Link],
-[Link]);

camera_.projectionMatrix = camera_.CalculateObliqueMatrix(clipPlane);
}

Vector4 CalcPlane(Camera cam, Vector3 pos, Vector3 normal)


{
var viewMat = [Link];

var normalOnView = [Link](normal).normalized;


var posOnView = [Link](pos);

return new Vector4(


normalOnView.x,
normalOnView.y,
normalOnView.z,
-[Link](normalOnView, posOnView)
);
}

VirtualCamera
VirtualCamera
[Link]()
[Link]
VirtualCamera
[Link]
bliqueMatrix()
xyz w
Vector4

142
7.5

7.5



• 7.6
• VirtualCamera
• [Link] VirtualCamera
PortalGate

7.6

[Link]

GrabPass
{
"_BackgroundTexture"
}

GrabPass*6

7.5.1

[Link]

*6 [Link]

143
7 Portal Unity

v2f vert(appdata_img In)


{
v2f o;

float3 posWorld = mul(unity_ObjectToWorld, float4([Link], 1)).xyz;


float4 clipPos = mul(UNITY_MATRIX_VP, float4(posWorld, 1));
float4 clipPosOnMain = mul(_MainCameraViewProj, float4(posWorld, 1));

[Link] = clipPos;
[Link] = [Link];
[Link] = ComputeScreenPos(clipPosOnMain);
[Link] = ComputeGrabScreenPos([Link]);
return o;
}

2
clipPos clipPosOnMain
VirtualCamera
RenderTexture GrabPass

7.5.2

[Link]

float2 uv = [Link];
uv = (uv - 0.5) * 2; // map 0~1 to -1~1
float insideRate = (1 - length(uv)) * _OpenRate;

insideRate 1 0
_OpenRate Portal-
[Link]()
[Link]

// background
float4 grabUV = [Link];
float2 grabOffset = float2(
snoise(float3(uv, _Time.y )),
snoise(float3(uv, _Time.y + 10))
);
[Link] += grabOffset * 0.3 * insideRate;
float4 bgColor = tex2Dproj(_BackgroundTexture, grabUV);

snoise include [Link]


SimplexNoise uv grabUV
insideRate

144
7.6

[Link]

// portal other side


float2 sUV = [Link] / [Link].w;
float4 sideColor = tex2D(_MainTex, sUV);

_MainTex VirutualCamera
UV
[Link]

// color
float4 col = lerp(bgColor, sideColor, _ConnectRate);

bgColor sideColor _
ConnectRate 0 1 1

[Link]

// frame
float frame = smoothstep(0, 0.1, insideRate);
float frameColorRate = 1 - abs(frame - 0.5) * 2;
float mixRate = saturate(grabOffset.x + grabOffset.y);
float3 frameColor = lerp(_FrameColor0, _FrameColor1, mixRate);
[Link] = lerp([Link], frameColor, frameColorRate);

col.a = frame;

insideRate _FrameColor0,_FrameCol
or1

7.6
PortalObj
GameObject

7.6.1

PortalObj

145
7 Portal Unity

7.7

[Link]

private void OnTriggerStay(Collider other)


{
var gate = [Link]<PortalGate>();
if ((gate != null) && ![Link](gate) && ([Link] != null))
{
[Link](gate);
[Link]([Link], collider_, true);
}
}

private void OnTriggerExit(Collider other)


{
var gate = [Link]<PortalGate>();
if (gate != null)
{
[Link](gate);
[Link]([Link], collider_, false);
}
}

OnTriggerEnder() OnTriggerStay()
Enter
tougingGates PortalGa
[Link] [Link]
llision()
OnTriggerExit()
[Link] PortalGate
OnTriggerStay()

146
7.6

7.6.2
[Link]

private void Update()


{
var passedGate = [Link](gate =>
{
var posOnGate = [Link]([Link]);
return posOnGate.z > 0f;
});

if (passedGate != null)
{
PassGate(passedGate);
}

if ((rigidbody_ != null) && !rigidbody_.useGravity)


{
if (([Link] - ignoreGravityStartTime) > ignoreGravityTime)
{
rigidbody_.useGravity = true;
}
}
}

center Transform
PortalObj GameObject

[Link] z > 0f
touchingGates
PassGate()
PortalObj

[Link]

void PassGate(PortalGate gate)


{
[Link](transform);

if (rigidbody_ != null)
{
rigidbody_.velocity = [Link](rigidbody_.velocity);
rigidbody_.useGravity = false;
ignoreGravityStartTime = [Link];

147
7 Portal Unity

if (fpController != null)
{
fpController.m_MoveDir = [Link](fpController.m_MoveDir);
[Link]();
}
}

VirtualCamera
[Link]() Transform
RigidBody fpController

7.6.3

PortalObj

OnTriggerEn
ter(),OnCollisionEnter() [Link]()
On~Enter()
[Link]()
Enter

PortalObj

Unity

148
7.7

7.7
Portal Unity

CG

7.8
• Portal [Link]
• Adam Character Pack [Link]
com/packages/essentials/tutorial-projects/
adam-character-pack-adam-guard-lu-74842
• playGROWnd [Link]
• PostProcessingStack [Link]
PostProcessing

149
8

8.1

[Link]
OverReaction

150
8.1

8.1
OverReaction
Inspector

PhysicsScene

8.2
3

1.
2.
3.

moveEnergy

kinetic energy
move energy

Updat
e FixedUpdate
[Link]

protected void FixedUpdate()


{
[Link] = [Link] - [Link];

UpdateMoveEnergy();
UpdateDeformEnergy();
DeformMesh();

[Link] = [Link];
[Link] = [Link];
}

FixedUpdate 2
3 ~ Update

151
8

Unity PhysX( ) Fix


edUpdate Update

UpdateMoveEnergy

[Link]

protected void UpdateMoveEnergy()


{
[Link] = new Vector3()
{
x = UpdateMoveEnergy
([Link].x, [Link].x, [Link].x),

y = UpdateMoveEnergy
([Link].y, [Link].y, [Link].y),

z = UpdateMoveEnergy
([Link].z, [Link].z, [Link].z),
};
}

X, Y, Z U
pdateMoveEnergy

[Link]

protected float UpdateMoveEnergy


(float crntMove, float prevMove, float moveEnergy)
{
int crntMoveSign = Sign(crntMove);
int prevMoveSign = Sign(prevMove);
int moveEnergySign = Sign(moveEnergy);

if (crntMoveSign == 0)
{
return moveEnergy * [Link];
}

public static int Sign(float value)


{
return value == 0 ? 0 : (value > 0 ? 1 : -1);
}

152
8.3

[Link]

if (crntMoveSign != prevMoveSign)
{
return moveEnergy - crntMove;
}

[Link]

if (crntMoveSign != moveEnergySign)
{
return moveEnergy + crntMove;
}

[Link]

if (crntMoveSign < 0)
{
return [Link](crntMove * [Link],
moveEnergy * [Link]);
}
else
{
return [Link](crntMove * [Link],
moveEnergy * [Link]);
}

8.3

deformEnergy
UpdateDeformEnergy

153
8

1
0

[Link]

protected void UpdateDeformEnergy()


{
float deformEnergyVertical
= [Link]
* [Link]([Link],
[Link]);

+0.8 -0.8
1 - 0.8 = 0.2
* 0.8 1 * 1.8
[Link]

protected void UpdateDeformEnergy()


{

float deformEnergyHorizontalRatio
= deformEnergyVertical / [Link];

float deformEnergyHorizontal
= 1 - deformEnergyHorizontalRatio;

deformEnergyVertical = 1 + deformEnergyVertical;
}

154
8.3

deformEnergyHorizontal 1
deformEnergyVertical deformEnergyHorizontal
1
[Link]

protected void UpdateDeformEnergy()


{
float deformEnergyVertical
= [Link]
* [Link]([Link],
[Link]);

float deformEnergyHorizontalRatio
= deformEnergyVertical / [Link];

float deformEnergyHorizontal
= 1 - deformEnergyHorizontalRatio;

if (deformEnergyVertical < 0)
{
deformEnergyVertical = deformEnergyHorizontalRatio;
}

deformEnergyVertical = 1 + deformEnergyVertical;

[Link]

deformEnergyVertical = [Link](deformEnergyVertical,
[Link],
[Link]);

deformEnergyHorizontal = [Link](deformEnergyHorizontal,
[Link],
[Link]);

[Link] = new Vector3(deformEnergyHorizontal,


deformEnergyVertical,
deformEnergyHorizontal);

155
8

8.4

DeformMesh
GPU

deformEnergy moveEnergy

moveEnergy

[Link]

protected void DeformMesh()


{
Vector3[] deformedVertices = new Vector3[[Link]];

Quaternion crntRotation = [Link];


Quaternion crntRotationI = [Link](crntRotation);

Quaternion moveEnergyRotation
= [Link]([Link], [Link]);
Quaternion moveEnergyRotationI = [Link](moveEnergyRotation);

1.
2.
3. deformEnergy
4.
5.

deformEnergy

[Link]

for (int i = 0; i < [Link]; i++)


{
deformedVertices[i] = [Link][i];
deformedVertices[i] = crntRotation * deformedVertices[i];
deformedVertices[i] = moveEnergyRotationI * deformedVertices[i];
deformedVertices[i] = new Vector3(
deformedVertices[i].x * [Link].x,
deformedVertices[i].y * [Link].y,

156
8.5

deformedVertices[i].z * [Link].z);
deformedVertices[i] = moveEnergyRotation * deformedVertices[i];
deformedVertices[i] = crntRotationI * deformedVertices[i];
}

[Link] = deformedVertices;

8.5

157
1 Baking Skinned Animation to Texture - / @sugi_cho
Unity
=> hi@[Link]

• [Link]
• [Link]
• [Link]

2 Gravitational N-Body Simulation / @kodai100


VFX TA
VR
Twitter DM

• [Link]
• [Link]
• [Link]

3 Screen Space Fluid Rendering - / @irishoak


MV
VJ
sugi-cho mattatz Aqueduct

• [Link]
• [Link]
• [Link]
• [Link]

158
4 GPU-Based Cellular Growth Simulation - / @mattatz
Web

• [Link]
• [Link]
• [Link]

5 Reaction Diffusion - @kaiware007


Twitter
VJ

• [Link]
• [Link]
• [Link]
• [Link]

6 Strange Attractor - / @sakope

Twitter

• [Link]
• [Link]

7 Portal Unity - / @fuqunaga

• [Link]
• [Link]
• [Link]

159
8 - @XJINE

UnityShaderProgramming

• [Link]
• [Link]
• [Link]

160
Unity Graphics Programming vol.3

2018 10 8 5 v1.0.0
IndieVisualLab
IndieVisualLab
IndieVisualLab

(C) 2018 IndieVisualLab

161

You might also like