点进来就看炫酷的3D字体!
1.准备工作:字体模型json
可以通过facetype.js
将字体包转成typeface.json
facetype.js
github链接:https://github.com/gero3/facetype.js
facetype.js
官网链接:http://gero3.github.io/facetype.js/
2.加载字体
if (!this.loader) {
this.loader = new THREE.FontLoader();
}
this.loader.load('DIN_Bold.json', (font) => {
//...
});
3.创建字体并获取字体点面
//创建字体图形
let geometry = new THREE.TextGeometry(that.text, {
font: font,
size: that.fontSize, //字体大小
height: that.thickness, //字体厚度
curveSegments: 3,
bevelThickness: 2,
bevelSize: 1,
bevelEnabled: true
});
//图形居中
geometry.center();
//转为缓存图形,方便获取点面等数据
geometry = new THREE.BufferGeometry().fromGeometry(geometry);
//三角形面数
const numFaces = geometry.attributes.position.count / 3;
4.字体形状赋值颜色
//需要赋值的点颜色数组
const colors = new Float32Array(numFaces * 3 * 3);
const color = new THREE.Color();
for (let f = 0; f < numFaces; f++) {
const index = 9 * f;
//随机颜色
color.setRGB(
Math.random() * 0.5 + 0.5,
Math.random() * 0.5 + 0.5,
Math.random() * 0.5 + 0.5
);
for (let i = 0; i < 3; i++) {
//给3个点赋值同样的颜色,形成一个颜色的三角形
colors[index + 3 * i] = color.r;
colors[index + 3 * i + 1] = color.g;
colors[index + 3 * i + 2] = color.b;
}
}
//设置顶点着色器值
geometry.setAttribute('aColor', new THREE.BufferAttribute(colors, 3));
5.着色器材质
5.1 顶点着色器
attribute vec3 aColor;
varying vec3 vColor;
void main() {
vColor = aColor;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
5.2 片元着色器
varying vec3 vColor;
void main() {
gl_FragColor =vec4(vColor, 1.0 );
}
5.3 着色材质
//着色器材质
const shaderMaterial = new THREE.ShaderMaterial({
uniforms: {
amplitude: {
value: 0.0 }
},
vertexShader: document.getElementById('vertexshader').textContent,
fragmentShader: document.getElementById('fragmentshader').textContent
});
6.使用
var myFont = new MyFont();
myFont.initThree(document.getElementById('font'));
myFont.createChart({
text: '666',//文本
fontSize: 20,//字体大小
thickness: 5,//厚度
distance: 30,//偏移距离
minDistance: 5,//最小偏移距离
});
7.字体每个面的偏移
顶点着色器:normal
是three顶点着色器默认值
attribute vec3 aColor;
varying vec3 vColor;
void main() {
vColor = aColor;
vec3 newPosition =position+normal*2.0;//每个面偏移
gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
}
8.让每个面三角形随机偏移
attribute vec3 aColor;
attribute vec3 displacement; //偏移值
varying vec3 vColor;
void main() {
vColor = aColor;
vec3 newPosition =position+normal*displacement;//每个面随机偏移
gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
}
设置随机偏移值
//需要赋值的偏移变量数组
const displacement = new Float32Array(numFaces * 3 * 3);
for (let f = 0; f < numFaces; f++) {
const index = 9 * f;
//随机偏移值
const d = that.minDistance + that.distance * Math.random();
for (let i = 0; i < 3; i++) {
//给3个点赋值偏移值,形成对应的三角形
displacement[index + 3 * i] = d;
displacement[index + 3 * i + 1] = d + Math.random() * that.minDistance;
displacement[index + 3 * i + 2] = d + Math.random() * that.minDistance;
}
}
//设置顶点着色器值
geometry.setAttribute('displacement', new THREE.BufferAttribute(displacement, 3));
9.随机偏移的三角形汇聚成原来的字体
9.1 偏移
uniform float time;
attribute vec3 aColor;
attribute vec3 displacement; //偏移值
varying vec3 vColor;
void main() {
vColor = aColor;
vec3 newPosition =position+normal*displacement*time;//每个面随机偏移随时间变
gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
}
9.2 汇聚
让偏移值随时间递减到0,汇聚成原来的字体,则时间值递减
animateAction() {
if (this.mesh) {
if (this.time >= 0) {
this.time += 0.005;
this.mesh.material.uniforms.time.value = 2.0 - this.time;
if (this.time >= 2.0) {
this.time = -1;
}
} else {
this.mesh.material.uniforms.time.value = 0.0;
}
}
}
10.字体面数细化
import {
TessellateModifier } from '../node_modules/three/examples/jsm/modifiers/TessellateModifier.js';
//细化修改器
const tessellateModifier = new TessellateModifier(8, 6);
//修改图形的面数
geometry = tessellateModifier.modify(geometry);
细化修改器
TessellateModifier( maxEdgeLength=0.1 最大边长, maxIterations = 6 最大遍历次数, maxFaces = Infinity 最大面数 )
可以看到相对于原来的字体,面数增加了,更加精细了!
11.同理可在其他模型形状也可使用该效果
let geometry = new THREE.CylinderGeometry(that.topRadius, that.bottomRadius, that.height);
//图形居中
geometry.center();
//细化修改器
const tessellateModifier = new TessellateModifier(8, 6);
//修改图形的面数
geometry = tessellateModifier.modify(geometry);
//转为缓存图形,方便获取点面等数据
geometry = new THREE.BufferGeometry().fromGeometry(geometry);
//...
GitHub地址
http://github.com/xiaolidan00/my-three
参考:https://threejs.org/examples/#webgl_modifier_tessellation