Why Switch from Three.js to Galacean? A Hands‑On Upgrade Guide for Web 3D
This article compares Three.js and Galacean Web 3D engines, explains performance bottlenecks of Three.js, showcases Galacean's core advantages, and provides a step‑by‑step migration guide with code examples for initializing, loading models, replacing assets, and handling animations.
Background
Web 3D technology is rapidly evolving, delivering immersive experiences across virtual showcases, games, architectural visualization, and educational simulations. Three.js has been a popular JavaScript 3D library thanks to its simple API and rich features, but as project complexity grows, performance bottlenecks such as frame drops and UI jank become noticeable.
Galacean: Next‑Generation Web 3D Engine
2.1 Business Overview
Galacean is an open‑source Web game engine designed for openness, ease of use, and high efficiency. It powers the "拟我形象" 3D digital avatar feature in the Vivo account, which originally used Three.js for rendering.
2.2 Technical Challenges & Pain Points
Performance bottlenecks: Complex facial morph targets cause long model‑parsing times.
Thread blocking: JavaScript’s single‑threaded nature leads to temporary UI unresponsiveness during model loading.
Multi‑model rendering: Simultaneous rendering of multiple outfits strains performance.
Shadow optimization: Three.js shadows are costly, requiring compromises between quality and speed.
2.3 Core Advantages of Galacean
Galacean adopts an Entity‑Component architecture, offers multi‑thread processing via Workers, optimizes mobile performance with constant approximation, and introduces a novel data‑transfer pipeline and caching system that dramatically reduces stutter under heavy loads.
Compared to Three.js, Galacean’s EC design greatly improves development flexibility, and its rendering engine now supports Chrome 82 and above with higher frame rates and visual fidelity.
Upgrade Guide: Practical Steps
3.1 Initialization
Unlike Three.js, Galacean’s engine creation is asynchronous; you must await the engine instance and call engine.run() once to start rendering.
const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(15, window.innerWidth / window.innerHeight, 0.1, 100);
requestAnimationFrame(function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
}); const engine = await WebGLEngine.create({
canvas,
physics: new LitePhysics()
});
engine.run();Angle units differ: Three.js uses radians for most rotations, while Galacean uses degrees directly.
// Three.js
camera.fov = 15;
item.rotation.y = 15 * Math.PI / 180;
// Galacean
camera.fieldOfView = 15;
item.rotation.y = 15;Color handling also varies; Three.js accepts hex or RGB, whereas Galacean expects normalized RGB (0‑1) values.
// Three.js
directLight.color = 0xffffff;
directLight.intensity = 0.9;
// Galacean
const color = new Color(0.9, 0.9, 0.9, 1);
color.toLinear(color);
directLight.color = color;3.2 Model Loading
Large models with many morph targets can be packaged as zip files. Neither engine loads zip directly, so you must download, unzip, create an ObjectURL, and feed it to the respective loader.
export class ModelLoader {
engine: WebGLEngine;
constructor(engine: WebGLEngine) {
this.engine = engine;
}
async load(src: string) {
const url = await fileLoader(src);
return this.engine.resourceManager.load<GLTFResource>({
url,
type: AssetType.GLTF
});
}
}Three.js returns a simple scene and animation clips, while Galacean provides a richer data structure that includes meshes, materials, textures, skinning, and animation information, simplifying asset replacement.
3.3 Asset Replacement
Asset replacement covers color, texture, morph‑target, and model swaps. Texture updates differ: Three.js assigns a canvas or image directly to material.map and sets needsUpdate, whereas Galacean requires loading a Texture2D resource first.
// Three.js
material.map = canvas;
material.needsUpdate = true;
// Galacean
const texture: Texture2D = await engine.resourceManager.load({
url,
type: AssetType.Texture2D
});
material.baseTexture = texture;Morph‑target updates also differ. Three.js uses morphTargetDictionary and morphTargetInfluences, while Galacean stores blend‑shape data under mesh.blendShapes and modifies blendShapeWeights.
// Three.js
const index = morphTargetDictionary[keyName];
if (index !== undefined) {
mesh.morphTargetInfluences[index] = value;
}
// Galacean
const blendShapes = skinMeshRenderer.mesh.blendShapes;
const index = blendShapes.findIndex(i => i.name === keyName);
if (index > -1) {
skinMeshRenderer.blendShapeWeights[index] = value;
}3.4 Animation
Galacean offers a component‑based animation system with state machines, blending, and duration compression, making animation switching simpler than Three.js’s AnimationMixer approach.
// Three.js
const mixer = new THREE.AnimationMixer(scene);
const action = mixer.clipAction(avatarClip);
action.play();
ticker.addEvent(delta => {
mixer.update(delta);
});
// Galacean
const animationState = animator.findAnimatorState('action');
const idleState = animator.findAnimatorState('idle');
const transition = new AnimatorStateTransition();
transition.duration = 1;
transition.offset = 0;
transition.exitTime = 1;
transition.destinationState = idleState;
animationState.addTransition(transition);
animator.play('action');Conclusion
Galacean revitalizes Web 3D development by addressing performance and feature gaps of legacy engines, offering high efficiency, rich functionality, and an easy‑to‑use workflow for both new and existing projects. Developers should be aware of API differences across Galacean versions and consult the evolving documentation and examples.
vivo Internet Technology
Sharing practical vivo Internet technology insights and salon events, plus the latest industry news and hot conferences.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
