🧞‍♂ī¸ Your magic WebGL carpet

Related tags

Effect webgl glsl shader
Overview

⚠ī¸ ⚠ī¸ 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>
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?
You might also like...

Very simple threejs boilerplate in VanillaJS to start your projects. There is only a basic scene, a load model method and a simple webpack.

Very simple threejs boilerplate in VanillaJS to start your projects. There is only a basic scene, a load model method and a simple webpack.

Ektogamat ThreeJS Boilerplate by Anderson Mancini Introduction This is a three.js starter project with only 120 lines. But why create another threejs

Jan 3, 2023

Some compile-time magic for your Vite project

💛 You can help the author become a full-time open-source maintainer by sponsoring him on GitHub. vite-plugin-compile-time Use this plugin to generate

Dec 15, 2022

Adds a handy $parent magic property to your Alpine components.

✨ Help support the maintenance of this package by sponsoring me. Alpine $parent Access parent components using a handy $parent magic variable. This pa

Aug 29, 2022

Magic number detection for JavaScript

Magic number detection for javascript. Let Buddy sniff out the unnamed numerical constants in your code. Overview What are magic numbers? Installation

Dec 24, 2022

Source code for Chrome/Edge/Firefox/Opera extension Magic CSS (Live editor for CSS, Less & Sass)

Live editor for CSS, Less & Sass (Magic CSS) Extension Live editor for CSS, Less & Sass (Magic CSS) for Google Chrome, Microsoft Edge, Mozilla Firefox

Dec 13, 2022

A vanishing effect for particles and magic lovers using Threejs, GSAP and custom shaders.

A vanishing effect for particles and magic lovers using Threejs, GSAP and custom shaders.

Three.js Experiment - Vanishing Suzanne Demo version Get started First, you need nodejs on your computer to build the assets. Install dependencies: np

Dec 23, 2022

A CLI utility to calculate/verify accessible magic numbers for a color palette.

A CLI utility to calculate/verify accessible magic numbers for a color palette.

A11y Contrast A CLI utility to calculate/verify accessible magic numbers for a color palette. Read my blog post for some more information. Installatio

Nov 13, 2022

Server and Browser code are really the same. It's magic.

Server and Browser code are really the same. It's magic.

Service Worker Magic Server (Cloudflare Workers) code is sw.js. Browser ( Service Worker ) code is sw.js. Cloudflare Workers sw.js serves sw.js. Servi

Dec 9, 2022

Weather-magic - Working with APIs to create a weather dashboard

Weather-magic - Working with APIs to create a weather dashboard

Weather Magic link to website Following the link above will bring you to the Wea

Feb 3, 2022

Querying Solana Blockchain, leveraging Magic Eden Apis!

Querying Solana Blockchain, leveraging Magic Eden Apis!

Solana Bot Deployment Instructions- Create a bot on discord dev portal learn basics here Copy the Bot Token and go to OAuth field for URL generation F

Sep 8, 2022

Extended magic-string with extra utilities

DEPRECATED. It has been ported back to magic-string = 0.26.0 magic-string-extra Extended Rich-Harris/magic-string with extra utilities. Install npm i

Sep 8, 2022

This a programming training app, aimed to help OMRI's students learng the magic world of programming.

OMRI App (fe-omri-app) This a programming training app, aimed to help OMRI's students learng the magic world of programming. Install the dependencies

Nov 19, 2022

The Remix Stack for Web2 apps and Web3 DApps with authentication with Magic, testing, linting, formatting, etc.

The Remix Stack for Web2 apps and Web3 DApps with authentication with Magic, testing, linting, formatting, etc.

Remix French House Stack Learn more about Remix Stacks. npx create-remix --template janhesters/french-house-stack What's in the Stack? The French Hou

Dec 26, 2022

MagicSniffer is a amazing tool could help you decrypt GI traffic by MAGIC of WindSeedClientNotify

MagicSniffer We have posted an article about this on sdl.moe: 原įĨž 2.8 KCP éĒŒč¯å¯†é’Ĩäē¤äē’æĩį¨‹č§Ŗ析与æĩé‡č§Ŗ密 As everyone knows, RSA is the most secure way to encrypt data

Dec 29, 2022

Flexible JavaScript library for creating squircley magic ✨

Flexible JavaScript library for creating squircley magic ✨

squircley.js squircley.js is the core squirclular magic ✨ from https://squircley.app wrapped up into a simple, 0 dependency JavaScript library. squirc

Dec 24, 2022

Kittos is NFT Marketplace built with Next Js, Hardhat, Solidity, Arweave + Bundlr Client and All The CSS Magic with TailwindCSS. đŸ˜ē

Kittos is NFT Marketplace built with Next Js, Hardhat, Solidity, Arweave + Bundlr Client and All The CSS Magic with TailwindCSS. đŸ˜ē

Kittos NFT Marketplace đŸ˜ē Built with Next Js, Hardhat, Solidity, Arweave, Bundlr and Tailwind CSS. Functionalities New Listed Assets Mint NFT Buy NFT

