{"id":14225482,"url":"https://github.com/harry7557558/spirulae","last_synced_at":"2025-08-09T21:32:07.535Z","repository":{"id":112582366,"uuid":"531197795","full_name":"harry7557558/spirulae","owner":"harry7557558","description":"GPU-accelerated math function graphers in web browsers, both 3D and 2D.","archived":false,"fork":false,"pushed_at":"2024-06-22T03:56:52.000Z","size":5581,"stargazers_count":22,"open_issues_count":0,"forks_count":5,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-08-21T01:17:30.350Z","etag":null,"topics":["automatic-differentiation","denoising","domain-coloring","formula-parser","function-graph","graphing-calculator","implicit-surfaces","math-plot","mesh-generation","parametric-surface","ray-tracing","special-functions","streamline-plots","webgl2"],"latest_commit_sha":null,"homepage":"https://spirulae.github.io/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/harry7557558.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-31T17:53:22.000Z","updated_at":"2024-08-16T23:43:54.000Z","dependencies_parsed_at":"2024-01-07T01:54:15.619Z","dependency_job_id":"827e2d22-05a7-4019-ba3e-bec97d70025f","html_url":"https://github.com/harry7557558/spirulae","commit_stats":null,"previous_names":["harry7557558/spirulae"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harry7557558%2Fspirulae","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harry7557558%2Fspirulae/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harry7557558%2Fspirulae/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harry7557558%2Fspirulae/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/harry7557558","download_url":"https://codeload.github.com/harry7557558/spirulae/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":229327604,"owners_count":18055774,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automatic-differentiation","denoising","domain-coloring","formula-parser","function-graph","graphing-calculator","implicit-surfaces","math-plot","mesh-generation","parametric-surface","ray-tracing","special-functions","streamline-plots","webgl2"],"created_at":"2024-08-20T01:01:00.288Z","updated_at":"2024-12-12T03:31:11.270Z","avatar_url":"https://github.com/harry7557558.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# Spirulae: Web-Based Math Visualization\n\n*by Harry Chen - Page updated September 2024*\n\n[![spirulae-2.jpg](assets/spirulae-2.jpg)](https://harry7557558.github.io/spirulae/implicit3/)\n\nGPU-accelerated math function graphers in web browsers, both 3D and 2D.\n\nThis 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](https://www.shadertoy.com/), 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.\n\nIt 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](https://github.com/harry7557558/spirulae/issues).\n\nThe name \"Spirulae\" comes from the name of a [deep-ocean cephalopod mollusk](https://en.wikipedia.org/wiki/Spirula) 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.\n\n----\n\n## Features\n\nThe equation parser implements the following features:\n\n - Function and variable definition\n - Vector and complex number supports\n - Comments (start with `#`, `%`, or `//`)\n - LaTeX preview\n - Special functions\n - Automatic differentiation\n - etc.\n\nThe 3D graphers have the following features implemented:\n\n - Infinite and bounded domain\n - Scalar field visualization\n - Mathematically-defined custom colors\n - Speed vs. quality control\n - Multiple shading and grid modes\n - Dark and light color themes\n - Transparent surfaces\n - Lighting control\n - Red highlight discontinuity\n - etc.\n\nExperimental features (subject to change):\n\n - Animation via `iTime(0)`\n - Export C++ code for 3D implicit grapher, via `exportCurrentFunction('cppd')` in the browser JS console\n - Custom code generation (`/autodiff`)\n - 2D implicit curve grapher (`/implicit2`)\n\n----\n\n## Working in Progress\n\nSpirulae is under active development. Tools and features that are being developed include:\n\n - 3D mesh generation (`/meshgen3`)\n - 2D mesh generation (`/meshgen2`)\n - 2D vector field (`/ode2`)\n\nFeatures that may be implemented in the future (ordered approximately by priority):\n\n - More robust equation parsing\n - More flexible viewport control\n - Variable sliders\n - Graph sharing via URL, `\u003ciframe\u003e` embed for webpages\n - Better expression editor (highlighting, bracket matching, etc.)\n \u003c!-- - More [domain coloring parameters](https://en.wikipedia.org/wiki/Domain_coloring) for complex graphers --\u003e\n\nOngoing and proposed research topics (ordered approximately by progress):\n\n - Denoising path-traced images using deep learning\n - Mesh generation and simplification\n - FEA and general physical simulation\n - Visualization of 3D vector and tensor fields\n - Fitting to NURBS and subdivision surfaces\n\n----\n\n## Limitations\n\nSpirulae has the following web dependencies:\n\n - [WebGL 2](https://webglreport.com/?v=2)\n    - `EXT_color_buffer_float`, required for path tracing and mesh generation\n    - `EXT_disjoint_timer_query_webgl2` (*optional*), an FPS counter will be shown when available\n - WebAssembly, required for mesh generation\n - [MathJax 3](https://www.mathjax.org/), required for equation preview\n\nSpirulae has the following known issues:\n\n - GPU-based graphers use single precision floating point and have incompatibility across devices for overflow and NaN behavior.\n - The parser has ambiguity in resolving conflicting variable names. You can avoid this issue by using unique and descriptive function and variable names.\n - Incomplete documentation for some graphers.\n\nSpirulae is not available for commercial licensing due to C++ dependency [Triangle](https://www.cs.cmu.edu/~quake/triangle.html) 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](https://github.com/harry7557558/spirulae/tree/4843b3e80d92e7633a6525e54c594cd254e5602b).\nNote that shader sources adapted from [Shadertoy](https://www.shadertoy.com/), namely [this](https://www.shadertoy.com/view/flcyWn), [this](https://www.shadertoy.com/view/7ltcW8), and [this](https://www.shadertoy.com/view/wsfGWH), are separately distributed under [CC BY-SA-NC 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/deed.en) according to [Shadertoy terms of service](https://www.shadertoy.com/terms).\n\n----\n\n## Frequently Asked Questions\n\n**Q: How to draw shapes using math equations?**\n\nCreating equations whose graphs represent meaningful shapes is more about intuition than rigorous mathematics. To get started, you can check [Inigo Quilez's YouTube channel](https://www.youtube.com/c/InigoQuilez) and videos like [this one](https://www.youtube.com/watch?v=aNR4n0i2ZlM). I also have a [Google Slide](https://docs.google.com/presentation/d/1CgVLkHcU2wQkaGv-QEvbTdrKlimdrVus-sfaRQyWHm8/edit) intended to introduce Desmos art to high school students that may cover similar principles. I recommend starting simple  \u0026ndash; once you master math art in two dimensions, you can easily apply the same principles in 3D.\n\n\n**Q: What libraries do Spirulae use?**\n\nTo make Spirulae lightweight and compatible, I tried to write it with as few dependencies as possible. With the exception of [MathJax](https://www.mathjax.org/) 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](https://en.wikipedia.org/wiki/WebGL). The C++ part that powers mesh generation is compiled to [WebAssembly](https://en.wikipedia.org/wiki/WebAssembly) with [Emscripten](https://emscripten.org/), which uses the following third-party libraries:\n\n - [Triangle](https://www.cs.cmu.edu/~quake/triangle.html), a fast header-only 2D mesh generation library\n - [GLM](https://github.com/g-truc/glm) and [GLFW](https://www.glfw.org/), popular math and GUI libraries for OpenGL\n\nSpirulae also adapts shader sources from [Shadertoy](https://www.shadertoy.com/):\n\n - [Zeros of Zeta](https://www.shadertoy.com/view/flcyWn) and [Zeta in a box](https://www.shadertoy.com/view/7ltcW8) by [guil](https://www.shadertoy.com/user/guil), for evaluating the [Riemann Zeta function](https://en.wikipedia.org/wiki/Riemann_zeta_function)\n - [Rayleigh/Mie Day and Night Cycle](https://www.shadertoy.com/view/wsfGWH) by [Elyxian](https://www.shadertoy.com/user/Elyxian), for realistic sky rendering in [path tracer](https://spirulae.github.io/implicit3-rt/)\n\n\n**Q: What algorithm does spirulae use to render 3D math equations?**\n\nFor 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](https://en.wikipedia.org/wiki/Newton%27s_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.\n\nThe 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.\n\nThe 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.\n\n\n\u003c!-- **Q: How does Spirulae evaluate functions on the GPU?**\n\nFor 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. --\u003e\n\n----\n\n## Gallery\n\n**Note:** To see more recent visual results, a gallery of unfiltered process screenshots can be found [here](https://spirulae.github.io/gallery/). The page is intended to be a progress overview rather than a showcase gallery.\n\nComplex domain coloring\n\n[![](./assets/gallery-complex-trigs.jpg)](https://harry7557558.github.io/spirulae/complex/)\n\nThe gamma function in 3D\n\n[![](./assets/gallery-complex3-gamma-2.jpg)](https://harry7557558.github.io/spirulae/complex3/)\n\nA realistic rendering of gamma function in 3D\n\n[![](./assets/gallery-implicit3rt-gamma.jpg)](https://harry7557558.github.io/spirulae/implicit3-rt/)\n\nA sextic algebraic surface\n\n[![](./assets/gallery-implicit3-barth6.jpg)](https://harry7557558.github.io/spirulae/implicit3/)\n\nScalar field visualization\n\n[![](./assets/gallery-implicit3-roots-field.jpg)](https://harry7557558.github.io/spirulae/implicit3/)\n\n[![](./assets/gallery-implicit3-bullhead.jpg)](https://harry7557558.github.io/spirulae/implicit3/)\n\nParametric surfaces\n\n[![](./assets/gallery-paramsurf-spherical.jpg)](https://harry7557558.github.io/spirulae/paramsurf/)\n\n[![](./assets/gallery-paramsurf-cups.jpg)](https://harry7557558.github.io/spirulae/paramsurf/)\n\n[![](./assets/gallery-paramsurf-boysurf.jpg)](https://harry7557558.github.io/spirulae/paramsurf/)\n\nA 3D Mandelbrot set\n\n[![](./assets/gallery-complex3-mandelbrot.jpg)](https://harry7557558.github.io/spirulae/complex3/)\n\nA path-traced fractal\n\n[![](./assets/gallery-implicit3rt-mandeltorus.jpg)](https://harry7557558.github.io/spirulae/implicit3-rt)\n\nAnother path-traced fractal\n\n[![](./assets/gallery-implicit3rt-sponge1.jpg)](https://harry7557558.github.io/spirulae/implicit3-rt)\n\n[![](./assets/gallery-implicit3rt-sponge2.jpg)](https://harry7557558.github.io/spirulae/implicit3-rt)\n\nCrystals modeled using math equations\n\n[![](./assets/gallery-implicit3rt-crystal.jpg)](https://harry7557558.github.io/spirulae/implicit3-rt)\n\n3D mesh models generated from math equations\n\n[![](./assets/gallery-meshgen3-bullhead.jpg)](https://harry7557558.github.io/spirulae/meshgen3)\n\n[![](./assets/gallery-meshgen3-julia.jpg)](https://harry7557558.github.io/spirulae/meshgen3)\n\nA 2D vector field streamline plot\n\n[![](./assets/gallery-ode2-cylflow.jpg)](https://harry7557558.github.io/spirulae/ode2)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharry7557558%2Fspirulae","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fharry7557558%2Fspirulae","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharry7557558%2Fspirulae/lists"}