banner
banner
banner
NEWS LETTER

threeJS-实现中文字体的3D效果

Scroll down

官方文档的3d字体无法显示中文字体

引入库

1
2
3
4
import * as THREE from "three" /*导入three库*/
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js" /*导入轨道控制器*/
import { FontLoader } from "three/examples/jsm/loaders/FontLoader.js" /*导入字体加载器*/
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry.js" /*导入文本缓冲几何体*/

创建场景

  • const scene = new THREE.Scene()

初始化相机

  • const camera = new THREE.PerspectiveCamera(45,window.innerWidth / window.innerHeight, 0.1, 1000)

设置相机的位置

  • camera .position.set(0, 0, 800)

初始化渲染器

1
2
3
const render = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

添加环境纹理

1
2
3
4
5
const texture = new THREE.TextureLoader().load("")
texture.mapping = THREE.EquirectangularReflectionMapping
scene.background = texture
scene.backgroundBlurriness = 0.5 /*设置场景的模糊度*/
scene.environment = texture

添加控制器

1
2
const controls = new OrbitControls(camera, render.domElement)
controls.enableDamping = true

渲染函数

1
2
3
4
5
6
const render = () => {
requestAnimationFrame(render)
controls.update()
renderer.render(scene,camera)
}
render()

加载字体

1
2
3
4
5
6
7
8
9
10
11
12
13
const loader = new FontLoader()
loader.load("字体文件", (font) => {
const geometry = new TextGepmetry('展示的字体', {
font: font,
size: 80, /*字体大小*/
height:5, /*字体厚度*/
curveSegments: 12,/*曲线分段数*/
bevelEnabled: true,/*是否启用斜角*/
bevelThickness: 10,/*斜角厚度*/
bevelSize: 3,/*斜角大小*/
bevelSegments: 5/*斜角分段数*/
})
})

设置字体的材质

1
2
3
4
5
6
7
8
9
const material = new THREE.MeshPhysicalMaterial({
color: 0xeeeeff,
roughness: 0, /*粗糙度*/
reflectivity: 1, /*反射*/
thickness: 80,/*玻璃的厚度*/
ior: 1.2, /*折射率*/
transmission: 1, /*设置透明*/
side: THREE.DoubleSide/*两面可看*/
})

创建字体

1
2
const mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)

文字特效

  • 按照上述创景场景相机,控制器,渲染函数
  • 导入字体模型展示在场景

加载模型并生成随机顶点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
let material;
let dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath("./draco/") /*这个路径是从库里面赋值出来放在当前目录的*/
const loader = new GLTFLoader()
loader.setDRACOLoader(dracoLoader)
loader.load("字体模型路径", (gltf) => {
let text = gltf.scene.children[0]
scene.add(text)

/* 随机生成顶点数据*/
let geometry = text.geometry
const position = geometry.attributes.position /*获取顶点位置*/
const vertexCount = position.count /*获取所有的向量数*/
const triangleCount = vertexCount / 3 /*获取顶点数*/
cosnt randomDirections = [] // 随机方向的数组
const randomStrengths = [] // 生成随机强度的数组

// 生成随机顶点
for (let i = 0; i< triangleCount; i++){
const dir = new THREE.Vector3(
Math.random()*2 -1,
Math.random()*2 -1,
Math.random()*2 -1,
).normalize().toArray()
randomDirections.push(dir[0],dir[1],dir[2])
const str = Math.random()
randomStrengths.push(str,str,str)
}
// 随机属性
const randomDirectionsAttribute = new THREE.Float32BufferAttribute(
new Float32Array(randomDirections),3)
geometry.setAttribute("randomDirection", randomDirectionsAttribute)

// 随机强度
const randomStrengthsAttribute = new THREE.Float32BufferAttribute(
new Float32Array(randomStrengths),1)
geometry.setAttribute("randomStrength", randomStrengthsAttribute)

// 定义着色器材质
material = new THREE.ShaderMaterial({
uniforms:{time: { value: 0}},
vertexShader: `
attributr vec3 randomDirection
attributr float randomStrength
uniform float time;
varying vec3 vPosition

void main() {
vPosition = position
vec3 pos = position.xyz
pos += randomDirection * randomStrength * sin(time)
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos.xyz, 1.0)
}
`,
fragmentShader: `
varying vec3 vPosition
void main() {
vec3 color = normalize(vPosition)*0.5 +0.5
color.z = color.z * 0.3
gl_FragColor = vec4(mixedColor * color * dProd, 1.0)
}
`,
side: THREE.DoubleSide,
transparent: true
})
})

添加控制器

1
2
3
4
5
6
const controls = new OrbitControls(camera, render.domElement)
controls.enableDamping = true
let showText = false
window.addEventListener("click", () => {
showText = !showText
})

渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let clock = new THREE.Clock()
let value = 0
const render = () => {
let delta = clock.getDelta()
if (material) {
if(showText){
value -= delta
value = Math.max(value, 0)
material.uniforms.time.value -= delta
} else {
value += delta
value = Math.max(value, 1)
material.uniforms.time.value += delta
}
}
requestAnimationFrame(render)
controls.update()
renderer.render(scene,camera)
}
render()
其他文章
cover
threeJS-网格的基础材料
  • 24/11/01
  • 11:01
  • ThreeJS
目录导航 置顶
  1. 1. 引入库
  2. 2. 创建场景
  3. 3. 初始化相机
  4. 4. 设置相机的位置
  5. 5. 初始化渲染器
  6. 6. 添加环境纹理
  7. 7. 添加控制器
  8. 8. 渲染函数
  9. 9. 加载字体
  10. 10. 设置字体的材质
  11. 11. 创建字体
  12. 12. 文字特效
  13. 13. 加载模型并生成随机顶点
  14. 14. 添加控制器
  15. 15. 渲染
请输入关键词进行搜索