{"id":38464853,"url":"https://github.com/leandrosq/js-mandelbrot","last_synced_at":"2026-01-17T05:01:19.673Z","repository":{"id":214599461,"uuid":"736910865","full_name":"LeandroSQ/js-mandelbrot","owner":"LeandroSQ","description":"WebGPU, WebGL, WASM, and JS comparison of Fractal rendering","archived":false,"fork":false,"pushed_at":"2023-12-30T02:12:35.000Z","size":1033,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2023-12-30T09:36:40.987Z","etag":null,"topics":["assemblyscript","fractal","glsl","mandelbrot","shaders","wasm","web","webgl","webgl2","webgpu","wgsl"],"latest_commit_sha":null,"homepage":"https://leandrosq.github.io/js-mandelbrot/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LeandroSQ.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}},"created_at":"2023-12-29T08:26:46.000Z","updated_at":"2023-12-29T08:53:45.000Z","dependencies_parsed_at":"2023-12-29T09:48:55.340Z","dependency_job_id":null,"html_url":"https://github.com/LeandroSQ/js-mandelbrot","commit_stats":null,"previous_names":["leandrosq/js-mandelbrot"],"tags_count":0,"template":null,"template_full_name":null,"purl":"pkg:github/LeandroSQ/js-mandelbrot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeandroSQ%2Fjs-mandelbrot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeandroSQ%2Fjs-mandelbrot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeandroSQ%2Fjs-mandelbrot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeandroSQ%2Fjs-mandelbrot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LeandroSQ","download_url":"https://codeload.github.com/LeandroSQ/js-mandelbrot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LeandroSQ%2Fjs-mandelbrot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28497956,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T04:31:57.058Z","status":"ssl_error","status_checked_at":"2026-01-17T04:31:45.816Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["assemblyscript","fractal","glsl","mandelbrot","shaders","wasm","web","webgl","webgl2","webgpu","wgsl"],"created_at":"2026-01-17T05:00:44.986Z","updated_at":"2026-01-17T05:01:19.601Z","avatar_url":"https://github.com/LeandroSQ.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mandelbrot Web\n\nA mandelbrot set renderer in the browser, comparing the performance of: `WebGPU`, `WebGL`, `HTML Canvas`, `WASM` and `HTML Canvas + MathJS`.\n\n\u003ccenter\u003e\n    \u003cp float=\"left\" align=\"center\"\u003e\n        \u003cimg src=\".github/screenshots/screenshot01.png\" style=\"width: 48%\"/\u003e\n    \u003c/p\u003e\n\u003c/center\u003e\n\n\u003cp align=\"center\"\u003e\n\t\u003ca href=\"https://leandrosq.github.io/js-mandelbrot/\"\u003eLive demo here\u003c/a\u003e\n\u003c/p\u003e\n\n## About\n\nThis is but an experiment to compare the performance of different technologies in the browser, the goal is to render the mandelbrot set in real time, and to be able to zoom and pan around with minimal latency.\n\nThe following technologies are used to render:\n- [WebGPU](https://gpuweb.github.io/gpuweb/)\n- [WebGL](https://www.khronos.org/webgl/)\n- [Canvas with raw ImageData manipulation](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API)\n- [WASM](https://webassembly.org/)\n- [Canvas with raw ImageData manipulation + MathJS](https://mathjs.org/)\n\nThe only target not widely supported is WebGPU, you can check the support [here](https://caniuse.com/webgpu).\n\n\u003e **Note 1:** I initially also made a renderer using plain Canvas API's, but since `fillRect` for each pixel is too slow, I decided to remove it from the comparison.\n\n\u003e **Note 2:** For the WASM renderer, I used [AssemblyScript](https://www.assemblyscript.org/) to compile the code to WASM, and [esbuild](https://esbuild.github.io/) to bundle it. For some reason it is slower than the pure JS version, I'm not sure why, but I suspect it has something to do with the way I'm passing the data to the WASM module.\n\n\u003e **Note 3:** For the Canvas + MathJS renderer, I used [MathJS](https://mathjs.org/) to do the calculations, and then I used the Canvas API to render the pixels. It is the slowest of all, but it is also the most accurate, since it uses arbitrary precision numbers.\n\n\u003e **Note 4:** For WebGL, WebGPU and WASM I used 32 float numbers, which are easily changed to 64 float numbers, except on WebGPU where there is no support. This yields a accurate enough result, but does not allow for deep zooms.\n\n## Controls\n\n### Desktop:\n\n\u003e \u003cimg src=\".github/images/Ctrl_Key_Light.png\" align=\"center\" height=\"32\"\u003e + \u003cimg src=\".github/images/Mouse_Scroll_Light.png\" align=\"center\" height=\"32\"\u003e to zoom in/out\n\n\u003e \u003cimg src=\".github/images/Mouse_Scroll_Light.png\" align=\"center\" height=\"32\"\u003e to vertical pan\n\n\u003e \u003cimg src=\".github/images/Shift_Key_Light.png\" align=\"center\" height=\"32\"\u003e + \u003cimg src=\".github/images/Mouse_Scroll_Light.png\" align=\"center\" height=\"32\"\u003e to horizontal pan\n\n\u003e Mouse secondary wheel to horizontal pan (Like the one in Logitech MxMaster3)\n\n\u003e \u003cimg src=\".github/images/Mouse_Left_Key_Light.png\" align=\"center\" height=\"32\"\u003e/\u003cimg src=\".github/images/Mouse_Middle_Key_Light.png\" align=\"center\" height=\"32\"\u003e to drag to pan\n\n\u003e \u003cimg src=\".github/images/F11_Key_Light.png\" align=\"center\" height=\"32\"\u003e to toggle fullscreen\n### Laptop:\n\n\u003e \u003cimg src=\".github/images/Gesture_Zoom_Out.png\" align=\"center\" width=\"32\"\u003e Trackpad Pinch zoom in/out\n\n\u003e \u003cimg src=\".github/images/Gesture_Scroll_Up.png\" align=\"center\" height=\"32\"\u003e/\u003cimg src=\".github/images/Gesture_Scroll_Down.png\" align=\"center\" height=\"32\"\u003e Trackpad vertical pan\n\n\u003e \u003cimg src=\".github/images/Gesture_Scroll_Left.png\" align=\"center\" width=\"32\"\u003e/\u003cimg src=\".github/images/Gesture_Scroll_Right.png\" align=\"center\" width=\"30\"\u003e Trackpad horizontal pan\n\n\u003e \u003cimg src=\".github/images/Gesture_Double_Tap.png\" align=\"center\" width=\"32\"\u003e Trackpad double tap to toggle fullscreen\n### Touch/Mobile:\n\n\u003e \u003cimg src=\".github/images/Gesture_Zoom_Out.png\" align=\"center\" width=\"32\"\u003e Pinch zoom in/out\n\n\u003e \u003cimg src=\".github/images/Gesture_Swipe_Up.png\" align=\"center\" width=\"32\"\u003e/\u003cimg src=\".github/images/Gesture_Swipe_Left.png\" align=\"center\" width=\"32\"\u003e/\u003cimg src=\".github/images/Gesture_Swipe_Right.png\" align=\"center\" width=\"32\"\u003e/\u003cimg src=\".github/images/Gesture_Swipe_Down.png\" align=\"center\" width=\"32\"\u003e Drag to pan\n\n\u003e \u003cimg src=\".github/images/Gesture_Double_Tap.png\" align=\"center\" width=\"32\"\u003e Double tap to toggle fullscreen\n\n## Project\n\n### Resources\n\n| Name | Description |\n| -- | -- |\n| Eslint | For linting and semantic analysis |\n| Prettier | For code formatting |\n| Typescript | For static typing |\n| AssemblyScript | For WASM |\n| esbuild | For bundling |\n| gulp | For task automation |\n| SASS | For CSS preprocessing |\n| EJS | For HTML templating |\n| [ThoseAwesomeGuys Prompts](https://thoseawesomeguys.com/prompts) | For the Keyboard and gesture icons |\n| Browser sync | For live reloading |\n| Github actions | For CI, building and deploying to github pages |\n| [Google fonts](https://fonts.google.com/) | For the [Rubik](https://fonts.google.com/specimen/Rubik) font |\n| FontAwesome | For the [favicon](https://fontawesome.com/icons/robot?s=solid\u0026f=classic) |\n| View Transition API | For the page transitions |\n| Vibrate API | For the haptic feedback |\n\n### Devices used for testing\n\n- iPhone 13 Pro\n- ROG Ally\n- Macbook M1 Pro 14\" 2021\n- Mi Pad 5 Pro\n- Windows Desktop\n\n### Browsers tested\n\n- Safari - iOS\n- Safari - MacOS\n- Chrome - iOS\n- Chrome - MacOS\n- Chrome - Android\n- Edge - MacOS\n- Edge - Windows","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleandrosq%2Fjs-mandelbrot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleandrosq%2Fjs-mandelbrot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleandrosq%2Fjs-mandelbrot/lists"}