Three.js - 创建文本
Three.js - 创建文本
Section titled “Three.js - 创建文本”在 3D 场景中显示文本是一个常见需求,无论是用于用户界面 (UI)、注释还是艺术效果。在 Three.js 中实现这一点有几种方法,每种方法都有其优缺点。我们将探讨三种主要方法。
方法一:HTML 和 CSS(UI 推荐方式)
Section titled “方法一:HTML 和 CSS(UI 推荐方式)”创建标签和叠加层等 UI 元素最灵活、质量最高的方法是利用浏览器最擅长的功能:渲染 HTML 和 CSS。Three.js 提供了 CSS2DRenderer 和 CSS3DRenderer 来帮助您在 3D 场景中定位常规 HTML 元素。
- 优点: 任何分辨率下文本都清晰锐利,可充分利用 CSS 进行样式设置和动画,有利于可访问性,支持可点击的链接和按钮。
- 缺点: 元素渲染在 3D 场景之上,而非其中。它们不会被 3D 对象遮挡,也无法受场景光照影响。
使用 CSS2DRenderer 实现
Section titled “使用 CSS2DRenderer 实现”import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
// 1. 设置渲染器const labelRenderer = new CSS2DRenderer();labelRenderer.setSize(window.innerWidth, window.innerHeight);labelRenderer.domElement.style.position = 'absolute';labelRenderer.domElement.style.top = '0px';document.body.appendChild(labelRenderer.domElement);
// 2. 创建 HTML 元素const p = document.createElement('p');p.textContent = 'Hello, World!';p.style.color = 'white';p.style.fontFamily = 'sans-serif';p.style.fontSize = '2em';
// 3. 创建 CSS2DObjectconst label = new CSS2DObject(p);
// 4. 定位并添加到 3D 对象或场景// 例如,将其定位在一个立方体的上方label.position.set(0, 0.75, 0); // 位置是相对于父对象的cube.add(label);
// 5. 在动画循环中渲染function animate() { // ... renderer.render(scene, camera); // WebGL 渲染器 labelRenderer.render(scene, camera); // CSS2D 渲染器}方法二:3D 文本几何体
Section titled “方法二:3D 文本几何体”对于需要作为真实 3D 对象存在于场景中的文本——能够投射阴影、受光照影响并被其他对象遮挡——您可以使用 TextGeometry。
- 优点: 是一个真实的 3D 网格,能与光照和其他对象交互,可以具有深度和倒角。
- 缺点: 需要加载特殊的字体文件(
.typeface.json),由于高多边形数量可能对性能造成负担,近距离观察时文本质量可能会下降。
使用 TextGeometry 实现
Section titled “使用 TextGeometry 实现”这个过程包括加载字体,然后使用该字体生成几何体。
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js';import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry.js';
const fontLoader = new FontLoader();
fontLoader.load( '/fonts/helvetiker_regular.typeface.json', // typeface.json 字体文件的路径 (font) => { const textGeometry = new TextGeometry( 'Three.js', { font: font, size: 0.5, height: 0.2, // 深度 curveSegments: 12, bevelEnabled: true, bevelThickness: 0.03, bevelSize: 0.02, bevelOffset: 0, bevelSegments: 5 } );
// 将几何体居中以便于定位 textGeometry.center();
const textMaterial = new THREE.MeshStandardMaterial({ color: 0xffffff }); const textMesh = new THREE.Mesh(textGeometry, textMaterial); scene.add(textMesh); });注意: 您可以在 Three.js 示例存储库中找到 typeface.json 字体,或者使用在线工具转换您自己的 TTF/OTF 字体。
方法三:在 Canvas 纹理上绘制文本
Section titled “方法三:在 Canvas 纹理上绘制文本”这是一种混合方法。您将文本绘制到 2D HTML5 Canvas 上,然后将该 canvas 作为 3D 平面 (PlaneGeometry) 上的纹理使用。这是一种高性能的文本显示方式,让文本看起来像是置身于 3D 世界中。
- 优点: 性能极佳,可应用于任何几何体,来自 2D canvas API 的高质量文本渲染。
- 缺点: 文本是平面的(作为纹理的一部分),如果文本需要动态更改,则需要仔细管理纹理更新。
// 1. 在内存中创建一个 canvas 元素const canvas = document.createElement('canvas');const context = canvas.getContext('2d');canvas.width = 512;canvas.height = 128;
// 2. 在 canvas 上绘制文本context.fillStyle = '#444444'; // 背景context.fillRect(0, 0, canvas.width, canvas.height);context.font = 'Bold 48px sans-serif';context.fillStyle = 'white';context.textAlign = 'center';context.textBaseline = 'middle';context.fillText('Canvas Texture', canvas.width / 2, canvas.height / 2);
// 3. 从 canvas 创建纹理const texture = new THREE.CanvasTexture(canvas);
// 4. 将纹理应用于材质const material = new THREE.MeshBasicMaterial({ map: texture });const geometry = new THREE.PlaneGeometry(4, 1); // 宽高比与 canvas 匹配const planeMesh = new THREE.Mesh(geometry, material);scene.add(planeMesh);如果您需要更新文本,只需在 canvas 上重新绘制,然后设置 texture.needsUpdate = true; 来通知 Three.js 重新将纹理上传到 GPU。
如何选择合适的方法?
Section titled “如何选择合适的方法?”- 对于 UI、HUD 和注释,使用 HTML/CSS (
CSS2DRenderer)。 - 对于必须作为场景一部分的 3D 标志或文本,使用
TextGeometry。 - 对于世界中标志或表面上的高性能文本,使用 Canvas 纹理。