-
Notifications
You must be signed in to change notification settings - Fork 6
/
index.html
222 lines (207 loc) · 15.3 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
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Spirulae | Web-Based Math Visualization</title>
<meta name="description" content="GPU-accelerated math function graphers in web browsers, both 3D and 2D." />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="canonical" href="https://harry7557558.github.io/spirulae/" />
<link rel="stylesheet" href="./assets/style.css" />
</head>
<body>
<div id="s" style="position:absolute;top:0;height:0px;"></div>
<div id="container">
<h1 style="text-align:center;margin-bottom:0;font-family:Arial,Helvetica;">Spirulae:
Web-Based Math Visualization</h1>
<p style="text-align:center;">
<em style="color:#555">by Harry Chen - Page updated September 2024</em>
</p>
<p style="text-align:center;margin-top:-0.5em;">
<a href="https://github.com/harry7557558/spirulae/" target="_blank">GitHub</a> ⋅
<a href="https://spirulae.github.io/gallery/">Gallery</a>
</p>
<div class="tool-gallery">
<a href="https://harry7557558.github.io/spirulae/implicit3/" class="a">
<img src="assets/img-implicit3.jpg" style="width:100%" />
<br/>
3D Implicit Surface Grapher
</a>
<a href="https://harry7557558.github.io/spirulae/paramsurf/" class="a">
<img src="assets/img-paramsurf.jpg" style="width:100%" />
<br/>
3D Parametric Surface Grapher
</a>
<a href="https://harry7557558.github.io/spirulae/complex/" class="a">
<img src="assets/img-complex.jpg" style="width:100%" />
<br/>
Complex Domain Coloring Grapher
</a>
<a href="https://harry7557558.github.io/spirulae/complex3/" class="a">
<img src="assets/img-complex3.jpg" style="width:100%" />
<br/>
3D Complex Function Grapher
</a>
<a href="https://harry7557558.github.io/spirulae/implicit3-rt/" class="a">
<img src="assets/img-implicit3rt.jpg" style="width:100%" />
<br/>
Implicit Surface Path Tracer<br />(powerful GPU required)
</a>
<a href="https://harry7557558.github.io/spirulae/meshgen3/" class="a">
<img src="assets/img-meshgen3.jpg" style="width:100%" />
<br/>
3D Implicit Mesh Generator (dev)<br />
</a>
<a href="https://harry7557558.github.io/spirulae/ode2/" class="a">
<img src="assets/img-ode2.jpg" style="width:100%" />
<br/>
2D Vector Field Grapher (dev)
</a>
<a href="https://harry7557558.github.io/spirulae/meshgen2/" class="a">
<img src="assets/img-meshgen2.jpg" style="width:100%" />
<br/>
2D to 3D Mesh Generator (dev)
</a>
</div>
<div class="home-md-content">
<p>GPU-accelerated math function graphers in web browsers, both 3D and 2D.</p>
<p>This is a personal passion project. Back in 2022 I couldn't find a 3D graphing calculator with satisfying 3D implicit surface rendering, so I made one, and the development continued. I was initially inspired by raymarching demos on <a href="https://www.shadertoy.com/">Shadertoy</a>, but as I extended the equation parser and renderer to other types of math functions, currently implemented function graphers are not limited to implicit ones.</p>
<p>It is important to note that these function graphers are developed completely by my effort, and many features I implemented are biased toward personal use. I'm not a "real" mathematician, and many features and examples I added are for visual impression rather than mathenatical accuracy and practicability. If you have any suggestions or believe you are experiencing a bug, feel free to <a href="https://github.com/harry7557558/spirulae/issues">open an issue on GitHub</a>.</p>
<p>The name "Spirulae" comes from the name of a <a href="https://en.wikipedia.org/wiki/Spirula">deep-ocean cephalopod mollusk</a> that has distinctive spiral shells. I consider myself a fan of spirals, so it shouldn't be surprising that you see a lot of spirals in examples.</p>
<hr />
<h2>Features</h2>
<p>The equation parser implements the following features:</p>
<ul>
<li>Function and variable definition</li>
<li>Vector and complex number supports</li>
<li>Comments (start with <code>#</code>, <code>%</code>, or <code>//</code>)</li>
<li>LaTeX preview</li>
<li>Special functions</li>
<li>Automatic differentiation</li>
<li>etc.</li>
</ul>
<p>The 3D graphers have the following features implemented:</p>
<ul>
<li>Infinite and bounded domain</li>
<li>Scalar field visualization</li>
<li>Mathematically-defined custom colors</li>
<li>Speed vs. quality control</li>
<li>Multiple shading and grid modes</li>
<li>Dark and light color themes</li>
<li>Transparent surfaces</li>
<li>Lighting control</li>
<li>Red highlight discontinuity</li>
<li>etc.</li>
</ul>
<p>Experimental features (subject to change):</p>
<ul>
<li>Animation via <code>iTime(0)</code></li>
<li>Export C++ code for 3D implicit grapher, via <code>exportCurrentFunction('cppd')</code> in the browser JS console</li>
<li>Custom code generation (<code>/autodiff</code>)</li>
<li>2D implicit curve grapher (<code>/implicit2</code>)</li>
</ul>
<hr />
<h2>Working in Progress</h2>
<p>Spirulae is under active development. Tools and features that are being developed include:</p>
<ul>
<li>3D mesh generation (<code>/meshgen3</code>)</li>
<li>2D mesh generation (<code>/meshgen2</code>)</li>
<li>2D vector field (<code>/ode2</code>)</li>
</ul>
<p>Features that may be implemented in the future (ordered approximately by priority):</p>
<ul>
<li>More robust equation parsing</li>
<li>More flexible viewport control</li>
<li>Variable sliders</li>
<li>Graph sharing via URL, <code><iframe></code> embed for webpages</li>
<li>Better expression editor (highlighting, bracket matching, etc.)
<!-- - More [domain coloring parameters](https://en.wikipedia.org/wiki/Domain_coloring) for complex graphers -->
</li>
</ul>
<p>Ongoing and proposed research topics (ordered approximately by progress):</p>
<ul>
<li>Denoising path-traced images using deep learning</li>
<li>Mesh generation and simplification</li>
<li>FEA and general physical simulation</li>
<li>Visualization of 3D vector and tensor fields</li>
<li>Fitting to NURBS and subdivision surfaces</li>
</ul>
<hr />
<h2>Limitations</h2>
<p>Spirulae has the following web dependencies:</p>
<ul>
<li><a href="https://webglreport.com/?v=2">WebGL 2</a><ul>
<li><code>EXT_color_buffer_float</code>, required for path tracing and mesh generation</li>
<li><code>EXT_disjoint_timer_query_webgl2</code> (<em>optional</em>), an FPS counter will be shown when available</li>
</ul>
</li>
<li>WebAssembly, required for mesh generation</li>
<li><a href="https://www.mathjax.org/">MathJax 3</a>, required for equation preview</li>
</ul>
<p>Spirulae has the following known issues:</p>
<ul>
<li>GPU-based graphers use single precision floating point and have incompatibility across devices for overflow and NaN behavior.</li>
<li>The parser has ambiguity in resolving conflicting variable names. You can avoid this issue by using unique and descriptive function and variable names.</li>
<li>Incomplete documentation for some graphers.</li>
</ul>
<p>Spirulae is not available for commercial licensing due to C++ dependency <a href="https://www.cs.cmu.edu/~quake/triangle.html">Triangle</a> and is currently distributed under GPLv3. Spirulae was previously distributed under the MIT license, an old version that allows commercial use can be found <a href="https://github.com/harry7557558/spirulae/tree/4843b3e80d92e7633a6525e54c594cd254e5602b">here</a>.
Note that shader sources adapted from <a href="https://www.shadertoy.com/">Shadertoy</a>, namely <a href="https://www.shadertoy.com/view/flcyWn">this</a>, <a href="https://www.shadertoy.com/view/7ltcW8">this</a>, and <a href="https://www.shadertoy.com/view/wsfGWH">this</a>, are separately distributed under <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/deed.en">CC BY-SA-NC 3.0</a> according to <a href="https://www.shadertoy.com/terms">Shadertoy terms of service</a>.</p>
<hr />
<h2>Frequently Asked Questions</h2>
<p><strong>Q: How to draw shapes using math equations?</strong></p>
<p>Creating equations whose graphs represent meaningful shapes is more about intuition than rigorous mathematics. To get started, you can check <a href="https://www.youtube.com/c/InigoQuilez">Inigo Quilez's YouTube channel</a> and videos like <a href="https://www.youtube.com/watch?v=aNR4n0i2ZlM">this one</a>. I also have a <a href="https://docs.google.com/presentation/d/1CgVLkHcU2wQkaGv-QEvbTdrKlimdrVus-sfaRQyWHm8/edit">Google Slide</a> intended to introduce Desmos art to high school students that may cover similar principles. I recommend starting simple – once you master math art in two dimensions, you can easily apply the same principles in 3D.</p>
<p><strong>Q: What libraries do Spirulae use?</strong></p>
<p>To make Spirulae lightweight and compatible, I tried to write it with as few dependencies as possible. With the exception of <a href="https://www.mathjax.org/">MathJax</a> for rendering LaTeX equations, the JavaScript equation parser and renderers are written from scratch without use of external libraries and frameworks, other than native browser APIs like <a href="https://en.wikipedia.org/wiki/WebGL">WebGL</a>. The C++ part that powers mesh generation is compiled to <a href="https://en.wikipedia.org/wiki/WebAssembly">WebAssembly</a> with <a href="https://emscripten.org/">Emscripten</a>, which uses the following third-party libraries:</p>
<ul>
<li><a href="https://www.cs.cmu.edu/~quake/triangle.html">Triangle</a>, a fast header-only 2D mesh generation library</li>
<li><a href="https://github.com/g-truc/glm">GLM</a> and <a href="https://www.glfw.org/">GLFW</a>, popular math and GUI libraries for OpenGL</li>
</ul>
<p>Spirulae also adapts shader sources from <a href="https://www.shadertoy.com/">Shadertoy</a>:</p>
<ul>
<li><a href="https://www.shadertoy.com/view/flcyWn">Zeros of Zeta</a> and <a href="https://www.shadertoy.com/view/7ltcW8">Zeta in a box</a> by <a href="https://www.shadertoy.com/user/guil">guil</a>, for evaluating the <a href="https://en.wikipedia.org/wiki/Riemann_zeta_function">Riemann Zeta function</a></li>
<li><a href="https://www.shadertoy.com/view/wsfGWH">Rayleigh/Mie Day and Night Cycle</a> by <a href="https://www.shadertoy.com/user/Elyxian">Elyxian</a>, for realistic sky rendering in <a href="https://spirulae.github.io/implicit3-rt/">path tracer</a></li>
</ul>
<p><strong>Q: What algorithm does spirulae use to render 3D math equations?</strong></p>
<p>For 3D implicit surface grapher and 3D complex function grapher, for each pixel, Spirulae approximates the nearest intersection between camera ray and the equation's isosurface. The intersection is approximated with <a href="https://en.wikipedia.org/wiki/Newton%27s_method">Newton's method</a> in screen space, with line derivative estimated from previous function evaluations. The method is designed to be robust to highly nonlinear and unbounded functions. A two-pass hierarchical ray-surface intersection is used to speed up rendering.</p>
<p>The implicit surface path tracer uses a similar method as implicit graphers, except it estimates intersection in clipped object space and does not utilize a hierarchical ray-surface intersection. This allows robust tracing of indirect rays.</p>
<p>The 3D parametric grapher uses a rasterization pipeline. The fragment shader directly evaluates the function per-pixel to calculate albedo and normal, allowing resembling fine surface details even with a relatively coarse geometry. Mesh generators use a conventional OpenGL rasterization pipeline for rendering, with per-vertex albedo and normal from generated mesh.</p>
<!-- **Q: How does Spirulae evaluate functions on the GPU?**
For readers with technical background, Spirulae recompiles shader every time the equation input or a graphing parameter is updated. Spirulae parses equations into [postfix notation](https://en.wikipedia.org/wiki/Reverse_Polish_notation#Explanation) and generates code of a GLSL function that can be compiled. Automatic differentiation can be done in this step. Generated shader code can be found in the browser's F12 developer console. -->
<hr />
<h2>Gallery</h2>
<p><strong>Note:</strong> To see more recent visual results, a gallery of unfiltered process screenshots can be found <a href="https://spirulae.github.io/gallery/">here</a>. The page is intended to be a progress overview rather than a showcase gallery.</p>
<p>Complex domain coloring</p>
<p><a href="https://harry7557558.github.io/spirulae/complex/"><img alt="" src="./assets/gallery-complex-trigs.jpg" /></a></p>
<p>The gamma function in 3D</p>
<p><a href="https://harry7557558.github.io/spirulae/complex3/"><img alt="" src="./assets/gallery-complex3-gamma-2.jpg" /></a></p>
<p>A realistic rendering of gamma function in 3D</p>
<p><a href="https://harry7557558.github.io/spirulae/implicit3-rt/"><img alt="" src="./assets/gallery-implicit3rt-gamma.jpg" /></a></p>
<p>A sextic algebraic surface</p>
<p><a href="https://harry7557558.github.io/spirulae/implicit3/"><img alt="" src="./assets/gallery-implicit3-barth6.jpg" /></a></p>
<p>Scalar field visualization</p>
<p><a href="https://harry7557558.github.io/spirulae/implicit3/"><img alt="" src="./assets/gallery-implicit3-roots-field.jpg" /></a></p>
<p><a href="https://harry7557558.github.io/spirulae/implicit3/"><img alt="" src="./assets/gallery-implicit3-bullhead.jpg" /></a></p>
<p>Parametric surfaces</p>
<p><a href="https://harry7557558.github.io/spirulae/paramsurf/"><img alt="" src="./assets/gallery-paramsurf-spherical.jpg" /></a></p>
<p><a href="https://harry7557558.github.io/spirulae/paramsurf/"><img alt="" src="./assets/gallery-paramsurf-cups.jpg" /></a></p>
<p><a href="https://harry7557558.github.io/spirulae/paramsurf/"><img alt="" src="./assets/gallery-paramsurf-boysurf.jpg" /></a></p>
<p>A 3D Mandelbrot set</p>
<p><a href="https://harry7557558.github.io/spirulae/complex3/"><img alt="" src="./assets/gallery-complex3-mandelbrot.jpg" /></a></p>
<p>A path-traced fractal</p>
<p><a href="https://harry7557558.github.io/spirulae/implicit3-rt"><img alt="" src="./assets/gallery-implicit3rt-mandeltorus.jpg" /></a></p>
<p>Another path-traced fractal</p>
<p><a href="https://harry7557558.github.io/spirulae/implicit3-rt"><img alt="" src="./assets/gallery-implicit3rt-sponge1.jpg" /></a></p>
<p><a href="https://harry7557558.github.io/spirulae/implicit3-rt"><img alt="" src="./assets/gallery-implicit3rt-sponge2.jpg" /></a></p>
<p>Crystals modeled using math equations</p>
<p><a href="https://harry7557558.github.io/spirulae/implicit3-rt"><img alt="" src="./assets/gallery-implicit3rt-crystal.jpg" /></a></p>
<p>3D mesh models generated from math equations</p>
<p><a href="https://harry7557558.github.io/spirulae/meshgen3"><img alt="" src="./assets/gallery-meshgen3-bullhead.jpg" /></a></p>
<p><a href="https://harry7557558.github.io/spirulae/meshgen3"><img alt="" src="./assets/gallery-meshgen3-julia.jpg" /></a></p>
<p>A 2D vector field streamline plot</p>
<p><a href="https://harry7557558.github.io/spirulae/ode2"><img alt="" src="./assets/gallery-ode2-cylflow.jpg" /></a></p>
</div>
<p style="text-align: center;">
<a href="#s">Back to top</a>
</p>
</div>
</body>
</html>