๐Ÿงžโ€โ™‚๏ธ Aladino โ€“ your magic WebGL carpet

Last update: Jun 18, 2022

โš ๏ธ โš ๏ธ BETA! โš ๏ธ โš ๏ธ (Most likely I won't maintain this...)

๐Ÿงžโ€โ™‚๏ธ Aladino โ€“ your magic WebGL carpet

Aladino is a tiny (around ~5kb gzipped) and dependency-free javascript library that allows to enhance your site using "shader effects".
The library is using WebGL1 and has progressive enhancement and accessibility in mind.

Because examples are worth thousand of words: https://luruke.github.io/aladino/

It was developed during some R&D time at EPIC Agency, back in 2019, and it's currently used on:

๐Ÿคทโ€ Even why?

CSS 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).

Following the footsteps of an old and depracated CSS spec (Custom filters aka CSS Shaders) this library allow to "augment" your DOM elements.

๐Ÿ”Ž How it even works?

Aladino operates on a full-screen canvas as position: fixed. You'll likely want this canvas to be as background or foreground of your site. When 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.

At resize and page scroll, aladino will make sure the WebGL plane matches the position and size of your DOM element.

Instead of using an orthographic camera, a perspective one is used, so you can make fancy perspective effects easily.

๐Ÿ“ Tailor-made rendering

The 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.

If 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->gl layer yourself.

Some features:

  • Reduce WebGL state change to the strict minimum (try to, without getting too complex, it can be greatly improved).
  • Use VAO (via OES_vertex_array_object).
  • Use a single geometry (a plane) for all the draw calls.
  • Automatically cache textures via the URL.
  • Uses ResizeObserver where available to track Element size.
  • Postprocessing using a big-triangle technique.

๐ŸŒŽ Browser support

The library should work on every browser supporting WebGL, eventually you might want to add a polyfill for OES_vertex_array_object.
For older browsers, you might need to transpile the code in order to support ES features like class, Map, destructuring.

๐Ÿ“ How to use it

The library has three main concepts:

  • Aladino, the main instance, you'll generally have only one in your app.
  • Carpet, the representation of your DOM element on the canvas (a plane mesh).
  • Material, the WebGL program (vertex + fragment shader) that will be used by your carpets.

A very basic example:

import Aladino from "aladino";

const aladino = new Aladino();
document.body.appendChild(aladino.canvas);

aladino.carpet(document.querySelector(".element"), {
  material: aladino.material({
    vertex: `
      attribute vec2 position;
      attribute vec2 uv;

      uniform mat4 projection;
      uniform float time;

      void main() {
        vec4 p = vec4(position, 0.0, 1.0);
        p.z += sin(uv.x * 3.0 + time * 0.003);

        gl_Position = projection * p;
      }
    `,
    fragment: `
      precision highp float;

      void main() {
        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
      }
    `,
  }),
});

Running this piece of code, will create a green animating box, that replace your .element.

๐Ÿ API

Arguments with the default values and methods.


Aladino

const aladino = new Aladino({
  // HTMLCanvasElement โ€“ The canvas to use
  canvas: document.createElement("canvas"),

  // Number โ€“ Pixel ratio to use (example for retina displays)
  dpr: Math.min(devicePixelRatio, 2),

  // Number โ€“ Define horizontal and vertical mesh density of the plane
  density: 1,

  // Boolean โ€“ Whether need to track the page scroll (`scroll` on `window`)
  autoScroll: true,

  // WebGLContextAttributes โ€“ An object for WebGL context attributes
  attribs: { antialias: true },

  // Object { fragment: String, uniforms: Object } - Enable postprocessing using a big-triangle
  post: false,
});

// WebGLRenderingContext - The WebGL context used by aladino
aladino.gl;

// Number โ€“ Read/set the horizontal scrolling in px
aladino.x;

// Number โ€“ Read/set the vertical scrolling in px
aladino.y;

// Map - All carpets instances
aladino.carpets;

// Carpet - Get the carpet instance of a specific Element
aladino.carpets.get(document.querySelector(".element"));

// Force the resize
aladino.resize();

// Destroy the instance
aladino.destroy();

Material

