by Harry Chen - Page updated September 2024
GPU-accelerated math function graphers in web browsers, both 3D and 2D.
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 Shadertoy, 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.
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 open an issue on GitHub.
The name "Spirulae" comes from the name of a deep-ocean cephalopod mollusk 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.
The equation parser implements the following features:
#
, %
, or //
)The 3D graphers have the following features implemented:
Experimental features (subject to change):
iTime(0)
exportCurrentFunction('cppd')
in the browser JS console/autodiff
)/implicit2
)Spirulae is under active development. Tools and features that are being developed include:
/meshgen3
)/meshgen2
)/ode2
)Features that may be implemented in the future (ordered approximately by priority):
<iframe>
embed for webpagesOngoing and proposed research topics (ordered approximately by progress):
Spirulae has the following web dependencies:
EXT_color_buffer_float
, required for path tracing and mesh generationEXT_disjoint_timer_query_webgl2
(optional), an FPS counter will be shown when availableSpirulae has the following known issues:
Spirulae is not available for commercial licensing due to C++ dependency Triangle and is currently distributed under GPLv3. Spirulae was previously distributed under the MIT license, an old version that allows commercial use can be found here. Note that shader sources adapted from Shadertoy, namely this, this, and this, are separately distributed under CC BY-SA-NC 3.0 according to Shadertoy terms of service.
Q: How to draw shapes using math equations?
Creating equations whose graphs represent meaningful shapes is more about intuition than rigorous mathematics. To get started, you can check Inigo Quilez's YouTube channel and videos like this one. I also have a Google Slide 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.
Q: What libraries do Spirulae use?
To make Spirulae lightweight and compatible, I tried to write it with as few dependencies as possible. With the exception of MathJax 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 WebGL. The C++ part that powers mesh generation is compiled to WebAssembly with Emscripten, which uses the following third-party libraries:
Spirulae also adapts shader sources from Shadertoy:
Q: What algorithm does spirulae use to render 3D math equations?
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 Newton's method 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.
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.
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.
Note: To see more recent visual results, a gallery of unfiltered process screenshots can be found here. The page is intended to be a progress overview rather than a showcase gallery.
Complex domain coloring
The gamma function in 3D
A realistic rendering of gamma function in 3D
A sextic algebraic surface
Scalar field visualization
Parametric surfaces
A 3D Mandelbrot set
A path-traced fractal
Another path-traced fractal
Crystals modeled using math equations
3D mesh models generated from math equations
A 2D vector field streamline plot