混合 PixiJS 和 Three.js
🌐 Mixing PixiJS and Three.js
在许多项目中,开发者旨在利用3D和2D图形的优势。将Three.js的先进3D渲染能力与PixiJS在2D方面的速度和多功能性结合起来,可以带来强大且无缝的体验。结合使用这些技术,可以为动态且视觉吸引力的应用创造机会。让我们看看如何实现这一点。
🌐 In many projects, developers aim to harness the strengths of both 3D and 2D graphics. Combining the advanced 3D rendering capabilities of Three.js with the speed and versatility of PixiJS for 2D can result in a powerful, seamless experience. Together, these technologies create opportunities for dynamic and visually compelling applications. Lets see how to do this.
本指南假设 PixiJS 将用作顶层,以在 Three.js 渲染的 3D 场景上渲染用户界面。然而,开发者可以按照任意顺序渲染,也可以根据需要多次渲染。这种灵活性允许创造性和动态的应用。
你将学到什么
🌐 What You’ll Learn
- 设置 PixiJS 和 Three.js 以共享单个 WebGL 上下文。
- 使用
resetState管理渲染器状态。 - 使用多个渲染器时避免常见的陷阱。
设置
🌐 Setting Up
第1步:初始化Three.js渲染器和场景
🌐 Step 1: Initialize Three.js Renderer and Scene
Three.js 将处理 3D 渲染、dom 元素和上下文的创建。
🌐 Three.js will handle the 3D rendering the creation of the dom element and context.
const WIDTH = window.innerWidth;
const HEIGHT = window.innerHeight;
const threeRenderer = new THREE.WebGLRenderer({
antialias: true,
stencil: true, // so masks work in pixijs
});
threeRenderer.setSize(WIDTH, HEIGHT);
threeRenderer.setClearColor(0xdddddd, 1);
document.body.appendChild(threeRenderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT);
camera.position.z = 50;
scene.add(camera);
const boxGeometry = new THREE.BoxGeometry(10, 10, 10);
const basicMaterial = new THREE.MeshBasicMaterial({ color: 0x0095dd });
const cube = new THREE.Mesh(boxGeometry, basicMaterial);
cube.rotation.set(0.4, 0.2, 0);
scene.add(cube);
我们使用了由 three.js 渲染器创建的 DOM 元素和上下文来传递给 pixijs 渲染器。这是确保两个渲染器使用相同 WebGL 上下文的最简单方法。如果你愿意,你也可以反过来做。
步骤 2:初始化 PixiJS 渲染器和舞台
🌐 Step 2: Initialize PixiJS Renderer and Stage
PixiJS 将处理 2D 叠加层。
🌐 PixiJS will handle the 2D overlay.
const pixiRenderer = new PIXI.WebGLRenderer();
await pixiRenderer.init({
context: threeRenderer.getContext(),
width: WIDTH,
height: HEIGHT,
clearBeforeRender: false, // Prevent PixiJS from clearing the Three.js render
});
const stage = new PIXI.Container();
const amazingUI = new PIXI.Graphics().roundRect(20, 80, 100, 100, 5).roundRect(220, 80, 100, 100, 5).fill(0xffff00);
stage.addChild(amazingUI);
渲染循环
🌐 Rendering Loop
为确保渲染器之间的平滑过渡,请在每次渲染之前重置其状态:
🌐 To ensure smooth transitions between the renderers, reset their states before each render:
function render() {
// Render the Three.js scene
threeRenderer.resetState();
threeRenderer.render(scene, camera);
// Render the PixiJS stage
pixiRenderer.resetState();
pixiRenderer.render({ container: stage });
requestAnimationFrame(render);
}
requestAnimationFrame(render);
示例:结合3D和2D元素
🌐 Example: Combining 3D and 2D Elements
这是集成 PixiJS 和 Three.js 的完整示例:
🌐 Here’s the complete example integrating PixiJS and Three.js:
陷阱
🌐 Gotchas
- 启用模板缓冲
- 在创建 Three.js 渲染器时,确保将
stencil设置为true。这可以使 PixiJS 遮罩正常工作。
- 在创建 Three.js 渲染器时,确保将
- 保持尺寸同步:
- 确保两个渲染器使用相同的
width和height来避免视觉不匹配——所以在调整一个大小时要小心,你需要同时调整另一个!
- 确保两个渲染器使用相同的
- 传递 WebGL 上下文:
- 在初始化期间使用
pixiRenderer.init({ context: threeRenderer.getContext() });将 Three.js 的 WebGL 上下文传递给 PixiJS。
- 在初始化期间使用
- 禁用渲染前清除:
- 在初始化 PixiJS 渲染器时设置
clearBeforeRender: false。这可以防止 PixiJS 清除之前渲染的 Three.js 内容。 - 或者你可以在
pixiRenderer.render()调用中设置clear: false。例如pixiRenderer.render({ container: stage, clear: false });。
- 在初始化 PixiJS 渲染器时设置
- 管理渲染顺序:
- 在这个例子中,Three.js 先被渲染,然后是用于 UI 层的 PixiJS。但是,这个顺序是灵活的。你可以按 pixi -> three -> pixi 的顺序渲染,只要在切换渲染器时确保重置状态即可。
- 独立资源:
- 请记住,像纹理这样的资源在 PixiJS 和 Three.js 之间是不能共享的。PixiJS 的纹理不能直接作为 Three.js 的纹理使用,反之亦然。
结论
🌐 Conclusion
混合使用 PixiJS 和 Three.js 可以是创建动态且视觉吸引力应用的强大方法。通过仔细管理渲染循环和状态,你可以实现 3D 和 2D 图层之间的无缝过渡。这种方法允许你利用两种技术的优势,创建既视觉惊艳又高性能的应用。
🌐 Mixing PixiJS and Three.js can be a powerful way to create dynamic and visually appealing applications. By carefully managing the rendering loop and states, you can achieve seamless transitions between 3D and 2D layers. This approach allows you to leverage the strengths of both technologies, creating applications that are both visually stunning and performant.
这种技术也可以用于其他渲染器——只要它们有自己的状态重置方法(主要的渲染器都有),你就可以混合使用它们。像 Babylon.js 和 PlayCanvas 这样的流行 3D 引擎都通过各自的 API 支持状态管理,使它们与这种混合方法兼容。这使你可以灵活选择最适合你需求的 3D 引擎,同时仍能利用 PixiJS 强大的 2D 功能。
🌐 This technique can be used with other renderers too - as long as they have their own way of resetting their state (which the main ones do) you can mix them. Popular 3D engines like Babylon.js and PlayCanvas both support state management through their respective APIs, making them compatible with this mixing approach. This gives you the flexibility to choose the 3D engine that best suits your needs while still leveraging PixiJS's powerful 2D capabilities.