const material = aladino.material({
  // String โ€“ Vertex shader
  vertex: `
    attribute vec2 position;
    attribute vec2 uv;

    uniform mat4 projection;
    uniform vec2 size;
    uniform float time;

    void main() {
      vec4 p = vec4(position, 0.0, 1.0);
      gl_Position = projection * p;
    }
  `,

  // String โ€“ Fragment shader
  fragment: `
    precision highp float;

    void main() {
      gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
  `,

  // Object - Uniforms shared across all the carpets using this material
  uniforms: {},
  /*
    {
      enable: false,         // uniform bool enable;
      speed: 0.4,            // uniform float speed;
      scale: [1, 1.2],       // uniform vec2 scale;
      color: [1, 0, 0],      // uniform vec3 color;
      color2: [1, 0, 0, 1],  // uniform vec4 color2;
      tex: aladino.texture() // uniform sampler2D tex;
    }
  */
});

Default attributes / uniforms:

attribute vec2 position;
attribute vec2 uv;

uniform mat4 projection;
uniform vec2 size; // Size in px of your carpet
uniform vec2 viewport;
uniform float time; // current time

// When using a `sampler2D` texture, it will automatically send the size in px of the texture
uniform vec2 size$SAMPLER_UNIFORM_NAME;

Carpet

const carpet = aladino.carpet(Element, {
  // Aladino Material โ€“ The material to use for this carpet
  material,

  // Boolean โ€“ Use gl.LINES
  wireframe: false,

  // Array[Number, Number] โ€“ Offset in px [x, y]
  position: [0, 0],

  // Array[Number, Number] โ€“ Scale multiplier [width, height]
  scale: [1, 1],

  // Number - order of depth of the carpet in the scene
  order: 10,

  // Uniforms โ€“ Uniforms specific to this carpet
  uniforms: {},
});

// Force the resize of the carpet
// Note, aladino uses `ResizeObserver` API, so already tracks some element changes
carpet.resize();

// Destroy the carpet
carpet.destroy();

// Boolean โ€“ Indicate if the carpet is active, so if needs to be drawn an updated
carpet.active;

After creating a carpet, the DOM Element will be set as opacity: 0 and a CSS class aladino will be added.


Texture

// String โ€“ URL of the texture
const texture = aladino.texture(url, {
  // Boolean - Apply anisotropy texture filtering via `EXT_texture_filter_anisotropic`
  anisotropy: false,
});

// Promise
   
texture.loading;

Texture instances can be passed as regular uniforms.


๐ŸŽ Tips 4 Performance

If you encour in performance issues:

  • Try to lower dpr.
  • Try to lower geometry density.
  • Try to disable antialias. (Expecially on retina displays, you might want to look into use GL_OES_standard_derivatives instead)
  • Try to share the same Material as much as possible on your carpets.
  • When possible, share uniforms per program then per single carpet.
  • Prefer vertex calculation then per pixel, exploiting the linear interpolation given by varyings variables.

Usually the biggest "price to pay" for this technique is the compositing phase between the canvas and the DOM due how browsers works internally.

๐Ÿค” Things to consider for Dev / Design

  • 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.

  • If you're using a custom font, makes sure to "resize" aladino after the font is loaded (as it might cause a layout shifting).

  • 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.

๐Ÿ”จ TODO

  • Support video texture?
  • Add a method to verify WebGL support?
  • Test canvas position fixed vs transform: translate()?
  • Culling?
  • Blending modes?
  • Support text?
  • Create components for react / vue.js?
  • See if magicshader can be implemented easily?

GitHub

https://github.com/luruke/aladino
You might also like...

Magic Quadrant built with React & Typescript

Magic Quadrant Interactive Magic Quadrant built with React & Typescript Demo Demo Link Firebase: https://magic-quadrant-3eaf1.web.app/ Usage Install D

Apr 10, 2022

Bindings for using react-navigation with react-native-magic-move ๐Ÿฐ๐ŸŽฉโœจ

Bindings for using react-navigation with react-native-magic-move ๐Ÿฐ๐ŸŽฉโœจ

react-navigation-magic-move Bindings for using react-navigation with react-native-magic-move ๐Ÿฐ ๐ŸŽฉ โœจ Why is this needed react-native-magic-move trigge

Feb 15, 2022

A Magic Memory Game Built with ReactJS

A Magic Memory Game Built with ReactJS

Jun 11, 2022

