npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@babylonjs/lite-gl

v1.19.0

Published

Function-based, tree-shakeable WebGL2 micro-engine for fullscreen effects, sprites and dynamic textures — the WebGL counterpart of @babylonjs/lite.

Readme

@babylonjs/lite-gl

A tiny, function-based, tree-shakeable WebGL2 micro-engine for fullscreen shader effects, sprites and dynamic textures — the WebGL counterpart of @babylonjs/lite. No classes, no scene graph: you call plain functions against an opaque GLEngineContext, so a bundler keeps only what you import.

It is a focused subset of Babylon.js' rendering primitives, validated to render near-identically (within ±1–2 LSB ANGLE / SwiftShader codegen noise) to Babylon's ThinEngine / EffectRenderer / SpriteRenderer / HtmlElementTexture path — every feature has a side-by-side parity scene in tests/gl/parity/ (and, downstream, the NeonBrush effect suite). Swapping @babylonjs/core for lite-gl typically shrinks an effect's shipped bundle ~10–16× (≈4–6 KB gzip vs ≈40–80 KB).

WebGL2 only. The context is created with canvas.getContext("webgl2").

Install

npm install @babylonjs/lite-gl

Quick start — an animated fullscreen effect

import { createGLEngine, createEffectWrapper, isEffectReady, applyEffectWrapper, drawEffect, setViewport, setEffectFloat, runRenderLoop, resizeGLEngine } from "@babylonjs/lite-gl";

const canvas = document.getElementById("renderCanvas") as HTMLCanvasElement;
const engine = createGLEngine(canvas, { alpha: false });

// The wrapper compiles + owns the effect. `vertexSource` defaults to a built-in
// fullscreen-quad shader (exposing a `vUv` varying), so only `fragmentSource`
// is required.
const wrapper = createEffectWrapper(engine, {
    name: "gradient",
    fragmentSource: `#version 300 es
        precision highp float;
        in vec2 vUv;
        out vec4 glFragColor;
        uniform float uTime;
        void main() {
            glFragColor = vec4(0.5 + 0.5 * cos(uTime + vUv.xyx + vec3(0.0, 2.0, 4.0)), 1.0);
        }`,
    uniformNames: ["uTime"],
});

const start = performance.now();
runRenderLoop(engine, () => {
    if (!isEffectReady(engine, wrapper.effect)) return; // shaders compile async
    resizeGLEngine(engine);
    setViewport(engine);
    applyEffectWrapper(wrapper);
    setEffectFloat(engine, wrapper.effect, "uTime", (performance.now() - start) / 1000);
    drawEffect(engine);
});

Effect readiness and errors

createEffect / createEffectWrapper submit compilation and linking without querying their results. With KHR_parallel_shader_compile, readiness checks poll completion before inspecting link status. Shader status and info logs are queried only after link failure, avoiding premature compilation stalls. Without the extension, checking link status can block.

Manual polling stays available: call isEffectReady(engine, effect) in your render loop and inspect getEffectCompilationError(engine, effect) when it returns false. The error accessor also polls once; null means no failure has been recorded, not necessarily that the effect is ready. Errors include the program log and failing shader stages' logs and are logged once. Neither this accessor nor executeWhenCompiled starts automatic polling.

To wait before starting a render loop, opt into the tree-shakeable helper:

import { waitForEffect } from "@babylonjs/lite-gl";

const controller = new AbortController();
try {
    await waitForEffect(engine, wrapper.effect, { signal: controller.signal });
    // The effect is finalized; rendering can now start.
} catch (error) {
    console.error("Effect could not become ready:", error);
}

The helper polls once per animation frame without registering a render loop. It rejects on compile/link/restore failure, context loss, disposal (on the next poll), or cancellation via controller.abort(), and cleans up its frame and listeners on every exit. Cancelling a wait does not dispose a shared effect. After context restoration, call it again to wait for the replacement program. Already ready effects resolve without scheduling a frame; consumers that only use manual polling ship none of the helper's scheduling code.

Migration: shader syntax errors no longer throw synchronously from createEffect or createEffectWrapper. Poll isEffectReady and inspect getEffectCompilationError, or catch a rejected waitForEffect promise instead. For wrappers, pass wrapper.effect to these readiness/error APIs. Shader/program allocation failures still throw synchronously.

Entry points

The entire public API is available from the single @babylonjs/lite-gl entry: engine + render loop, effects & uniform setters, textures (incl. float / HDR + dynamic), the EffectWrapper fullscreen-quad renderer, render targets, meshes / vertex-index buffers + instancing, depth / stencil / color-mask / clear, scissor, blend modes, the sprite renderer, and HTML-element textures. The package is sideEffects: false, so a bundler tree-shakes away whichever features you don't use.

