{"id":13425911,"url":"https://github.com/luruke/aladino","last_synced_at":"2025-04-04T09:06:49.519Z","repository":{"id":57175423,"uuid":"348324350","full_name":"luruke/aladino","owner":"luruke","description":"🧞‍♂️  Your magic WebGL carpet","archived":false,"fork":false,"pushed_at":"2021-03-30T21:26:31.000Z","size":8299,"stargazers_count":847,"open_issues_count":3,"forks_count":29,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-28T08:06:25.136Z","etag":null,"topics":["glsl","shader","webgl"],"latest_commit_sha":null,"homepage":"https://luruke.github.io/aladino/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/luruke.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-16T11:38:10.000Z","updated_at":"2025-02-08T14:40:02.000Z","dependencies_parsed_at":"2022-08-29T00:10:56.840Z","dependency_job_id":null,"html_url":"https://github.com/luruke/aladino","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luruke%2Faladino","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luruke%2Faladino/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luruke%2Faladino/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luruke%2Faladino/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luruke","download_url":"https://codeload.github.com/luruke/aladino/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247149500,"owners_count":20891954,"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":["glsl","shader","webgl"],"created_at":"2024-07-31T00:01:21.879Z","updated_at":"2025-04-04T09:06:49.497Z","avatar_url":"https://github.com/luruke.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"⚠️⚠️ BETA! ⚠️⚠️\n(Most likely I won't maintain this...)\n\n# 🧞‍♂️ Aladino – your magic WebGL carpet\n\nAladino is a tiny (around ~5kb gzipped) and dependency-free javascript library that allows to enhance your site using \"shader effects\".  \nThe library is using WebGL1 and has progressive enhancement and accessibility in mind.\n\nBecause examples are worth thousand of words: [https://luruke.github.io/aladino/](https://luruke.github.io/aladino/)\n\nIt was developed during some R\u0026D time at [EPIC Agency](https://epic.net), back in 2019, and it's currently used on:\n\n- [https://days.epic.net](https://days.epic.net)\n- [https://luruke.com](https://luruke.com)\n\n\u003cp float=\"left\"\u003e\n  \u003ca href=\"https://luruke.github.io/aladino/#slider.html\"\u003e\u003cimg src=\"docs/assets/demo/1.gif\" width=\"250\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://luruke.github.io/aladino/#scroll.html\"\u003e\u003cimg src=\"docs/assets/demo/2.gif\" width=\"250\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://luruke.github.io/aladino/#basic.html\"\u003e\u003cimg src=\"docs/assets/demo/3.gif\" width=\"250\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## 🤷‍ Even why?\n\nCSS is cool and powerful, you can build complex responsive layouts and more. Unfortunately the creative interactions you can achieve are very limited (only basic transforms, basic set of CSS filters).\n\nFollowing the footsteps of an old and depracated CSS spec [(Custom filters aka CSS Shaders)](https://developers.google.com/web/updates/2013/03/Introduction-to-Custom-Filters-aka-CSS-Shaders) this library allow to \"augment\" your DOM elements.\n\n## 🔎 How it even works?\n\nAladino operates on a full-screen canvas as `position: fixed`. You'll likely want this canvas to be as background or foreground of your site.\nWhen any `Element` is added to aladino, the original DOM element will be hidden (via `opacity: 0`), and a WebGL plane with the exact same size and position will be created in the canvas.\n\nAt resize and page scroll, aladino will make sure the WebGL plane matches the position and size of your DOM element.\n\nInstead of using an orthographic camera, a perspective one is used, so you can make fancy perspective effects easily.\n\n## 📏 Tailor-made rendering\n\nThe library itself is tiny and doesn't support many of the WebGL capabilities (stencil, cube maps, array uniforms...). The rendering approach is very tailored for this specific use case.\n\nIf you need to render 3D objects and do more complex things, you might want to use libraries like pixi, ogl or three.js and build the dom-\u003egl layer yourself.\n\nSome features:\n\n- Reduce WebGL state change to the strict minimum (try to, without getting too complex, it can be greatly improved).\n- Use VAO (via `OES_vertex_array_object`).\n- Use a single geometry (a plane) for all the draw calls.\n- Automatically cache textures via the URL.\n- Uses [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) where available to track Element size.\n- Postprocessing using a [big-triangle technique](https://michaldrobot.com/2014/04/01/gcn-execution-patterns-in-full-screen-passes/).\n\n## 🌎 Browser support\n\nThe library should work on [every browser supporting WebGL](https://caniuse.com/#feat=webgl), eventually you might want to add a [polyfill for OES_vertex_array_object](https://github.com/greggman/oes-vertex-array-object-polyfill).  \nFor older browsers, you might need to transpile the code in order to support ES features like `class, Map, destructuring`.\n\n## 📝 How to use it\n\nThe library has three main concepts:\n\n- **Aladino**, the main instance, you'll generally have only one in your app.\n- **Carpet**, the representation of your DOM element on the canvas (a plane mesh).\n- **Material**, the WebGL program (vertex + fragment shader) that will be used by your carpets.\n\nA very basic example:\n\n```javascript\nimport Aladino from \"aladino\";\n\nconst aladino = new Aladino();\ndocument.body.appendChild(aladino.canvas);\n\naladino.carpet(document.querySelector(\".element\"), {\n  material: aladino.material({\n    vertex: `\n      attribute vec2 position;\n      attribute vec2 uv;\n\n      uniform mat4 projection;\n      uniform float time;\n\n      void main() {\n        vec4 p = vec4(position, 0.0, 1.0);\n        p.z += sin(uv.x * 3.0 + time * 0.003);\n\n        gl_Position = projection * p;\n      }\n    `,\n    fragment: `\n      precision highp float;\n\n      void main() {\n        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);\n      }\n    `,\n  }),\n});\n```\n\nRunning this piece of code, will create a green animating box, that replace your `.element`.\n\n## 🐝 API\n\nArguments with the default values and methods.\n\n---\n\n### Aladino\n\n```javascript\nconst aladino = new Aladino({\n  // HTMLCanvasElement – The canvas to use\n  canvas: document.createElement(\"canvas\"),\n\n  // Number – Pixel ratio to use (example for retina displays)\n  dpr: Math.min(devicePixelRatio, 2),\n\n  // Number – Define horizontal and vertical mesh density of the plane\n  density: 1,\n\n  // Boolean – Whether need to track the page scroll (`scroll` on `window`)\n  autoScroll: true,\n\n  // WebGLContextAttributes – An object for WebGL context attributes\n  attribs: { antialias: true },\n\n  // Object { fragment: String, uniforms: Object } - Enable postprocessing using a big-triangle\n  post: false,\n});\n\n// WebGLRenderingContext - The WebGL context used by aladino\naladino.gl;\n\n// Number – Read/set the horizontal scrolling in px\naladino.x;\n\n// Number – Read/set the vertical scrolling in px\naladino.y;\n\n// Map - All carpets instances\naladino.carpets;\n\n// Carpet - Get the carpet instance of a specific Element\naladino.carpets.get(document.querySelector(\".element\"));\n\n// Force the resize\naladino.resize();\n\n// Destroy the instance\naladino.destroy();\n```\n\n---\n\n### Material\n\n```javascript\nconst material = aladino.material({\n  // String – Vertex shader\n  vertex: `\n    attribute vec2 position;\n    attribute vec2 uv;\n\n    uniform mat4 projection;\n    uniform vec2 size;\n    uniform float time;\n\n    void main() {\n      vec4 p = vec4(position, 0.0, 1.0);\n      gl_Position = projection * p;\n    }\n  `,\n\n  // String – Fragment shader\n  fragment: `\n    precision highp float;\n\n    void main() {\n      gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n    }\n  `,\n\n  // Object - Uniforms shared across all the carpets using this material\n  uniforms: {},\n  /*\n    {\n      enable: false,         // uniform bool enable;\n      speed: 0.4,            // uniform float speed;\n      scale: [1, 1.2],       // uniform vec2 scale;\n      color: [1, 0, 0],      // uniform vec3 color;\n      color2: [1, 0, 0, 1],  // uniform vec4 color2;\n      tex: aladino.texture() // uniform sampler2D tex;\n    }\n  */\n});\n```\n\nDefault attributes / uniforms:\n\n```glsl\nattribute vec2 position;\nattribute vec2 uv;\n\nuniform mat4 projection;\nuniform vec2 size; // Size in px of your carpet\nuniform vec2 viewport;\nuniform float time; // current time\n\n// When using a `sampler2D` texture, it will automatically send the size in px of the texture\nuniform vec2 size$SAMPLER_UNIFORM_NAME;\n```\n\n---\n\n### Carpet\n\n```javascript\nconst carpet = aladino.carpet(Element, {\n  // Aladino Material – The material to use for this carpet\n  material,\n\n  // Boolean – Use gl.LINES\n  wireframe: false,\n\n  // Array[Number, Number] – Offset in px [x, y]\n  position: [0, 0],\n\n  // Array[Number, Number] – Scale multiplier [width, height]\n  scale: [1, 1],\n\n  // Number - order of depth of the carpet in the scene\n  order: 10,\n\n  // Uniforms – Uniforms specific to this carpet\n  uniforms: {},\n});\n\n// Force the resize of the carpet\n// Note, aladino uses `ResizeObserver` API, so already tracks some element changes\ncarpet.resize();\n\n// Destroy the carpet\ncarpet.destroy();\n\n// Boolean – Indicate if the carpet is active, so if needs to be drawn an updated\ncarpet.active;\n```\n\nAfter creating a carpet, the DOM Element will be set as `opacity: 0` and a CSS class `aladino` will be added.\n\n---\n\n### Texture\n\n```javascript\n// String – URL of the texture\nconst texture = aladino.texture(url, {\n  // Boolean - Apply anisotropy texture filtering via `EXT_texture_filter_anisotropic`\n  anisotropy: false,\n});\n\n// Promise\u003cTexture\u003e\ntexture.loading;\n```\n\nTexture instances can be passed as regular uniforms.\n\n---\n\n## 🏎 Tips 4 Performance\n\nIf you encour in performance issues:\n\n- Try to lower dpr.\n- Try to lower geometry density.\n- Try to disable antialias. (Expecially on retina displays, you might want to look into use `GL_OES_standard_derivatives` instead)\n- Try to share the same Material as much as possible on your carpets.\n- When possible, share uniforms per program then per single carpet.\n- Prefer vertex calculation then per pixel, exploiting the linear interpolation given by varyings variables.\n\nUsually the biggest \"price to pay\" for this technique is the compositing phase between the canvas and the DOM due how browsers works internally.\n\n## 🤔 Things to consider for Dev / Design\n\n- The library automatically tracks your scroll and keep in sync the WebGL, but in case of frame dropping during scroll, you will notice the DOM to be \"smoother\", that's because the browser prioritise it's own rendering instead of Javascript tasks - consider to use a \"virtual scrolling\" if needed.\n\n- If you're using a custom font, makes sure to \"resize\" aladino after the font is loaded (as it might cause a layout shifting).\n\n- The library tracks the position of your DOM elements at page load and resize and with `ResizeObserver` API if available. If you change the position of your item, you'll have to remember to use `.resize()` method.\n\n## 🔨 TODO\n\n- Support video texture?\n- Add a method to verify WebGL support?\n- Test canvas position fixed vs `transform: translate()`?\n- Culling?\n- Blending modes?\n- Support text?\n- Create components for react / vue.js?\n- See if magicshader can be implemented easily?\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluruke%2Faladino","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluruke%2Faladino","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluruke%2Faladino/lists"}