A Simple Magic paint app made with React

A Simple Magic paint app made with React

React Magic painter Simple paint app made with React, custom hooks, Canvas API, font awesome and lots of โค๏ธ Demo https://magic-painter.netlify.app/ Mo

Jun 24, 2022

React-magic-scroll - A react library for adding some effect you want when scroll

react-magic-scroll A react library for adding some effect you want when scroll.

May 13, 2022

React Native Web's Pressable, but with Remix's Link magic

React Native Web's Pressable, but with Remix's Link magic

May 28, 2022

Ams Date Picker - A magic date picker component for React

Ams Date Picker  - A magic date picker component for React

Ams Date Picker (React) - A magic date picker component for React. We have your favorite modifiers and input supercharge.

Jun 15, 2022

Connect, discover, be free to choose between WebGL / Canvas (PIXI) / DOM or any other UI renderer

Connect, discover, be free to choose between WebGL / Canvas (PIXI) / DOM or any other UI renderer

React Liberty Be free to choose between WebGL / Canvas / DOM / Native or any other UI renderer This is a React library designed to abstract renderer b

May 24, 2022

๐Ÿฆโ€ข [Work in Progress] React Renderer to build UI interfaces using canvas/WebGL

๐Ÿฆโ€ข [Work in Progress] React Renderer to build UI interfaces using canvas/WebGL

React Ape React Ape is a react renderer to build UI interfaces using canvas/WebGL. React Ape was built to be an optional React-TV renderer. It's mainl

Jun 21, 2022

gl-react โ€“ React library to write and compose WebGL shaders

gl-react โ€“ React library to write and compose WebGL shaders

gl-react is a React library to write and compose WebGL shaders. Implement complex effects by composing React components.

Apr 14, 2022

gl-react is a React library to write and compose WebGL shaders.

gl-react is a React library to write and compose WebGL shaders.

gl-react is a React library to write and compose WebGL shaders. Implement complex effects by composing React components.

Aug 23, 2021

WebGL effects for React elements

WebGL effects for React elements

REACT-VFX: WebGL effects for React elements!! Install npm i -S react-vfx Usage REACT-VFX exports VFXSpan, VFXImg and VFXVideo. These components works

Jun 14, 2022

The open-source fork of Mapbox GL JS: Interactive maps in the browser, powered by vector tiles and WebGL.

The open-source fork of Mapbox GL JS: Interactive maps in the browser, powered by vector tiles and WebGL.

Jun 25, 2022

๐Ÿ—บ Mandelbrot set and Julia set explorer made with React and WebGL

๐Ÿ—บ Mandelbrot set and Julia set explorer made with React and WebGL

Mandelbrot Maps Mandelbrot Maps is an interactive fractal explorer built using React and WebGL.

Apr 15, 2022

5kB WebGL globe lib.

5kB WebGL globe lib.

A lightweight (5kB) WebGL globe lib. The name "COBE" stands for Cosmic Background Explorer. Demo and configurations Use with React: https://codesandbo

Jun 22, 2022

Experiment in creating a custom react renderer using an offscreen webgl canvas on top of Skia CanvasKit

Experiment in creating a custom react renderer using an offscreen webgl canvas on top of Skia CanvasKit

React-CanvasKit Experimental implementation of Skia CanvasKit using ReactJS. This implementation allows you to use all familiar React concepts like ho

Jun 16, 2022

React component for Globe Data Visualization using ThreeJS/WebGL

React component for Globe Data Visualization using ThreeJS/WebGL

react-globe.gl React bindings for the globe.gl UI component. A React component to represent data visualization layers on a 3-dimensional globe in a sp

Jun 18, 2022

React Fiber Reconciler Renderer for Regl WebGL

react-regl This library enables Regl shader WebGL draw commands to be rendered directly as React components. Demos View demos in the Storybook There i

Jun 10, 2022

Reagraph - a high-performance network graph visualization built in WebGL for React

๐Ÿ•ธ reagraph WebGL Network Graphs for React Reagraph is a high-performance network graph visualization built in WebGL for React. If you are looking for

