Rendering Features
Advanced rendering features for VRMAvatar — expression presets, animations, environment maps, post-processing, and more.
Expression Presets
Override VRM expressions directly using expressionOverrides. Values are clamped to 0–1. These take effect when no live blendshape data (A2F) is active.
<VRMAvatarblendshapes={blendshapes}expressionOverrides={{ happy: 0.8, blink: 0.2 }}/>
Available VRM expressions depend on the model, but common ones include: aa, happy, blink, blinkLeft, blinkRight, ou.
Idle Animations
VRMAvatar includes built-in idle behavior by default:
- Breathing — subtle spine and chest movement
- Head bob — gentle neck/head sway
- Micro-expressions — random blinks, small smiles, brow raises, eye drift
- Spring bone physics — hair and clothing react to bone movement automatically (if the VRM includes spring bones)
These are suppressed when live A2F data or expressionOverrides are active.
Animation Clips (.vrma)
Load a VRM Animation (.vrma) file as a looping idle animation. When set, this replaces the built-in bone-based idle with the clip animation.
<VRMAvatarblendshapes={blendshapes}idleAnimationUrl="https://cdn.example.com/idle.vrma"/>
The animation is loaded via @pixiv/three-vrm-animation and plays on loop. Set idleAnimationUrl to undefined to stop the clip and return to built-in idle.
Background Options
Three background modes are available:
Solid Color
// Default white background<VRMAvatar blendshapes={blendshapes} backgroundColor={0xffffff} />// Dark background<VRMAvatar blendshapes={blendshapes} backgroundColor={0x1a1a2e} />// Transparent (for compositing over your own UI)<VRMAvatar blendshapes={blendshapes} backgroundColor={null} />
HDRI Environment Map
Load an environment map as both the scene background and environment lighting. This replaces the solid color background. Three formats are supported:
- .ktx2 (FastHDR) — Recommended. 65-75% smaller files, 10x faster loading, 95% less GPU memory vs .hdr/.exr. Pre-baked PMREM skips server-side processing.
- .hdr — Standard Radiance HDR format. Processed via PMREMGenerator on load.
- .exr — OpenEXR format. Processed via PMREMGenerator on load.
<VRMAvatarblendshapes={blendshapes}environmentUrl="https://example.com/environment_4k.ktx2"environmentIntensity={1.2}environmentBlur={0.1}environmentZoom={1.5}/>
Adjust environmentIntensity, environmentBlur, and environmentZoom without reloading the texture.
Converting to KTX2 (FastHDR)
Convert your own HDRIs to KTX2 using the Needle FastHDR cloud tool or the basisu CLI with UASTC HDR encoding. KTX2 files load directly to GPU memory without CPU-side decode.
HDRI Lighting & PBR
HDRI environment maps light PBR avatars automatically — skin shows warm/cool tinting from the scene, hair picks up soft specular, and clothing reflects the environment. MToon (toon shader) materials ignore environment maps. For full HDRI interaction, use models with PBR materials (MeshStandardMaterial).
When an HDRI is active, ACES filmic tone mapping is enabled by default to prevent blown-out highlights. Fixed scene lights (ambient, directional, back) are automatically dimmed to 30% so the HDRI becomes the dominant light source. Both behaviors revert when the HDRI is removed.
<VRMAvatarblendshapes={blendshapes}environmentUrl="https://example.com/studio.ktx2"environmentIntensity={1.2}toneMappingExposure={1.0} // Adjust HDRI brightnesstoneMapping={true} // ACES filmic (default when HDRI active)/>
Tune toneMappingExposure to control overall brightness — lower values darken the scene, higher values brighten it. Switching between HDRI presets visibly changes avatar lighting and reflections.
Finding HDR Assets
Poly Haven offers hundreds of free, CC0-licensed HDRI environments. To use one:
- Browse polyhaven.com/hdris and select an environment
- Choose resolution — 4K minimum, 8K recommended for sharp backgrounds
- Download in HDR format, then convert to KTX2 via Needle FastHDR for best performance
- Pass the URL as
environmentUrl
Post-Processing Effects
Enable GPU post-processing effects via the postProcessing prop. Effects auto-disable if FPS drops below 30.
<VRMAvatarblendshapes={blendshapes}postProcessing={{bloom: 0.3, // Glow intensity (0–1+)ao: 0.5, // Ambient occlusion strength (0–1)dof: true, // Depth of field (bokeh)}}/>
| Effect | Type | Description |
|---|---|---|
bloom | number | Unreal Bloom glow intensity. 0 = off |
ao | number | Screen-space ambient occlusion strength. 0 = off |
dof | boolean | Bokeh depth of field focused at face distance |
Camera Control
Customize the camera position, target, and field of view. Users can also orbit with mouse drag and zoom with scroll wheel.
<VRMAvatarblendshapes={blendshapes}cameraPosition={[0, 1.4, 1.2]} // [x, y, z]cameraTarget={[0, 1.3, 0]} // look-at pointcameraFov={30} // field of view (degrees)lightIntensity={1.2} // scale all lights/>
Keyboard controls: arrow keys for orbit and height adjustment.
Full Props Reference
| Prop | Type | Default | Description |
|---|---|---|---|
blendshapes | number[] | required | 52 ARKit blendshape values from A2F |
width | number | 400 | Canvas width in pixels |
height | number | 400 | Canvas height in pixels |
modelUrl | string | Supabase default | URL of the VRM model file |
backgroundColor | number | null | 0xffffff | Solid background color, or null for transparent |
blendshapeMap | Record<string, string> | — | ARKit → model blendshape name mapping |
expressionOverrides | Record<string, number> | — | Manual VRM expression values (0–1) |
onModelLoad | (report) => void | — | Callback with compatibility report after load |
maxModelSize | number | 30MB | Max model file size in bytes (0 to disable) |
cameraPosition | [x, y, z] | [0, 1.4, 1.2] | Camera position in world space |
cameraTarget | [x, y, z] | [0, 1.3, 0] | Camera look-at target |
cameraFov | number | 30 | Camera field of view (degrees) |
lightIntensity | number | 1 | Multiplier for all scene lights |
idleAnimationUrl | string | — | URL of a .vrma animation clip for idle loop |
postProcessing | PostProcessingConfig | — | Post-processing effects config |
environmentUrl | string | — | URL of an environment map (.ktx2, .hdr, or .exr) |
environmentIntensity | number | 1 | HDRI lighting intensity |
environmentBlur | number | 0 | HDRI background blur amount |
environmentZoom | number | 1 | HDRI background zoom level |
toneMapping | boolean | true | Enable ACES filmic tone mapping when HDRI is active |
toneMappingExposure | number | 1 | Tone mapping exposure level for HDRI brightness |
onEnvironmentLoad | () => void | — | Callback when HDRI environment finishes loading |
animationSpeed | number | 1 | Playback speed multiplier for idle animation clip |
animationWeight | number | 1 | Blend weight for idle animation clip (0–1) |
animationCrossfade | number | 0.5 | Crossfade duration in seconds when switching animations |
orbitAngle | number | — | Camera azimuth angle (radians) for orbit control |
orbitElevation | number | — | Camera elevation angle (radians) for orbit control |
avatarRotation | number | — | Avatar Y-axis rotation (radians) |
onOrbitChange | (angle, elevation) => void | — | Callback when camera orbit changes via user interaction |
features | VRMAvatarFeatures | — | Feature toggle object (see Feature Toggles section) |
Animation Controls
Fine-tune idle animation clip playback with speed, weight, and crossfade props.
<VRMAvatarblendshapes={blendshapes}idleAnimationUrl="https://cdn.example.com/idle.vrma"animationSpeed={0.8} // Slow down to 80%animationWeight={0.7} // Blend at 70% intensityanimationCrossfade={0.3} // 300ms crossfade between clips/>
Camera Orbit Controls
Control camera orbit programmatically with angle and elevation props. Users can also orbit with mouse drag and zoom with scroll wheel.
const [angle, setAngle] = useState(0);const [elevation, setElevation] = useState(0.2);<VRMAvatarblendshapes={blendshapes}orbitAngle={angle}orbitElevation={elevation}avatarRotation={Math.PI / 6} // Rotate avatar 30°onOrbitChange={(a, e) => {setAngle(a);setElevation(e);}}/>
Feature Toggles
Control which built-in behaviors are active via the features prop. All features are enabled by default.
<VRMAvatarblendshapes={blendshapes}features={{idleAnimation: true, // Breathing/swaying bone animationmicroExpressions: true, // Random blinks, smiles, brow raisesspringBones: true, // Hair/clothing physics simulationexpressionPresets: true, // VRM expression preset support}}/>
| Feature | Type | Default | Description |
|---|---|---|---|
idleAnimation | boolean | true | Subtle breathing and swaying bone animation |
microExpressions | boolean | true | Random blinks, small smiles, brow raises, eye drift |
springBones | boolean | true | Hair and clothing physics simulation |
expressionPresets | boolean | true | VRM expression preset support (happy, blink, etc.) |
Combined Example
import { useAStackCSR, VRMAvatar } from '@aether-stack-dev/client-sdk/react';function StylizedAvatar() {const { blendshapes, connect, startCall } = useAStackCSR({workerUrl: 'wss://your-worker-url',sessionToken: token,});return (<VRMAvatarblendshapes={blendshapes}modelUrl="https://cdn.example.com/character.vrm"width={600}height={600}environmentUrl="https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/4k/studio_small_09_4k.hdr"environmentIntensity={1.0}environmentBlur={0.1}environmentZoom={1.5}idleAnimationUrl="https://cdn.example.com/idle.vrma"cameraPosition={[0, 1.5, 1.0]}cameraFov={25}/>);}