# 用three.js创造时空裂缝特效

14,062 阅读2分钟

code.juejin.cn/pen/7168065…

## 建模

### 多边形形状

``````let points = [
{ x: 0, y: 0 },
{ x: 25, y: 0 },
{ x: 45, y: 45 },
{ x: 0, y: 25 },
];
points = kokomi.polySort(points);
const shape = kokomi.createPolygonShape(points, {
scale: 0.01,
});
const geometry = new THREE.ExtrudeGeometry(shape, {
steps: 1,
depth: 0.0001,
bevelEnabled: true,
bevelThickness: 0.0005,
bevelSize: 0.0005,
bevelSegments: 1,
});
geometry.center();
``````

### 随机多边形

1. 多边形是按二维网格排布的，这样就能尽可能避免有重合的情况出现
2. 多边形的边数`edgeCount`按个人喜好用随机概率来控制
3. 多边形的第一个点决定了它在网格上的位置，其他的点是以它为圆心延伸出来的随机角度的点（跟圆有关因此用到了极坐标公式）
``````const generatePolygons = (config = {}) => {
const { gridX = 10, gridY = 20, maxX = 9, maxY = 9 } = config;

const polygons = [];

for (let i = 0; i < gridX; i++) {
for (let j = 0; j < gridY; j++) {
const points = [];
let edgeCount = 3;
const randEdgePossibility = Math.random();
if (randEdgePossibility > 0 && randEdgePossibility <= 0.2) {
edgeCount = 3;
} else if (randEdgePossibility > 0.2 && randEdgePossibility <= 0.55) {
edgeCount = 4;
} else if (randEdgePossibility > 0.55 && randEdgePossibility <= 0.9) {
edgeCount = 5;
} else if (randEdgePossibility > 0.9 && randEdgePossibility <= 0.95) {
edgeCount = 6;
} else if (randEdgePossibility > 0.95 && randEdgePossibility <= 1) {
edgeCount = 7;
}
let firstPoint = {
x: 0,
y: 0,
};
let angle = THREE.MathUtils.randFloat(0, 2 * Math.PI);
for (let k = 0; k < edgeCount; k++) {
if (k === 0) {
firstPoint = {
x: (i % maxX) * 10,
y: (j % maxY) * 10,
};
points.push(firstPoint);
} else {
// random polar
const r = 10;
angle += THREE.MathUtils.randFloat(0, Math.PI / 2);
const anotherPoint = {
x: firstPoint.x + r * Math.cos(angle),
y: firstPoint.y + r * Math.sin(angle),
};
points.push(anotherPoint);
}
}
polygons.push(points);
}
}

return polygons;
};
``````

## 漂浮动画

``````let floatDistance = 0;
let floatSpeed = 1;
let floatMaxDistance = 1;

this.update(() => {
floatDistance += floatSpeed;

const y = floatDistance * 0.001;
if (y > floatMaxDistance) {
floatDistance = 0;
}

totalG.position.y = y;
});
``````

1. 要想达成一种大小错落的层次感，我们可以拷贝一份多边形组，将其的z轴位置往后移即可
2. 要想达成无限上升的动画“假象”，我们需要再整体拷贝一份多边形组（包括组本身和偏移z轴后的组），将它和之前的那组在y轴上错开，这样动画就能无限衔接了

## 光照

1. 漫反射光和镜面反射光相结合
2. 扭曲顶点、法线和uv
3. 根据光线动态计算透明度，以形成玻璃般的效果

## 后期处理

1. RGB扭曲（该特效所采用的）
2. 色差
3. 景深效果
4. 噪声点阵