-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
474 lines (465 loc) · 25.4 KB
/
index.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<style>
body {
padding: 50px;
padding-top: 40px;
width: 1000px;
margin: auto;
text-align: left;
font-weight: 400;
font-family: 'Open Sans', sans-serif;
color: #020202;
}
h1, h2, h3, h4, h5 {
font-family: 'Source Sans Pro', sans-serif;
}
h5 {
margin-top: 20px !important;
}
ol {
list-style-type: decimal;
}
ol ol {
list-style-type: lower-latin;
}
ol ol ol {
list-style-type: lower-roman;
}
p { line-height: 1.8em; }
</style>
<title>CS 184: Hair Rendering - Briggs, Shen, Xia</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link href="https://fonts.googleapis.com/css?family=Open+Sans|Source+Sans+Pro" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body class="container">
<h1 align="middle">Realistic Hair Rendering</h1>
<h3 align="middle" style="margin-top:0px">CS184 Final Project Report</h3>
<h4 align="middle" style="margin-top:20px">Jonathan Briggs, Nick Shen, Xiling Xia</h4>
<h5 align="middle">3032095561, 3031863147, 3031835899</h5>
<hr>
<div class="container">
<h3>Abstract</h3>
<p>
In this project we set out to render hair realistically both statically and dynamically, with varying and gorgeous results. For static rendering such as the <a href="#kkay">Kajiya-Kay [1]</a> and <a href="#marsch">Marschner model [7]</a>, we built custom BSDFs on top of the <a href="#mitsuba">Mitsuba Renderer [2]</a> in order to
realistically render hair. Using the existing framework, which provided simple ray-hair intersection
functionality, we successfully implemented Kajiya Kay model, and made progress in the Marschner model. As our stretch goal, we explored GLSL dynamic fur shading using WebGL and <a href="#three">three.js</a>, and even built an <a href="http://nickshen.me/184proj/web-fur" target="_blank">interactive fur demo</a>.
</p>
<hr>
<h3>Technical Approach</h3>
<h5>Static Rendering</h5>
<p>
We created brand new hair BSDFs in Mitsuba, following the approaches of the Kajiya-Kay and Marschner models. Mitsuba provided the framework for ray tracing and hair intersection. Mitsuba came with a Kajiya-Kay styled phase function; however, it did not operate as a functional BSDF, and did not match up with the original SIGGRAPH paper we read. Thus, we ultimately decided not to use it, and instead build our own BSDF from scratch.
</p>
<h5>Kajiya-Kay</h5>
<p>
The basics of our Kajiya-Kay BSDF are as follows. First, we define the following vectors:
</p>
<ul>
<li><b>t:</b> tangent vector to the hair cylinder</li>
<li><b>l:</b> directional vector from intersection to light source</li>
<li><b>e:</b> directional vector from intersection to eye/camera</li>
</ul>
<p>
Next, we define three constants that control the lighting effects of the rendered image.
</p>
<ul>
<li><b>Ks:</b> scaling factor for specular lighting component</li>
<li><b>Kd:</b> scaling factor for diffuse lighting component</li>
<li><b>p:</b> exponent for specular lighting component</li>
</ul>
<p>
As shown in the model below, the incoming light to eye/camera is specularly reflected into the cone formed by taking
the incoming light vector, reflecting it over the normal, and rotating it around the tangent. This
outgoing ray is drawn with the label <i>e'</i>.
</p>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/kajiyakaymodel.png" align="middle" height="360px" />
<figcaption align="middle">Kajiya-Kay Model</figcaption>
</td>
</tr>
</table>
</div>
<br>
<p>
Next, we calculated the diffuse and specular terms, setting pointers as necessary. The images below
describe how these terms are discerned in the original model, and the pseudo-code equations that follow
demonstrate how we broke down each term in order to make our code simpler and more readible.
</p>
<ul>
<li>
<i> Ψ<sub>diffuse</sub> = Kd * sin(θ)
= Kd * ||cross(t, l)||</i>
</li>
<li>
<i> Ψ<sub>specular</sub> = Ks * cos(θ’ - θ)P
= Ks * (cos(θ’)cos(θ) + sin(θ’)sin(θ))P
= Ks * [ dot(t, l) * dot(-t, e) + ||cross(t, l)|| * ||sin(-t, e)|| ]<sup>P</sup></i>
</li>
</ul>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/kajiyakaydiffuse.png" align="middle" height="133px" />
<figcaption align="middle">Kajiya-Kay Diffuse Component</figcaption>
</td>
<td padding="10px 10px 10px 10px">
<img src="img/kajiyakayspecular.png" align="middle" height="133px" />
<figcaption align="middle">Kajiya-Kay Specular Component</figcaption>
</td>
</tr>
</table>
</div>
<br>
<div id="marschner">
<h5>Marschner Model</h5>
<p>The second BSDF we sought to implement was the Marschner model. In it, hair follicles are modeled as rough,
cylindrical surfaces consisting of tilted cuticle scales. This model takes into account the detail
that incident light may be reflected one or more times before exiting the hair. Therefore, reflection is
broken down into three components:
</p>
<ul>
<li><b>R:</b> simple reflection</li>
<li><b>TT:</b> one transmission</li>
<li><b>TRT:</b> two transmissions</li>
</ul>
<p>The details of this process are best described by the diagrams below:</p>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/marschnermodel0.png" align="middle" height="300px" />
<figcaption align="middle">Marschner Model Diagram</figcaption>
</td>
<td padding="10px 10px 10px 10px">
<img src="img/marschnermodel1.png" align="middle" height="300px" />
<figcaption align="middle">A Closer Look at an Individual Hair Fiber</figcaption>
</td>
</tr>
</table>
</div>
<br>
<p>
We tackled this problem by considering each scattering component individually, and summing them together,
as represented by the scattering function <i>f</i>.
</p>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/marschner_f.png" align="middle" height="100px" />
<figcaption align="middle">Scattering Functions Summed</figcaption>
</td>
<td padding="10px 10px 10px 10px">
<img src="img/marschnerf_detailed.png" align="middle" height="100px" />
<figcaption align="middle">A Closer Look at an Individual Scattering Component</figcaption>
</td>
</tr>
</table>
</div>
<br>
<p>
Each component is broken down into three major components, each of which are calculated based on the
incoming and outgoing angle of reflectance. These are outlined below:
</p>
<ul>
<li>
<b>M<sub>p</sub>:</b> describes the longitudinal scattering function.
</li>
</ul>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/marschner_m.png" align="middle" height="64px" />
<figcaption align="middle"></figcaption>
</td>
</tr>
</table>
</div>
<ul>
<li>
<b>A<sub>p</sub>:</b> describes how incident light affects a scattering mode p. This component
considers Fresnel reflection, transmission at hair-air boundary, and absorption (for <i>p >
0</i>i>). It is responsible for the color of the hair fiber.
</li>
</ul>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/marschner_a.png" align="middle" height="64px" />
<figcaption align="middle"></figcaption>
</td>
</tr>
</table>
</div>
<ul>
<li>
<b>N<sub>p</sub>:</b> describes the angular difference between the angle Φ and the third function
shown below, which calculates the net change in azimuthal direction.
</li>
</ul>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/marschner_n.png" align="middle" height="64px" />
<figcaption align="middle"></figcaption>
</td>
</tr>
</table>
</div>
</div>
<h5>Dynamic Fur Rendering by Shells and Fins Model</h5>
<p>
Lastly, we implemented our stretch goal of dynamic fur shading using WebGL and the three.js framework. In order to
maximize performance, we utilize the "shell and fin" <a href="nvidia">[NVIDIA, 4]</a> approach to dynamic fur rendering. This method uses
multiple layers, or "shells," of the mesh and stacks them at different scales in order to simulate
individual hair/fur fibers. Pixels are rendered according to a randomly generated hair distribution
texture map at each layer. Starting from a simple bear model with a standard diffuse shader, as shown
below, we constructed a photo-realistic and dynamically rendered interactive demo.
</p>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/bear_diffuse.png" align="middle" height="400px" />
<figcaption align="middle">Original bear mesh</figcaption>
</td>
<td padding="10px 10px 10px 10px">
<img src="img/rigid_fur.png" align="middle" height="400px" />
<figcaption align="middle">Random hair distribution, no deformation or alignment</figcaption>
</td>
</tr>
</table>
</div>
<br>
<p>
Initially, the fur was rigid and linear, with no deformation or correction due to gravity or the surface
normals. This led to an unrealistic model. Therefore, we defined methods to align the hair fibers to the
surface normal, and also to correct for gravity, within the vertex shader.
</p>
<pre><code>
vec3 augmented = position + vec3(fNormal) * vec3(scaling, scaling, scaling);
gl_Position = (projectionMatrix * modelViewMatrix * vec4(augmented, 1.0))
+ (vec4(displacement, 0.0) * vec4(dFactor, dFactor, dFactor, 0.0));
</code></pre>
<p>
Lastly, to more accurately model the finer characteristics of fur, we needed to add shadows, sheen, and
some controlled randomness. First, we tackled realistic shadows by implementing Phong shading. Since the
shell-based fur fibers have no mesh or sense of normals, we needed to think out of the box in order to
model shadow intersections. Therefore, we ultimately figured out that altering the Phong light intensity
on a per-pixel level produced the most accurate image. We scaled the light intensity relative to its proximity to the root of the hair, similarly to: <i>pow(layer/fullLength, 2).</i>
</p>
<p>
Our final improvement came after noticing that random fiber lengths are unrealistic and unexciting at
such a high frequency/resolution image (2048x2048). Therefore, we multiplied a modified specularity texture map (as a heuristic)
with our noise distribution together to create visually interesting, random hairs. After these improvements, we produced the
following results:
</p>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/bear_final.png" align="middle" height="330px" />
<figcaption align="middle"></figcaption>
</td>
<td padding="10px 10px 10px 10px">
<img src="img/bear_1.png" align="middle" height="330px" />
<figcaption align="middle"></figcaption>
</td>
<td padding="10px 10px 10px 10px">
<img src="img/bear_0.png" align="middle" height="330px" />
<figcaption align="middle"></figcaption>
</td>
</tr>
</table>
</div>
<br>
<p>In terms of divergence from established models, using a modified-specular map as a hair distribution heuristic, parametrizing stiffness and sparsity, adjusting brightness of coat as function of hair length and sparsity, and applying wind force all diverged from those that we found online. The detail and realism achieved by this method can be better seen and appreciated in our live demo,
linked below in the <a href="#results"><i>results</i></a> section.</p>
<hr>
<h3 id="results">Results</h3>
<p>
Here are some high-quality renders that we produced using the Mitsuba Renderer and our custom BSDFS. All
renders were done with 4 samples per pixel, and 32 samples per light.
</p>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/kk_diff.png" align="middle" height="400px" />
<figcaption align="middle">Diffuse Only</figcaption>
</td>
<td padding="10px 10px 10px 10px">
<img src="img/kk_spec.png" align="middle" height="400px" />
<figcaption align="middle">Specular Only, Low Exponent (P = 5)</figcaption>
</td>
</tr>
</table>
</div>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/kk_spec2.png" align="middle" height="400px" />
<figcaption align="middle">Specular Only, Regular Exponent (P = 10)</figcaption>
</td>
<td padding="10px 10px 10px 10px">
<img src="img/kk_spec3.png" align="middle" height="400px" />
<figcaption align="middle">Specular Only, Large Exponent (P = 30)</figcaption>
</td>
</tr>
</table>
</div>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/kk_combined.png" align="middle" height="400px" />
<figcaption align="middle">Combined Render: Ks = 0.6, Kd = 0.4, P = 10</figcaption>
</td>
</tr>
</table>
</div>
<br>
<p>
Here are some other scenes that demonstrate the realism of our hair BSDF. They are rendered with
identical parameters (4 samples per pixel, 32 samples per light).
</p>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/kk_fur_diff.png" align="middle" width="100%" />
<figcaption align="middle">Diffuse Component Only</figcaption>
</td>
<td padding="10px 10px 10px 10px">
<img src="img/kk_fur_spec.png" align="middle" width="100%" />
<figcaption align="middle">Specular Component Only</figcaption>
</td>
<td padding="10px 10px 10px 10px">
<img src="img/kk_fur.png" align="middle" width="100%" />
<figcaption align="middle">Combined</figcaption>
</td>
</tr>
</table>
</div>
<div align="middle">
<table style="width=100%">
<tr>
<td padding="10px 10px 10px 10px">
<img src="img/kk_curls_diff.png" align="middle" width="100%" />
<figcaption align="middle">Diffuse Component Only</figcaption>
</td>
<td padding="10px 10px 10px 10px">
<img src="img/kk_curls_spec.png" align="middle" width="100%" />
<figcaption align="middle">Specular Component Only</figcaption>
</td>
<td padding="10px 10px 10px 10px">
<img src="img/kk_curls.png" align="middle" width="100%" />
<figcaption align="middle">Combined</figcaption>
</td>
</tr>
</table>
</div>
<br>
<p>
Lastly, below we provide a link to our dynamic fur shading demo and a video outlining the results of our
final project.
</p>
<b><a href="http://nickshen.me/184proj/web-fur/" target="_blank">Interactive Demo of Dynamic Fur Shading (link)</a></b>
<div align="middle">
<table width="80%">
<tr>
<td padding="10px 10px 10px 10px">
<a href="http://nickshen.me/184proj/web-fur/" target="_blank"><img src="img/bear_closeup.png" align="middle" width="100%" />
<figcaption align="middle">Closeup of Bear (click for demo)</figcaption></a>
</td>
</tr>
</table>
</div>
<b><a href="https://youtu.be/FwE47vOtx3Y" target="_blank">
Final Showcase Video (Youtube Link)
</a></b><br>
<iframe width="900" height="600" src="https://www.youtube.com/embed/FwE47vOtx3Y" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
<hr>
<h3>Resources and References:</h3>
<h5>Computing Platforms:</h5>
<ol>
<li>MacOS High Sierra (v 10,13,3), Shen</li>
<li>Ubuntu 16.04, Briggs + Xia</li>
<li>Windows 10, Briggs (for GTX 1080), Shen (GTX 1060)</li>
</ol>
<h5>Hardware:</h5>
<ol>
<li>NVIDIA GPUs: GTX 1060s + GTX 1080</li>
</ol>
<h5>Software:</h5>
<ol>
<li>Mitsuba Renderer
<ol>
<li>Built using Mitsuba as a basic foundation for ray-tracing and ray-hair intersection:
<a href="http://mitsuba-renderer.org" target="_blank">http://mitsuba-renderer.org</a></li>
<li>Benedikt Bitterli's Tungsten Hair Scenes converted to Mitsuba format:
<a href="https://benedikt-bitterli.me/resources/" target="_blank">https://benedikt-bitterli.me/resources/</a></li>
</ol>
</li>
<li>C++ language and standard libraries</li>
<li>Standard development IDEs</li>
<li>WebGL for dynamic hair/fur rendering</li>
<li id="three">Three.js: <a href="https://threejs.org/" target="_blank">https://threejs.org/</a>, used heavily for interactive demo</li>
</ol>
<h5>References:</h5>
<ol>
<li><b id="kkay">Kajiya-Kay Model, SIGGRAPH, '89: </b>
<a href="https://www.cs.drexel.edu/~david/Classes/CS586/Papers/p271-kajiya.pdf" target="_blank">https://www.cs.drexel.edu/~david/Classes/CS586/Papers/p271-kajiya.pdf</a>
<ol>
<li>Not very photorealistic</li>
<li>Low polygon approach to hair rendering, combines low-poly patches (not cylinders) with diffuse, ambient-occlusion, and specular values to model hair:
<a href="http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketchSlides.pdf" target="_blank">http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2012/10/Scheuermann_HairSketchSlides.pdf</a>
</li>
</ol>
</li>
<li><b id="mitsuba">Mitsuba Renderer</b>, implements ray tracing hair curvature already:
<a href="http://mitsuba-renderer.org" target="_blank">http://mitsuba-renderer.org</a>
</li>
<li><b>WebGL interactive/dynamic fur rendering</b> using three.js and this article:
<a href="http://oos.moxiecode.com/js_webgl/fur" target="_blank">http://oos.moxiecode.com/js_webgl/fur</a>
</li>
<li><b id="#nvidia">NVIDIA shells and fins fur model:</b><a href="http://developer.download.nvidia.com/SDK/10/direct3d/Source/Fur/doc/FurShellsAndFins.pdf" target="_blank">http://developer.download.nvidia.com/SDK/10/direct3d/Source/Fur/doc/FurShellsAndFins.pdf</a></li>
<li><b>Human Hair vs. Animal Fur:</b>
<a href="https://cs184.eecs.berkeley.edu/lecture/advanced-materials/slide_043" target="_blank">https://cs184.eecs.berkeley.edu/lecture/advanced-materials/slide_043</a>
<ol>
<li>Medulla small in humans, larger in animals, exaggerated in softer/higher brightness fur</li>
</ol>
</li>
<li><b>Disney's fur rendering model:</b>
<a href="https://benedikt-bitterli.me/pchfm/pchfm.pdf" target="_blank">https://benedikt-bitterli.me/pchfm/pchfm.pdf</a>
</li>
<li><b id="marsch">"An Energy Conserving Hair Reflectance Model"</b>, (Marschner) <a href="http://www.eugenedeon.com/wp-content/uploads/2014/04/egsrhair.pdf" target="_blank">http://www.eugenedeon.com/wp-content/uploads/2014/04/egsrhair.pdf</a></li>
<li>Zinke-Weber: "Light Scattering From Filaments" (2007)</li>
</ol>
<hr>
<h5>Contributions</h5>
<ul>
<li><b>Jonathan Briggs:</b> Focused mainly on Marschner implementation, but some assistance with
Kajiya-Kay method. Fixed compile/config errors and compatibility issues with Mitsuba Renderer. Wrote HTML
documents for project proposal and final report. Contributed to final presentation slides. Recorded
videos for project milestone and final report.</li>
<li><b>Nick Shen:</b> Focused primarily on WebGL dynamic fur rendering, and interactive demo in three.js setting, but some assistance with Kajiya-Kay method. Contributed heavily to the Javascript/Shader code, HTML document for project milestone. Contributed to final presentation slides. Recorded and edited video for final report. Worked on script.</li>
<li><b>Xiling Xia:</b> Focused mainly on Kajiya-Kay implementation, but some assistance with Marschner
model. Contributed heavily to the K-Kay BSDF and static rendering renders; contributed to final presentation slides. Helped with script for video included in final report.</li>
</ul>
<p>All members each read papers of all three methods, and shared and collaborated in the understanding of each.</p>
</body>
</html>