-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcatmull-clark.html
142 lines (140 loc) · 5.73 KB
/
catmull-clark.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Catmull-Clark Subdivision Surfaces</title>
</head>
<body>
<canvas width="768" height="768"></canvas>
<p>What this demo shows:</p>
<ul>
<li>
Toggle between:
<ul>
<li>A 5-face square pyramid</li>
<li>
A 16-face solid that is the (<a
href="https://en.wikipedia.org/wiki/Catmull%E2%80%93Clark_subdivision_surface"
>Catmull-Clark</a
>) subdivided mesh of the 5-face pyramid, using the formulation of
<a href="https://dl.acm.org/doi/10.1145/2077341.2077347"
>Niessner et al.</a
>
<b>Why this is cool</b>: Connectivity (at all levels of subdivision)
can be and is statically generated, but the subdivision is computed
dynamically in a compute shader. Thus we can send a small coarse
mesh from CPU to GPU, animate that coarse mesh on the CPU, and
generate its more detailed subdivision entirely on the GPU. No one
wants to animate a fine mesh.
</li>
<li>
These two surfaces don't look too similar, to be honest. That is
typical though (level 0 and level 1 aren't super close to each
other, and it's additionally possible there could be coding
mistakes). The subdivided surface at level 1 should be the proper
subdivision of the level-0 pyramid. If we kept subdividing, we would
eventually get a smooth limit surface. Autodesk was
<a
href="https://download.autodesk.com/global/docs/softimage2014/en_us/userguide/index.html?url=files/subdivs_AboutSubdivisionSurfaces.htm,topicNumber=d30e117288"
>nice to show</a
>
that I'm roughly on the right track:
<img
src="https://download.autodesk.com/global/docs/softimage2014/en_us/userguide/images/GUID-D40260F1-5A9D-4AB0-8685-D1CA0B991229-low.png"
width="100"
/>
</li>
</ul>
</li>
<li>
What is the compute? The core of Catmull-Clark subdivision is three
compute kernels, which iterate over (1) all faces (computing new "face
points"), (2) all edges (computing new "edge points"), and (3) all
vertices (computing new vertices as a function of old vertices and new
face and edge points).
</li>
<li>
Additionally, pyramid vertices are perturbed (as a function of vertex
ID) in a compute shader, which iterates over all vertices. This is
analogous to animating the base mesh on the CPU, as would occur in a
game/simulation.
</li>
<li>Rendered as indexed triangles</li>
<li>Toggle is implemented simply by binding a different index buffer</li>
<li>Vertex colors are simply the vertex normal</li>
<li>
Camera is implemented in the vertex shader; it rotates around the
pyramid. Camera code mostly swiped from
<a href="https://webgpu.github.io/webgpu-samples/?sample=rotatingCube"
>rotating cube demo</a
>.
</li>
</ul>
<p>
<a
href="https://webgpufundamentals.org/webgpu/lessons/webgpu-fundamentals.html"
>Code with which I started</a
>
</p>
<p>External includes that help make this work:</p>
<ul>
<li>
<a href="https://wgpu-matrix.org/docs/">wgpu-matrix</a> for
modelview/projection matrix operations
</li>
</ul>
<p>Things missing from WebGPU:</p>
<ul>
<li>Indexed quad rendering</li>
<li>Hardware tessellation units (not sure on this, though)</li>
</ul>
<p>What would be fun to write that I'm secretly hoping I get to write:</p>
<ul>
<li>More levels of subdivision</li>
<li>
Automatically generating all tables for that subdivision (in the CPU, at
"compile time", but really at runtime when the program is launched)
</li>
<li>More interesting inputs than a pyramid</li>
<li>
The whole point of Niessner's formulation is it supports sharp creases.
That's currently ignored in the implementation; the implementation
generates a smooth limit surface. But real subdivision surfaces may have
sharp edges and/or vertices.
</li>
<li>Adaptive subdivision (subdividing only where necessary)</li>
<li>Integrating a prefix-sum for the valence-offset tables</li>
</ul>
<p>What could make this visually better:</p>
<ul>
<li>Actual lighting (we do have normal vectors per vertex)</li>
<li>
<a href="https://webgpu.github.io/webgpu-samples/?sample=wireframe"
>Wireframe</a
>
that shows the underlying mesh
</li>
<li>Better choice of parameters that generates a smooth animation</li>
</ul>
<p>What could make the (nonexistent) UI better:</p>
<ul>
<li>
<a href="https://webgpu.github.io/webgpu-samples/?sample=cameras"
>Camera control</a
>
</li>
<li>
Setting simulation parameters in the UI rather than ~hardcoded in the
code
</li>
</ul>
<script src="./webgpufundamentals-timing.js"></script>
<!-- parses file -- this is external, not written by me -->
<script src="./OBJFile.js"></script>
<!-- builds data structure from parsed file -->
<script src="./objload.js"></script>
<!-- webgpu compute and rendering -- these are the main routines -->
<!-- eventually: On github you can turn on github pages so it will be served from jowens.github.io/webgpu-sandbox-->
<script src="https://jowens.github.io/webgpu-sandbox/catmull-clark.js" type="module"></script>
</body>
</html>