Core API (@babylonjs/lite-gl)

  • Engine / lifecycle — createGLEngine, disposeGLEngine, resizeGLEngine, getRenderWidth, getRenderHeight, get/setHardwareScalingLevel, getRenderingCanvas, and on/offContextLost + on/offContextRestored (context-loss is handled: effects and textures are rebuilt on restore).
  • Render loop — runRenderLoop, stopRenderLoop.
  • Effects — createEffect, isEffectReady, getEffectCompilationError, executeWhenCompiled, waitForEffect (optional cancellable readiness promise), useEffect, disposeEffect, and the cached uniform setters setEffectFloat / …Float2 / …Float3 / …Float4 / …Int / …Color3 / …Color4 / …Texture.
  • Fullscreen renderer — createEffectWrapper, applyEffectWrapper, drawEffect, setViewport, disposeEffectWrapper.
  • Textures — createRawTexture (typed-array upload, LDR byte formats), createTextureFromSource (single upload from already-decoded bitmaps/canvases/images), createTexture3DFromPixels + setEffectTexture3D (optional native RGBA8 LUT volumes with trilinear sampling and zero 2D-only bundle cost), createFloatTexture (float / half-float HDR opt-in), generateTextureMipMaps, loadTexture2D (async URL upload with a 1×1 placeholder), bindTexture, disposeTexture, plus updateRawTexture, updateTextureSamplingMode, updateTextureWrapMode, createTextureFromHandle.
  • Dynamic textures — createDynamicTexture, updateDynamicTexture, clearDynamicTextureSource (the retained source is replayed on context-restore).
  • Render targets — createRenderTarget (RGBA8 FBO with a sampleable color GLTexture + optional depth / stencil renderbuffer), createFloatRenderTarget (float / half-float HDR opt-in), bindRenderTarget (cached, null = the canvas), resizeRenderTarget, generateRenderTargetMipMaps, readRenderTargetPixels, disposeRenderTarget.
  • Meshes / buffers — createVertexBuffer, updateVertexBuffer, createIndexBuffer, bindAttributes, drawIndexed (instanced), disposeBuffer.
  • Depth / stencil / scissor — setDepthState, setStencilState, setStencilOpSeparate (independent front/back operations), setCullState, setColorMask, clearEngine; setScissor, disableScissor.
  • Blend — setBlendMode + GLBlendMode (DISABLE / ADD / ALPHA / PREMULTIPLIED), matching Babylon's setAlphaMode parameters.

Already-decoded textures

import { createTextureFromSource, disposeTexture } from "@babylonjs/lite-gl";

const texture = createTextureFromSource(engine, bitmap);
// One texImage2D upload, linear filtering and clamp-to-edge by default.
// Later, release the GPU resource:
disposeTexture(engine, texture);

The factory accepts TexImageSource (including ImageBitmap, ImageData, canvas/offscreen canvas, decoded images, video and video frames), derives the intrinsic size, and performs no placeholder or blank allocation first. Video elements must have a decoded current frame (readyState >= 2, HAVE_CURRENT_DATA), not just metadata with positive dimensions. A retained video that loses its current frame restores as transparent black with a logged error, like other unusable retained sources. GLTextureSourceOptions configures filtering/wrapping and unpack flags. For ImageBitmap, WebGL ignores unpack flip/premultiplication; choose those settings during decoding instead. Convert SVG or density-selected (srcset) images to an ImageBitmap first, since WebGL may upload them at a size other than their natural size.

Sources are retained for automatic context restoration by default, so keep retained bitmaps/frames open while their texture is live. Pass { retainSource: false } when your application owns recovery: the source reference is dropped after upload and can be closed, but context restoration produces a ready, transparent-black texture at the original size. Recreate the texture after restore (for example from onContextRestored) to recover its content. Mutable retained sources replay their current pixels and intrinsic size. If a retained source was closed anyway, restore logs an error and falls back to transparent black for that texture only. Mipmaps generated with generateTextureMipMaps are not replayed; regenerate them after restore. No source is closed by lite-gl.

Demos

Runnable scenes for every feature live in the repo's GL lab (lab/gl/) — fullscreen effects, textures, sprites, blend modes, HTML-element textures and render-to-texture round-trips. The standalone /gl/texture-3d-test.html source test (lab/gl/src/texture-3d-test.ts) checks native 3D texel addressing and trilinear filtering without a gallery demo.

License

Apache-2.0