Jun 24, 2022
Comments
  • 1. no license

    Hello,

    May we know the license for the repo? GitHub also encourages us to have a license for public repo (under "Licensing a repository - GitHub Docs"). We would like to highlight this as a transparency concern.

    The following are from GitHub Docs. ยท "If you're creating an open source project, we strongly encourage you to include an open source license." ยท "If you publish your source code in a public repository on GitHub Enterprise Server, other users of your GitHub Enterprise Server instance have the right to view and fork your repository." ยท "Public repositories on GitHub are often used to share open source software. For your repository to truly be open source, you'll need to license it so that others are free to use, change, and distribute the software."

    Regards, Software Ethics Researcher.

    Reviewed by SoftwareEthicsResearcher at 2022-06-03 06:44
  • 2. FEATURE REQUEST: Create images wrapped into a 3D globe (100 images and clickable)

    also...

    It would be awesome if your script could handle creating HTML5 cards with images and text info and those cards can be rendered and scroll -x or -y with a smooth webgl slider animation

    Best regards

    Reviewed by inglesuniversal at 2021-11-21 06:07
  • 3. Please continue to build this library

    Hey there,

    Just wanted to drop by and say this library is a godsend! There's literally nothing like this out and for us creative devs that can't dedicate the time and resources to delved to the true abyss that is WebGL and shaders, this library is exactly what we're looking for!

    This can definitely be THE next library. Please please please continue to maintain and build this library!

    Thanks!

    Reviewed by MrUltimate at 2021-10-16 04:11
  • 4. Rubberband scrolling not always handled

    If I start scrolling up when it's already at scrollY=0, it works well, but if I have it overscroll up from anywhere below 0, it loses the effect until I go back to 0 and wait a moment

    Safari 14.0.3, macOS

    Also, hi #1

    Reviewed by fregante at 2021-03-16 19:34
Find and record your favourite photo spots. Built using React using Google API.
Find and record your favourite photo spots. Built using React using Google API.

Photo Locations Photo Locations is a personal project. When travelling with family or friends, you often don't have enough time to extensively researc

Mar 8, 2022
React hooks for generating Barcode for your next React apps.
React hooks for generating Barcode for your next React apps.

react-barcodes React hooks for generating Barcodes. Live demo ?? Features Compatible with both JavaScript and TypeScript Generate as SVG, Canvas and I

Jun 13, 2022
Beautifully crafted unique avatar placeholder for your next react project
Beautifully crafted unique avatar placeholder for your next react project

Avvvatars Beautifully crafted unique avatar placeholder for your next react project Lightweight and customizable โค๏ธ demo.mp4 Live Demo ?? | Website ??

Jun 4, 2022
React Unity WebGL provides an easy solution for embedding Unity WebGL builds in your React application, with two-way communication between your React and Unity application with advanced API's.
React Unity WebGL provides an easy solution for embedding Unity WebGL builds in your React application, with two-way communication between your React and Unity application with advanced API's.

React Unity WebGL provides an easy solution for embedding Unity WebGL builds in your React application, with two-way communication between your React and Unity application with advanced API's.

Jun 22, 2022
Magic-Selector - Magic Selector Project developed in React
Magic-Selector - Magic Selector Project developed in React

Magic Selector ?? Projeto desenvolvido em React com objetivo de explorar melhor

Jan 31, 2022
Lazy load & transition your React images with some WebGL glsl niceness ๐ŸŽ‰
Lazy load & transition your React images with some WebGL glsl niceness ๐ŸŽ‰

react-gl-transition-image ?? Lazy load & transition your React images with some WebGL glsl niceness ?? . Easy to use, offers 8 different transitions o

May 2, 2022
react-magic-move - MagicMove wrapper.

React Magic Move Magic Move for React.JS NOT A PRODUCTION MODULE This was just a fun experiment, with some love, it could definitely be a real thing,

May 27, 2022
Automatically AJAXify plain HTML with the power of React. It's magic!

React-Magic and HTMLtoJSX React-Magic is an experimental library that uses the power of Facebook's React library to inject AJAX-loading goodness into

Jun 21, 2022
Automatically AJAXify plain HTML with the power of React. It's magic!

React-Magic and HTMLtoJSX React-Magic is an experimental library that uses the power of Facebook's React library to inject AJAX-loading goodness into

Jun 21, 2022
A image magic module for react native

react-native-imagewand React native image wand view for android. Enabling you to do instagram like effects to images Installation npm i --save react-n

Mar 21, 2019