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

@niccolofanton/morphing-ascii-shader

v1.0.1

Published

Real-time ASCII / halftone post-processing effect for three.js + pmndrs/postprocessing: glyph-atlas luminance mapping, Sobel edge glyphs, per-cell temporal memory and SDF shape morphing.

Downloads

332

Readme

ASCII Shader

Real-time ASCII / halftone post-processing toolkit for three.js + pmndrs/postprocessing. Maps video (or any rendered scene) to a glyph atlas by luminance, with Sobel edge glyphs, per-cell temporal memory (each cell morphs gradually toward its target), a bloom-like ink bleed, film grain with blend modes, and SDF shape morphing between glyphs.

Ships as an installable package of Effect subclasses — drop them into your own postprocessing pipeline. The repo also includes a full demo (examples/) with a frosted-glass UI.

Install

npm install @niccolofanton/morphing-ascii-shader three postprocessing

three and postprocessing are peer dependencies — you provide them in your app.

Usage

import { EffectComposer, RenderPass, EffectPass } from 'postprocessing';
import { AsciiEffect, InkBleedEffect } from '@niccolofanton/morphing-ascii-shader';

const composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene, camera));

const ascii = new AsciiEffect({
  cellSize: 16,
  colorMode: 2,       // glyphs in the video's color on white
  glyphBlend: true,   // cross-fade between adjacent glyphs
  edges: true,        // Sobel contour glyphs
});
composer.addPass(new EffectPass(camera, ascii));

// optional: ink bleed as a separate pass downstream
composer.addPass(new EffectPass(camera, new InkBleedEffect({ bleed: 0.5, radius: 24 })));

// in your render loop:
composer.render(dt);

Per-cell memory & SDF shape morph (optional)

MemoryGrid gives each cell memory so it morphs gradually toward its target instead of snapping. It is not an Effect — update it each frame before composer.render():

import { MemoryGrid } from '@niccolofanton/morphing-ascii-shader';

const ascii = new AsciiEffect({ useMemory: true, glyphBlend: true, sdfMorph: true });
const memory = new MemoryGrid(renderer, videoTexture, { rate: 2.25 });

function animate(dt) {
  memory.setSize(bufferW, bufferH, ascii.cellSize);
  ascii.gridSize = memory.gridSize;
  ascii.memoryTexture = memory.update(dt);
  composer.render(dt);
}

With sdfMorph: true the current glyph transforms into the shape of the target glyph (distance-field interpolation, “face-morph” style) instead of cross-fading.

API

| Export | Type | Notes | |---|---|---| | AsciiEffect | Effect | glyph-atlas ASCII effect (luminance, Sobel, grain, memory, SDF morph) | | InkBleedEffect | Effect | bloom-like ink bleed (Vogel-disk sampling + blur) | | MemoryGrid | helper | per-cell temporal memory (ping-pong RT); update each frame | | DEFAULT_CHARSET | string | default density glyphs ' ·•+✦★○◯●' | | DEFAULT_EDGE_CHARS | string | default edge glyphs - \| / \\ |

TypeScript definitions are bundled (types/index.d.ts).

Parameters

Every parameter is documented in depth — type, default, range, what it does, its visual effect and interactions — each with an animated GIF showing exactly what it changes.

📖 → Full parameter reference with GIFs: docs/PARAMETERS.md

Covers all of AsciiEffect, InkBleedEffect and MemoryGrid:

| Group | Parameters | |---|---| | Grid & glyphs | cellSize, glyphScale, charset, variety, invert | | Color | colorMode, ink, background, whiteCutoff | | Luminance | brightness, contrast, gamma | | Edges | edges, edgeThreshold, edgeChars | | Memory & morph | useMemory, glyphBlend, magnet, sdfMorph, sdfThreshold, sdfAA, rate | | Grain | colorVar, noise, noiseScale, noiseMode | | Ink bleed | bleed, radius, blur |

Features

  • Glyph-atlas ASCII — per-cell luminance picks a glyph from a runtime atlas, with per-cell variety for the “mixed symbols” look.
  • Sobel edge detection (optional) with dedicated directional glyphs (- | / \) on contours.
  • Per-cell memory — each cell morphs gradually toward its target color/luminance (exponential smoothing, no flicker), with a “magnetic” cross-fade between glyphs.
  • SDF shape morph — glyphs transform into one another via signed-distance-field interpolation (the characters act as keyframes).
  • Ink bleed as a separate bloom-like pass (Vogel-disk sampling) with built-in blur.
  • Film grain (static) with selectable blend modes (Add, Multiply, Screen, Overlay, Soft Light, Burn, Dodge…).
  • Layer blending — every effect composites with postprocessing's native blend functions.

Run the demo

npm install        # install dev dependencies (three, postprocessing, tweakpane, …)
npm run dev        # Vite dev server serving examples/ (default http://localhost:5173)

Build the demo as a static site: npm run build:demo (outputs demo-dist/).

The demo's panel uses @niccolofanton/driftpane for persistence, drag and presets. If a clone fails to install it, it only affects the demo, not the library.

Build the library

npm run build      # bundles src/ → dist/index.js (ESM), three & postprocessing external

npm pack produces the publishable tarball (dist/, types/, src/, README.md).

How it works

The demo is a full-screen quad with a VideoTexture; on top runs the pipeline EffectComposer → RenderPass → EffectPass(ASCII) → EffectPass(InkBleed).

  • Luminance → glyph (UV-sampled atlas) — technique by Maxime Heckel.
  • Sobel contour glyphs — inspired by humanbydefinition.
  • Per-cell memory: a ping-pong of grid-resolution render targets (one texel per cell) keeps state between frames; each cell converges with exponential inertia. The “morph activity” drives the magnetic cross-fade / SDF morph.
  • SDF morph: glyphs are also rasterized to a signed-distance-field atlas (EDT at init); interpolating the two distance fields and thresholding produces in-between shapes.

Project structure

package.json            # package manifest + scripts (dev / build / build:demo)
vite.config.js          # library build (lib mode → dist/)
vite.config.demo.js     # demo dev/build (root = examples/)
src/                    # the published package
  index.js              # entry point (re-exports)
  AsciiEffect.js        # ASCII effect (glyph atlas + Sobel + grain + SDF morph)
  MemoryGrid.js         # per-cell memory (ping-pong RT, morph)
  InkBleed.js           # bloom-like ink bleed (Vogel spiral + blur)
types/index.d.ts        # TypeScript definitions
examples/               # demo app (uses the library)
  index.html, main.js, overlay.js
  public/assets/        # source videos + preview.gif
tools/                  # procedural video generators (numpy + ffmpeg)

Source code comments are in Italian.

Stack

three.js 0.161 · postprocessing 6.36.3 (peer) · demo UI via Tweakpane 4.0.5 + @niccolofanton/driftpane — bundled by Vite.

Assets

The “flower” videos are procedurally generated (tools/gen_flowers.py, tools/gen_flower.py) with numpy + ffmpeg.

Credits / licenses of the demo sources included:

  • Bad Apple!! — the well-known Touhou shadow-art PV; copyright of its respective authors.
  • Big Buck Bunny — © Blender Foundation, CC-BY 3.0.
  • Fragole (strawberries) — sample clip.
  • 17 flowers — procedurally generated (see tools/).

License

MIT © Niccolò Fanton