【Three.js】第十三章 3D Text 3D文字

13. 3D Text 3D文字

介绍

我们已经了解足够的基础知识,现在可以创作一些好看的效果了。对于我们第一个正式的项目,我们将复刻一个开发者ilithya的作品(https://www.ilithya.rocks/),这个作品在场景中间有一个大的 3D 文本,很多几何体漂浮在文字的周围。
这个作品是学习 Three.js 早期可以实现的一个很好的例子。它简单、高效,而且特效看起来很棒。
Three.js 已经通过TextGeometry类支持 3D 文本几何图形。问题是你必须先指定一种字体,而且这个字体必须是一种叫做 typeface 的特定 json 格式。
我们不会涉及数字字体版权授权相关的问题,您使用下载字体后,使用字体时必须保证有权使用该字体,或者字体版权是供开发者免费使用的。

如何获得字体

有很多方法可以获取 typeface 格式的字体。首先,您可以使用如下转换器转换您的字体:https://gero3.github.io/facetype.js/。您必须提供一个文件并单击转换按钮。
您还可以在node_modules文件夹中的 Three.js 库示例中找到字体。/node_modules/three/examples/fonts/你可以把这些字体放在/static/文件夹中,或者你可以直接在你的 JavaScript 文件中导入它们,因为它们是 json 并且 Vite 中.json文件就像.js的文件一样被支持:

import typefaceFont from 'three/examples/fonts/helvetiker_regular.typeface.json'

我们打开/node_modules/three/examples/fonts/,获取helvetiker_regular.typeface.json文件和LICENSE文件并将它们放入/static/fonts/文件夹(您需要创建fonts文件夹)来混合使用这两种技术。
现在只需在基本 URL 的末尾写入即可访问该/fonts/helvetiker_regular.typeface.json字体。

加载字体

要加载字体,我们必须使用一个名为FontLoader的新加载器类。
此类在THREE变量中不可用。像在前面课程中我们所做的,像导入OrbitControls那样导入它:

import {
    
     FontLoader } from 'three/examples/jsm/loaders/FontLoader.js'

这个加载器像TextureLoader一样工作。在该部分之后添加以下代码textureLoader(如果您使用的是其他字体,请不要忘记更改路径):

/**
 * Fonts
 */
const fontLoader = new FontLoader()

fontLoader.load(
    '/fonts/helvetiker_regular.typeface.json',
    (font) =>
    {
    
    
        console.log('loaded')
    }
)

进入你的控制台发现打印了'loaded'。如果不是,请检查前面的步骤并在控制台中搜索潜在的错误。
我们现在可以通过使用函数内的font变量来访问字体。与TextureLoader不同,我们必须在该函数中的成功回调编写其余代码。

创建几何体

正如我们之前所说,我们将使用TextGeometry来创建几何体。
就像FontLoader一样,我们需要导入它:

import {
    
     TextGeometry } from 'three/examples/jsm/geometries/TextGeometry.js'

请注意文档页面上的示例代码;这些值比我们场景中的值大得多。
确保在成功的回调函数中编写代码:

fontLoader.load(
    '/fonts/helvetiker_regular.typeface.json',
    (font) =>
    {
    
    
        const textGeometry = new TextGeometry(
            'Hello Three.js',
            {
    
    
                font: font,
                size: 0.5,
                height: 0.2,
                curveSegments: 12,
                bevelEnabled: true,
                bevelThickness: 0.03,
                bevelSize: 0.02,
                bevelOffset: 0,
                bevelSegments: 5
            }
        )
        const textMaterial = new THREE.MeshBasicMaterial()
        const text = new THREE.Mesh(textGeometry, textMaterial)
        scene.add(text)
    }
)


您应该得到一个需要改进的白色 3D 文本。
首先,注释掉立方体的代码。其目的是确保一切正常。

如果您想看到一些很酷的网格,请添加wireframe: true到您的材料中。

const textMaterial = new THREE.MeshBasicMaterial({
    
     wireframe: true })


您现在可以看到几何体是有很多三角形生成的。创建文本几何图形对计算机来说既漫长又困难。curveSegments避免这样做太多次,并通过减少多边形和bevelSegments属性使几何体尽可能保持低。
一旦您对几何体渲染详细程度感到满意,请删除wireframe

文本居中

有几种方法可以使文本居中。一种方法是使用边界。边界是与几何相关联的信息,它告诉该几何占用了哪些空间。它可以是一个盒子或一个球体。

你实际上看不到这些边界,但它可以帮助 Three.js 轻松计算对象是否在屏幕上,如果不在屏幕上,则对象甚至不会被渲染。这称为视锥体剔除,但这不是本课的主题。
我们想要的是使用这个边界来了解几何体的大小并使它重新居中。默认情况下,Three.js 使用球体边界。我们想要的是一个盒子边界,更准确地说。为此,我们可以要求 Three.js 通过调用computeBoundingBox()几何来计算此框边界:

textGeometry.computeBoundingBox()

我们可以使用boundingBox几何属性选中此框。

console.log(textGeometry.boundingBox)

结果是一个名为Box3 的对象,它有一个min属性和一个max属性。该min0并不像我们预期的那样。这是由于bevelThicknessand bevelSize,但我们现在可以忽略它。
现在我们有了措施,我们可以移动对象。我们不移动网格,而是移动整个几何体。这样,网格仍将位于场景的中心,文本几何体也将在我们的网格内居中。
为此,我们可以在方法translate(...)之后立即在几何体上使用该方法computeBoundingBox()

textGeometry.translate(
    - textGeometry.boundingBox.max.x * 0.5,
    - textGeometry.boundingBox.max.y * 0.5,
    - textGeometry.boundingBox.max.z * 0.5
)


文本居中,但如果你想非常精确,你还应该减去 bevelSizeis 0.02

textGeometry.translate(
    - (textGeometry.boundingBox.max.x - 0.02) * 0.5, // Subtract bevel size
    - (textGeometry.boundingBox.max.y - 0.02) * 0.5, // Subtract bevel size
    - (textGeometry.boundingBox.max.z - 0.03) * 0.5  // Subtract bevel thickness
)

我们在这里所做的实际上可以通过调用几何上的方法center()更快地完成:

textGeometry.center()

容易多了,不是吗?我们手写居中做的目的是了解边界和截锥体剔除

添加matcap材质

是时候为我们的文本添加一个很酷的材料了。我们将使用 MeshMatcapMaterial 替换 MeshBasicMaterial,因为它看起来很酷,而且性能更好。
首先,让我们选择一个 matcap 纹理。我们将使用位于/static/textures/matcaps/文件夹中的 matcaps,但您可以随意使用您自己的 matcaps
您也可以从此存储库https://github.com/nidorx/matcaps下载一个。不要花太多时间去选择它!如果不是供个人使用,请确保您有版权使用它。您不需要高分辨率的纹理,256x256应该绰绰有余。
我们现在可以使用代码中已有的TextureLoader来加载纹理:

const matcapTexture = textureLoader.load('/textures/matcaps/1.png')

我们现在可以用漂亮的MeshMatcapMaterial替换丑陋的MeshBasicMaterial并将我们的matcapTexture变量与matcap属性一起使用:

const textMaterial = new THREE.MeshMatcapMaterial({
    
     matcap: matcapTexture })


你应该可以渲染出一个可爱的文字,上面有一个很酷的材料。

添加对象

让我们添加漂浮的对象。为此,我们将在循环函数内创建一个甜甜圈。
在成功函数中,紧跟在该text部分之后,添加循环函数:

for(let i = 0; i < 100; i++)
{
    
    
    
}

我们可以在 success 函数之外完成此操作,但我们需要将文本和对象一起创建,这是有充分理由的,您稍后会看到。
在此循环中,创建一个TorusGeometry(例如甜甜圈的技术名称),其材质与文本和Mesh相同:

for(let i = 0; i < 100; i++)
{
    
    
    const donutGeometry = new THREE.TorusGeometry(0.3, 0.2, 20, 45)
    const donutMaterial = new THREE.MeshMatcapMaterial({
    
     matcap: matcapTexture })
    const donut = new THREE.Mesh(donutGeometry, donutMaterial)
    scene.add(donut)
}


你应该在同一个地方得到 100 个甜甜圈。
让我们为他们的位置添加一些随机性:

donut.position.x = (Math.random() - 0.5) * 10
donut.position.y = (Math.random() - 0.5) * 10
donut.position.z = (Math.random() - 0.5) * 10


你应该把 100 个甜甜圈分散在现场。
为旋转添加随机性。无需旋转所有 3 个轴,并且由于甜甜圈是对称的,旋转半圈就足够了:

donut.rotation.x = Math.random() * Math.PI
donut.rotation.y = Math.random() * Math.PI


甜甜圈应该向各个方向旋转。
最后,我们可以为比例添加随机性。不过要小心;我们需要对所有 3 个轴( x, y, z)使用相同的值:

const scale = Math.random()
donut.scale.set(scale, scale, scale)

优化

我们的代码不是最优的。正如我们在上一课中看到的,我们可以在多个网格上使用相同的材质,但我们也可以使用相同的几何体来节省性能。
thedonutGeometrythedonutMaterial移出循环:

const donutGeometry = new THREE.TorusGeometry(0.3, 0.2, 20, 45)
const donutMaterial = new THREE.MeshMatcapMaterial({
    
     matcap: matcapTexture })

for(let i = 0; i < 100; i++)
{
    
    
    // ...
}

你应该得到相同的结果,但我们可以走得更远。text的材料与donut 的相同。
让我们删除donutMaterial,重命名textMaterialbymaterial并将其用于 thetextdonut

const material = new THREE.MeshMatcapMaterial({
    
     matcap: matcapTexture })
                
// ...

const text = new THREE.Mesh(textGeometry, material)

// ...

for(let i = 0; i < 100; i++)
{
    
    
    const donut = new THREE.Mesh(donutGeometry, material)
    
    // ...
}

我们可以继续优化,但是有一个关于优化的专门课程,所以先按下不表。

更多优化

如果需要,您可以添加更多形状,为它们设置动画,甚至可以尝试其他 matcaps

猜你喜欢

转载自blog.csdn.net/m0_68324632/article/details/131151984