【Three.js】实现护罩(防御罩、金钟罩、护盾)效果
前言:
在这篇博客中,我们将使用 Three.js 从零开始生成一个护罩效果。护罩将使用自定义的 Shader 材质,带有动画效果,最终呈现一个视觉上酷炫的护罩。此篇文章的重点将放在如何生成一个3D护罩,其它功能将在之后的博客中讨论,后续会有很多酷炫的效果~
。
实现技术简介:
要实现这个护罩,我们需要掌握以下技术:
- Three.js: 一个强大的 3D 图形库,简化了 WebGL 的使用。
- Shader: 我们将用到 GLSL(OpenGL 着色语言)编写自定义着色器,为护罩增添独特的效果,比如渐变、透明度和动态变化。
- WebGLRenderer: Three.js 的核心渲染器,用于将 3D 场景渲染到网页上。
第一步:设置基础的场景
任何使用three.js的项目都会设置基础的场景,且大同小异
在开始生成护罩之前,我们需要一个 Three.js 基础场景。这个场景包括相机、渲染器和一些光源,以便能够观察到护罩的效果。
代码:
// 创建一个场景
const scene = new THREE.Scene();
// 设置透视相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 7, 10);
// 创建 WebGL 渲染器并设置其尺寸
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加环境光和方向光到场景中
const ambientLight = new THREE.AmbientLight(0xcccccc, 0.4); // 柔和的环境光
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); // 模拟太阳光的方向光
directionalLight.position.set(0, 5, 5);
scene.add(directionalLight);
解释:
- 场景(Scene):Three.js 中所有对象的容器,所有物体都会添加到场景中。
- 相机(Camera):用于查看场景。这里我们使用透视相机,能模拟人眼的视角。
- 渲染器(Renderer):负责将 3D 场景绘制到网页上,我们选择了 WebGLRenderer 并将其尺寸设置为浏览器窗口大小。
- 光源(Light):环境光均匀地照亮场景,方向光模拟来自一个方向的强光,给物体添加阴影效果。
第二步:创建自定义护罩材质
为了让护罩看起来与众不同,我们需要自定义材质。我们将使用 GLSL 编写顶点着色器和片段着色器,来控制护罩的颜色、透明度和动画效果。
代码:
// 创建护罩的自定义 Shader 材质
class ShieldMaterial extends THREE.ShaderMaterial {
constructor() {
super({
uniforms: {
time: { value: 0 }, // 动态变化的时间
color: { value: new THREE.Color(0x00ffff) } // 护罩的颜色
},
vertexShader: `
varying vec3 vNormal;
void main() {
vNormal = normalize(normalMatrix * normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform float time;
uniform vec3 color;
varying vec3 vNormal;
void main() {
float intensity = pow(0.5 - dot(vNormal, vec3(0.0, 0.0, 1.0)), 2.0);
gl_FragColor = vec4(color * intensity, 1.0);
}
`,
transparent: true, // 设置材质为透明
blending: THREE.AdditiveBlending, // 使用叠加效果
});
}
update(time) {
this.uniforms.time.value = time;
}
}
解释:
- ShaderMaterial:我们继承了
THREE.ShaderMaterial
类来创建自定义的护罩材质。 - 顶点着色器(Vertex Shader):用于处理每个顶点的位置。这里我们计算了每个顶点的法线信息。
- 片段着色器(Fragment Shader):控制护罩的颜色和透明度。我们通过法线计算光照的强度,并将护罩设置为半透明效果。
- uniforms:用于在 GPU 上保存变量。我们定义了
time
来让护罩产生动态效果,color
控制护罩的颜色。 - blending:使用叠加混合模式,使护罩看起来有发光效果。
第三步:生成护罩几何体
接下来,我们需要生成一个 3D 几何体来承载我们的材质。我们使用 Three.js 提供的 SphereGeometry
来生成一个球体,代表护罩的形状。
代码:
// 创建护罩
const createShield = () => {
// 创建球体几何体,表示护罩
const geometry = new THREE.SphereGeometry(1.5, 64, 64); // 半径为1.5的球体,使用64段分割
const material = new ShieldMaterial(); // 使用自定义的护罩材质
// 创建网格并将几何体和材质绑定
const shield = new THREE.Mesh(geometry, material);
// 将护罩添加到场景中
scene.add(shield);
return shield;
};
const shield = createShield();
解释:
- SphereGeometry:生成一个球体,半径为 1.5,几何体细分为 64 段,使球体看起来更加平滑。
- Mesh:将几何体与材质结合生成一个网格,并将这个护罩网格添加到场景中。
第四步:渲染和动画
为了让护罩动画起来,我们可以通过不断更新时间 time
变量,使其动态变化。在动画循环中,更新 ShieldMaterial
的时间。
代码:
// 创建动画循环
const clock = new THREE.Clock(); // 用于追踪时间
const animate = () => {
requestAnimationFrame(animate); // 不断调用 animate 函数
const elapsedTime = clock.getElapsedTime(); // 获取流逝的时间
// 更新护罩的时间,使其产生动态效果
shield.material.update(elapsedTime);
// 渲染场景
renderer.render(scene, camera);
};
animate(); // 开始动画循环
解释:
- Clock:Three.js 中的
Clock
对象用于获取经过的时间,使我们可以根据时间变化来创建动画效果。 - requestAnimationFrame:浏览器内置的动画函数,确保动画以最佳帧率运行。
- update:我们将流逝的时间传递给护罩材质的
time
参数,让护罩随时间变化而动态变动。
总结:
通过以上步骤,我们使用 Three.js 和自定义 Shader 成功生成了一个带有动画效果的护罩。你可以根据需求自定义护罩的颜色、动画速度和透明度。
在未来的博客中,我们将深入探讨如何扩展这个护罩效果,比如添加交互、生成多个护罩或是为护罩之间添加飞线特效。
ps:最近的项目使用three.js的地方很多,且拓展了很多功能,我会将一个个的功能点拆分出来。因为之前查找相关博客发现很多都是整个一起的,对于只想要其中一部分而言会增加很多不必要的时间成本,所以我会将功能点拆解出来。