Get Started with OpenHuman WebGL

OpenHuman is a pure WebGL 2.0 digital human render engine - zero runtime dependencies (no Three.js, no Babylon.js). It is designed to be embedded as an SDK into any website or application.

This guide walks you through installing and running the OpenHuman WebGL engine in your project.


Requirements

Before you begin, make sure your environment meets the following requirements:

  • Node.js 18+ (for build tooling only - the engine itself has zero runtime dependencies)
  • A browser supporting WebGL 2.0: Chrome 60+, Firefox 55+, Edge 79+, Safari 15+
  • For mobile: Chrome Android or Safari iOS 15+

Start as a new project

Install

To embed OpenHuman into your project, install the SDK package:

npm install @openhuman/sdk

OpenHuman has zero runtime dependencies. The package bundles everything - WebGL context management, shaders, math, animation - in a single file ≤ 200KB gzipped.


Add a Canvas element

In your HTML, create a <canvas> element that OpenHuman will render into:

index.html
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>OpenHuman Demo</title>
        <style>
            body {
                margin: 0;
                background: #000;
            }
            canvas {
                display: block;
                width: 100vw;
                height: 100vh;
            }
        </style>
    </head>
    <body>
        <canvas id="oh-canvas"></canvas>
        <script type="module" src="./main.js"></script>
    </body>
</html>

Initialize the Engine

Create a main.js file and initialize the OpenHuman engine with your canvas:

main.js
import { OpenHuman } from "@openhuman/sdk"
 
const canvas = document.getElementById("oh-canvas")
 
const human = new OpenHuman({
    canvas,
    quality: "high", // 'high' | 'medium' | 'low'
    fps: 60,
})
 
// Load a digital human character bundle (.ohb)
await human.loadCharacter("./characters/default.ohb")
 
// Start the render loop
human.play("idle")

Character assets use the .ohb (OpenHuman Bundle) format - a prepackaged archive containing the glTF mesh, KTX2 textures, skeleton, and morph targets. See the Asset Pipeline guide for how to build your own bundles.


Verify WebGL 2.0 Support

OpenHuman automatically detects WebGL 2.0. To handle unsupported browsers gracefully, listen for the ready event:

main.js
human.on("ready", ({ webglVersion, extensions }) => {
    console.log(`Running on WebGL ${webglVersion}`)
    console.log("Loaded extensions:", extensions)
})
 
human.on("error", (err) => {
    if (err.code === "WEBGL2_NOT_SUPPORTED") {
        // Show fallback UI or downgrade to WebGL 1.0 reduced-quality mode
        console.warn("WebGL 2.0 not available, falling back to reduced quality.")
        human.setQuality("low")
    }
})

Embed as a Web Component

OpenHuman ships a <open-human> custom element for zero-config embedding:

index.html
<script type="module" src="https://cdn.openhuman.io/sdk/latest/embed.js"></script>
 
<open-human src="./characters/default.ohb" animation="idle" quality="high" style="width: 600px; height: 800px;"></open-human>

The embed Web Component supports src, animation, quality, streaming-url, and autoplay attributes. See the Embed API reference for the full list.


Enable Streaming Animation

To stream real-time animation (e.g. lip sync from AI TTS or mocap), connect a WebSocket stream:

main.js
import { OpenHuman, StreamingClient } from "@openhuman/sdk"
 
const human = new OpenHuman({ canvas })
await human.loadCharacter("./characters/default.ohb")
 
// Connect to a streaming animation server
const stream = new StreamingClient({
    url: "wss://your-server.example.com/animation-stream",
    jitterBuffer: 80, // ms - smooths latency spikes
})
 
stream.on("frame", (pose) => {
    human.applyPose(pose)
})
 
stream.connect()

The binary WebSocket protocol sends joint data at 8 floats per joint (position × 3, quaternion × 4, scale × 1), with 16-bit quantization for 50% bandwidth reduction. Target latency is < 50ms end-to-end.


SDK Configuration Reference

new OpenHuman({
    canvas, // HTMLCanvasElement - required
    quality, // 'high' | 'medium' | 'low'   (default: 'high')
    fps, // target frame rate             (default: 60)
    shadows, // enable shadow map             (default: true)
    postProcess, // enable bloom, DoF, ACES tone  (default: true)
    sss, // enable subsurface scattering  (default: true)
})
OptionTypeDefaultDescription
canvasElement-Target <canvas> element (required)
qualitystring'high'Rendering quality preset
fpsnumber60Target frame rate (30 recommended for mobile)
shadowsbooleantruePCF soft shadow map from key light
postProcessbooleantrueBloom, Depth of Field, ACES tonemapping, FXAA
sssbooleantrueScreen-space subsurface scattering for skin

Browser Compatibility

BrowserWebGLStatus
Chrome 60+2.0✅ Full support
Firefox 55+2.0✅ Full support
Edge 79+2.0✅ Full support
Safari 15+2.0✅ Full support
Chrome Android2.0✅ 30fps+ mobile
Safari iOS 15+2.0✅ 30fps+ mobile
Older browsers1.0⚠️ Reduced quality mode

Next Steps