Character animation for the web: emotions, gestures and elemental GLSL shaders. Canvas 2D and WebGL 2. MIT.
翻訳待ち
Loading the full README.
Read the full README ↗Character animation for the web: emotions, gestures and elemental GLSL shaders. Canvas 2D and WebGL 2. MIT.
Real-time character animation engine with Canvas 2D and WebGL 3D rendering. 8 elemental shader systems. 160 elemental gestures. One replicable pattern.
Live · emotiveengine.com · Demo · elemental gestures · npm · @joshtol/emotive-engine · Status · active
npm install @joshtol/emotive-engine
import { EmotiveMascot3D } from '@joshtol/emotive-engine/3d';
const mascot = new EmotiveMascot3D({
coreGeometry: 'crystal',
assetBasePath: '/assets', // self-hosted assets (see below)
});
mascot.init(document.getElementById('container'));
mascot.start();
mascot.setEmotion('joy');
mascot.express('bounce');
mascot.morphTo('heart');
mascot.feel('happy, bouncing'); // Natural language control
3D mode requires Three.js (npm install three, version 0.170 or later) and a
browser with WebGL 2. Without WebGL 2, init() logs a warning and renders
nothing; it does not fall back to Canvas 2D, which is the separate
@joshtol/emotive-engine import below.
import { EmotiveMascot } from '@joshtol/emotive-engine';
const mascot = new EmotiveMascot();
await mascot.init(document.getElementById('container'));
mascot.start();
mascot.feel('happy, bouncing');
2D mode has no dependencies and requires no external assets. Both modes need
Node 20 or later to build (engines).
Every build is a separate entry, so a page that shows one elemental does not pay
for the other seven. Sizes are brotli over the wire (npm run size:report);
Three.js is a peer dependency and is not included in the 3D numbers.
| Import | Brotli | What you get |
|---|---|---|
@joshtol/emotive-engine | 178 KB | 2D canvas engine |
@joshtol/emotive-engine/lean | 166 KB | 2D, no rhythm sync / accessibility / profiling |
@joshtol/emotive-engine/minimal | 67 KB | 2D loading-screen build |
@joshtol/emotive-engine/3d | 232 KB | 3D, no elementals |
@joshtol/emotive-engine/3d-<element> | 249 to 256 KB | 3D + one elemental (see below) |
@joshtol/emotive-engine/3d-elementals | 303 KB | 3D + all eight elementals |
The eight single-element entries are 3d-fire, 3d-water, 3d-ice,
3d-electric, 3d-earth, 3d-nature, 3d-light and 3d-void. Each registers
only its own element and gestures; the other elements' shaders and gestures are
not in the file.
// A page that only shows the electric elemental
import { EmotiveMascot3D } from '@joshtol/emotive-engine/3d-electric';
const mascot = new EmotiveMascot3D({
coreGeometry: 'crystal',
assetBasePath: '/assets',
maxPixelRatio: 1.5, // cap the DPR (default 2.0): sharpness vs fill rate
hdri: false, // skip the optional 1.7 MB studio HDRI
glowHalo: false, // no screen-space halo when the canvas bleeds past its slot
surface: 'light', // or mascot.setSurface('light'): arcs drawn as ink on light pages
});
mascot.init(document.getElementById('container'));
mascot.start();
mascot.express('shock'); // any electric gesture; fire gestures etc. are not registered
A gesture from an element that is not in the entry is simply unknown to
express(). Import 3d-elementals when a page switches between elements.
Shared: 15 emotions · 179 gestures · Natural language feel() API ·
TypeScript definitions · Unified API
The npm package ships JavaScript only. GLB models, textures, and HDRI maps
must be self-hosted. They live in assets/ in this repository. The 3D engine
loads WebP textures (Crystal 282 KB, Moon 1.2 MB, Sun 0.8 MB); the PNG/JPEG
sources sit beside them and are not requested at runtime.
new EmotiveMascot3D({
assetBasePath: '/assets', // wherever you host the assets folder
});
| Hosting option | assetBasePath |
|---|---|
Copy to public/ | '/assets' |
| CDN / S3 | 'https://cdn.example.com/emotive-engine/assets' |
| GitHub Pages | 'https://joshtol.github.io/emotive-engine/assets' |
<assetBasePath>/
├── models/Elements/ # GLB models for elemental effects
├── textures/ # Crystal, Moon, Sun textures
└── hdri/ # Environment maps (optional)
This is the beginning of the README. Read the rest at the original. Read the full README ↗