Dec 24, 2022

It's an AI Tag (Prompt) generator for magic drawer! We have many tags and support to generate prompts easily!

It's an AI Tag (Prompt) generator for magic drawer! We have many tags and support to generate prompts easily!

魔å¯ŧįģĒčŽē AI 魔咒į”Ÿæˆå™¨, äŊŋį”¨į”ą B įĢ™ UP ä¸ģ 十äēŒäģŠå¤ŠäšŸåžˆå¯įˆą 提䞛įš„ 4 万ä¸Ē tag åšļ提䞛中文æŖ€į´ĸīŧŒåšļ提䞛äē†é­”å’’į¤žåŒēæ–šäžŋ魔æŗ•å¸ˆäģŦį›´æŽĨ复åˆļį”Ÿæˆã€‚æ°¸čŋœå…č´šīŧŒæ°¸æ— åšŋ告īŧŒæ— å•†ä¸šã€‚ v2 į‰ˆæœŦ更新内厚 äŊŋį”¨ Netlify įš„äē‘å‡Ŋ数提䞛更ä¸ēåŋĢ速įš„į¤žåŒē数捎操äŊœīŧīŧˆæš‚æ—ļ不įŸĨé“čŠąč´šå¤šå°‘īŧ‰ æŸĨįœ‹č‡Ēåˇąįš„

Jan 1, 2023

Add a water ripple effect to your background using WebGL.

jQuery Ripples Plugin By the powers of WebGL, add a layer of water to your HTML elements which will ripple by cursor interaction! Important: this plug

Dec 30, 2022

Space Invaders in your browser with 3D WebGL. Built with BabylonJS.

Space Invaders in your browser with 3D WebGL. Built with BabylonJS.

Space Invaders A fun re-imagining of the 1978 classic by Tomohiro Nishikado and Taito. Play it here: https://spaceinvaders.viperfish.com.au Play in th

Dec 26, 2022
Comments
  • FEATURE REQUEST: Create images wrapped into a 3D globe (100 images and clickable)

    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

    opened by inglesuniversal 0
  • Please continue to build this library

    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!

    opened by MrUltimate 1
  • Rubberband scrolling not always handled

    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

    opened by fregante 0
Owner
Luigi De Rosa
Interactive lead @activetheory Creative development, WebGL, JavaScript and performance
Luigi De Rosa
Add a water ripple effect to your background using WebGL.

jQuery Ripples Plugin By the powers of WebGL, add a layer of water to your HTML elements which will ripple by cursor interaction! Important: this plug

Pim Schreurs 976 Dec 30, 2022
sync CSS 3D transformations to a WebGL scene

gl-css3d Synchronize CSS 3D transformations to a WebGL scene Usage: var createCSS3D = require('gl-css3d'); // pass an HTML DOM element node, such as

null 30 Oct 17, 2022
Animated haze distortion effect for images and text, with WebGL.

Animated Heat Distortion Effects with WebGL A tutorial on how to use fragment shaders in WebGL to create an animated heat haze distortion effect on im

Lucas Bebber 289 Nov 1, 2022
Some experimental rain and water drop effects in different scenarios using WebGL, by Lucas Bebber.

Rain & Water Effect Experiments Some experimental rain and water drop effects in different scenarios using WebGL, by Lucas Bebber. Article on Codrops

Codrops 1.4k Jan 4, 2023
A JavaScript library for advanced 2D slideshow with WebGL, that provides variety of beautiful effects

gl-slideshow An advanced 2D slideshow with WebGL, provides a variety of beautiful effects with GLSL power. Shaders are forked from https://gl-transiti

Akihiro Oyamada 68 Nov 28, 2022
A JavaScript library for advanced 2D slideshow with WebGL, that provides variety of beautiful effects

gl-slideshow An advanced 2D slideshow with WebGL, provides a variety of beautiful effects with GLSL power. Shaders are forked from https://gl-transiti

Akihiro Oyamada 69 Jan 1, 2023
:tada: Add a cute click effect to your mouse in your vuepress!

vuepress-plugin-cursor-effects ?? Add a cute click effect to your mouse in your vuepress! Document: moefy-vuepress LiveDemo: notev Install yarn add vu

null 19 Sep 25, 2022
Only 90's kids remember... well not really, but these beloved effects that would follow your mouse around will always be classic reminders of the old, beloved internet.

90's Cursor Effects "Knowing the codes" used to be all the rage, I want to bring a few back. A repo of the old effects that inspired creativity and th

Tim Holman 2.6k Jan 9, 2023
PowerModeInput can make your text input box more compelling

PowerModeInput PowerModeInput can make your text input box more compelling This project can make your input box lively. One day I saw a vscode plugin

lindelof 74 Dec 2, 2022
Animatelo is a bunch of cool, fun, and cross-browser animations for you to use in your projects. This is a porting to Web Animation API of the fabulous animate.css project.

Animatelo Just-add-water Web Animations Animatelo is a bunch of cool, fun, and cross-browser animations for you to use in your projects. Great for emp

GibboK 477 Nov 12, 2022