Fog/Tween/Trimesh
约 1232 字大约 4 分钟
2025-03-31
雾
在 Threejs 中,Fog 类用于创建线性雾的效果。雾效果常用于模拟真实世界中视觉深度递减的效果,也可以用于创建某些艺术效果。当物体距离观察者越远,雾就越浓,物体的颜色就越接近雾的颜色。
Fog
const scene = new THREE.Scene();
const cube = new THREE.Mesh(
new THREE.BoxGeometry(1, 1, 50),
new THREE.MeshBasicMaterial({ color: 0x00ff00 })
);
scene.add(cube);
scene.fog = new THREE.Fog(0x999999, 0.1, 20);
参数:
color: 雾的颜色,默认为黑色。
near: 雾开始生效的距离,默认为 1。
far: 雾完全生效的距离,默认为 1000。
.isFog: 只读属性,表示该对象是否为雾对象。
FogExp2
const scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000000, 0.02);
参数:
color: 雾的颜色,默认为黑色。
density: 雾的密度,默认为 0.00025。
isFogExp2: 只读属性,表示该对象是否为 FogExp2 对象。
注意:
雾效果是通过改变物体材质的颜色来实现的,如果一个物体的材质不包含颜色信息,那么雾效果将不会对该物体产生影响。
在一些复杂的场景中,雾效果可能会对渲染性能产生影响,因此在使用雾效果时需要权衡性能和视觉效果。
雾效果并不会阻止物体的渲染,而是通过改变物体的颜色来模拟雾的效果。
补间动画(Tween)
Tween.js 是一个轻量级的 JavaScript 库,用于创建补间动画。补间动画是一种常见的动画形式,它通过在两个关键帧之间插入多个中间帧来创建平滑的动画效果。
//导入tween
import * as TWEEN from "three/examples/jsm/libs/tween.module.js";
//创建补间动画-可以链式调用
const tween = new TWEEN.Tween(sphere.position).to({ x: 6 }, 2000).start();
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
TWEEN.update(); //更新补间动画
}
方法
to(): 设置动画的目标值。
start(): 启动动画。
stop(): 停止动画。
chain(): 链接动画,使一个动画结束后立即开始下一个动画。
repeat(): 设置动画重复的次数。
yoyo(): 设置动画是否在重复时反向播放。
easing(): 设置动画的缓动函数。
delay(): 设置动画的延迟时间。
interpolation(): 设置动画的插值函数。
onUpdate(): 设置动画更新时的回调函数。
onComplete(): 设置动画完成时的回调函数。
onStart(): 设置动画开始时的回调函数。
onStop(): 设置动画停止时的回调函数。
缓动函数
缓动函数用于控制动画的速度,它决定了动画在两个关键帧之间如何变化。Three.js 提供了多种内置的缓动函数:
const tween = new TWEEN.Tween(sphere.position)
.to({ x: 6 }, 2000)
.easing(TWEEN.Easing.Quadratic.InOut);
//创建补间动画
const tween = new TWEEN.Tween(sphere.position).to({ x: 6 }, 1000);
const tween2 = new TWEEN.Tween(sphere.position).to({ y: -4 }, 1000);
const tween3 = new TWEEN.Tween(sphere.position).to({ x: -6 }, 1000);
const tween4 = new TWEEN.Tween(sphere.position).to({ y: 4 }, 1000);
tween.chain(tween2);
tween2.chain(tween3);
tween3.chain(tween4);
tween4.chain(tween);
tween.start();
Trimesh 不规则形状
之前在学习 CANNON
中知道,绘制物体时不仅需要绘制几何体还需要绘制物理几何体,对于绘制几何体,Three.js 提供了 BufferGeometry
来创建几何体,或者通过导入 3D 模型来创建不规则几何体。同样,在绘制物理几何体时,CANNON.js 提供了 Trimesh
来创建不规则形状,适用于复杂的多面体、不规则的物体,甚至可以基于导入进来的 3D 模型创建对应的物理形状。
Trimesh() 构造函数用于创建不规则形状,适用于复杂的多面体、不规则的物体,甚至可以基于导入进来的 3D 模型创建对应的物理形状。
//导入GLTFLoader
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
//导入CANNON
import * as CANNON from "cannon-es";
//创建物理世界
const world = new CANNON.World();
world.gravity.set(0, -9.82, 0); // 设置重力
//创建地面
const ground = new THREE.Mesh(
new THREE.PlaneGeometry(100, 100),
new THREE.MeshBasicMaterial({ color: 0x303030, side: THREE.DoubleSide })
);
ground.rotation.x = -Math.PI / 2;
scene.add(ground);
//创建地面物理
const groundBody = new CANNON.Body({ mass: 0, shape: new CANNON.Plane() });
groundBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0);
world.addBody(groundBody);
var body;
var mesh;
const gltfLoader = new GLTFLoader();
gltfLoader.load("./models/bunny.gltf", (gltf) => {
gltf.scene.position.set(0, 2, 0);
mesh = gltf.scene;
scene.add(gltf.scene);
//获取geometry
const geometry = gltf.scene.getObjectByName("bunny").geometry;
//创建物理
let shape = new CANNON.Trimesh(geometry.attributes.position.array, geometry.index.array);
body = new CANNON.Body({
mass: 1,
shape,
position: gltf.scene.position,
});
world.addBody(body);
});
function animate() {
requestAnimationFrame(animate);
world.step(1 / 60);
if (mesh) {
mesh.position.copy(body.position);
mesh.quaternion.copy(body.quaternion);
}
renderer.render(scene, camera);
}
.Trimesh() 构造函数用于创建不规则形状。
vertices: 顶点位置数据。
indices: 顶点索引数据。
物理引擎调试
使用 Cannon.js
时,无法直观的看到物体的物理属性,比如碰撞、摩擦力等,因此需要使用调试工具来查看物体的物理属性。
- 安装
npm install cannon-es-debugger
- 导入
import { CannonDebugger } from "cannon-es-debugger";
- 创建调试器
const cannonDebugger = new CannonDebugger(scene, world, {
//设置颜色
color: 0xffffff,
});
- 更新调试器
function animate() {
requestAnimationFrame(animate);
world.step(1 / 60);
cannonDebugger.update(); //更新调试器
renderer.render(scene, camera);
}