三维引擎Wall2类封装:动态圆柱墙体实现
在三维可视化场景中,墙体是常见的几何元素之一。本文将基于Three.js库,将一段创建动态圆柱墙体的代码封装为Wall2
类,实现可复用的圆柱墙体组件,支持动态效果和自定义样式。

类设计概述
Wall2
类主要实现以下功能:
- 创建圆柱几何体
- 应用自定义着色器实现动态效果
- 支持高度、颜色等属性配置
- 提供资源管理和更新接口
该类参考了已有的Wall
类结构,采用面向对象设计,便于在场景中集成和管理。
完整代码实现
javascript
/**
*
* @file 动态圆柱墙体
*
* @author
*/
import {
Object3D,
CylinderGeometry,
ShaderMaterial,
Mesh,
DoubleSide
} from 'three';
/**
* 动态圆柱墙体类 - 用于创建带波浪动态效果的圆柱墙体
* @class Wall2
* @extends Object3D
* @param {Object} [opts={}] 初始化参数
* @param {number} [opts.radius=30] 圆柱半径
* @param {number} [opts.height=20] 圆柱高度
* @param {number} [opts.radialSegments=4] 径向分段数
* @param {number} [opts.heightSegments=64] 高度分段数
* @param {boolean} [opts.openEnded=true] 是否开放端面
* @param {Object|string} [opts.color] 墙体颜色
* @param {number} [opts.time=0] 时间参数,用于动态效果
* @param {number} [opts.positionY=10] Y轴位置偏移
*/
class Wall2 {
constructor(opts = {}) {
super();
// 基础属性初始化
this.radius = opts.radius || 30;
this.height = opts.height || 20;
this.radialSegments = opts.radialSegments || 4;
this.heightSegments = opts.heightSegments || 64;
this.openEnded = opts.openEnded !== undefined ? opts.openEnded : true;
this.color = opts.color || { r: 0, g: 1, b: 0.5 };
this.time = opts.time || 0;
this.positionY = opts.positionY || 10;
// 渲染相关属性
this.geometry = null;
this.material = null;
this.mesh = null;
// 初始化墙体
this.init();
}
/**
* 初始化圆柱墙体
* @private
*/
init() {
// 创建圆柱几何体
this.geometry = new CylinderGeometry(
this.radius,
this.radius,
this.height,
this.radialSegments,
this.heightSegments,
this.openEnded
);
// 创建着色器材质
this.material = new ShaderMaterial({
side: DoubleSide,
transparent: true,
depthWrite: false,
uniforms: {
uTime: { value: this.time },
uColor: { value: this.color }
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform float uTime;
uniform vec3 uColor;
varying vec2 vUv;
#define PI 3.14159265
void main() {
vec4 baseColor = vec4(uColor, 1.0);
vec4 finalColor;
float amplitude = 1.0;
float frequency = 10.0;
float x = vUv.x;
float y = sin(x * frequency);
float t = 0.01 * (-uTime * 130.0);
y += sin(x * frequency * 2.1 + t) * 4.5;
y += sin(x * frequency * 1.72 + t * 1.121) * 4.0;
y += sin(x * frequency * 2.221 + t * 0.437) * 5.0;
y += sin(x * frequency * 3.1122 + t * 4.269) * 2.5;
y *= amplitude * 0.06;
y /= 3.0;
y += 0.55;
float r = step(0.5, fract(vUv.y - uTime));
baseColor.a = step(vUv.y, y) * (y - vUv.y) / y;
gl_FragColor = baseColor;
}
`
});
// 创建网格对象
this.mesh = new Mesh(this.geometry, this.material);
this.mesh.position.y = this.positionY;
}
}
export { Wall2 };
核心功能解析
构造函数与属性初始化
javascript
constructor(opts = {}) {
super();
// 基础属性初始化
this.radius = opts.radius || 30;
this.height = opts.height || 20;
this.radialSegments = opts.radialSegments || 4;
this.heightSegments = opts.heightSegments || 64;
this.openEnded = opts.openEnded !== undefined ? opts.openEnded : true;
this.color = opts.color || { r: 0, g: 1, b: 0.5 };
this.time = opts.time || 0;
this.positionY = opts.positionY || 10;
// 渲染相关属性
this.geometry = null;
this.material = null;
this.mesh = null;
// 初始化墙体
this.init();
}
构造函数中定义了墙体的基本属性:
- 几何属性:半径、高度、分段数等
- 视觉属性:颜色、位置偏移
- 渲染相关:几何体、材质、网格对象引用
初始化方法
javascript
init() {
// 创建圆柱几何体
this.geometry = new CylinderGeometry(
this.radius,
this.radius,
this.height,
this.radialSegments,
this.heightSegments,
this.openEnded
);
// 创建着色器材质
this.material = new ShaderMaterial({
side: DoubleSide,
transparent: true,
depthWrite: false,
uniforms: {
uTime: { value: this.time },
uColor: { value: this.color }
},
// 顶点着色器和片段着色器代码(略)
});
// 创建网格对象并添加到场景
this.mesh = new Mesh(this.geometry, this.material);
this.mesh.position.y = this.positionY;
this.add(this.mesh);
}
初始化方法完成以下核心工作:
- 使用
CylinderGeometry
创建圆柱几何体 - 配置
ShaderMaterial
实现自定义渲染效果 - 将几何体与材质组合成
Mesh
对象 - 设置网格位置并添加到当前对象
着色器实现动态效果
着色器代码是实现动态波浪效果的关键:
glsl
// 顶点着色器
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
// 片段着色器
uniform float uTime;
uniform vec3 uColor;
varying vec2 vUv;
#define PI 3.14159265
void main() {
vec4 baseColor = vec4(uColor, 1.0);
float amplitude = 1.0;
float frequency = 10.0;
float x = vUv.x;
float y = sin(x * frequency);
float t = 0.01 * (-uTime * 130.0);
y += sin(x * frequency * 2.1 + t) * 4.5;
y += sin(x * frequency * 1.72 + t * 1.121) * 4.0;
y += sin(x * frequency * 2.221 + t * 0.437) * 5.0;
y += sin(x * frequency * 3.1122 + t * 4.269) * 2.5;
y *= amplitude * 0.06;
y /= 3.0;
y += 0.55;
float r = step(0.5, fract(vUv.y - uTime));
baseColor.a = step(vUv.y, y) * (y - vUv.y) / y;
gl_FragColor = baseColor;
}
着色器实现了以下效果:
- 通过多个正弦函数叠加生成复杂波浪曲线
- 使用
uTime
uniform参数驱动动画效果 - 根据UV坐标计算透明度,实现波浪上升效果
- 支持自定义颜色参数
更新与资源管理
javascript
/**
* 更新墙体状态
* @param {number} deltaTime 时间增量
*/
update(deltaTime) {
if (this.material) {
this.time += deltaTime;
this.material.uniforms.uTime.value = this.time;
}
}
/**
* 释放资源
*/
dispose() {
if (this.mesh) {
if (this.mesh.geometry) {
this.mesh.geometry.dispose();
}
if (this.mesh.material) {
this.mesh.material.dispose();
}
this.remove(this.mesh);
this.mesh = null;
}
this.geometry = null;
this.material = null;
}
更新方法用于驱动动态效果,通过更新uTime
参数使波浪动画持续运行。
使用示例
下面是一个完整的使用示例,展示如何创建Wall2
实例并集成到Three.js场景中:
javascript
import { Wall2 } from "./Wall2";
import * as THREE from "three";
// 初始化场景、相机和渲染器
function initScene() {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 添加光源
const ambientLight = new THREE.AmbientLight(0x404040, 2);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(1, 1, 1);
scene.add(directionalLight);
return { scene, camera, renderer };
}
// 创建墙体
function createWall(scene) {
const wall = new Wall2({
radius: 40,
height: 30,
radialSegments: 8,
heightSegments: 128,
color: 0x00aaff,
positionY: 15
});
scene.add(wall);
return wall;
}
// 动画循环
function animate(scene, camera, renderer, wall) {
requestAnimationFrame(() => animate(scene, camera, renderer, wall));
// 更新墙体动画
const deltaTime = 0.01;
wall.update(deltaTime);
// 旋转相机
camera.position.x = Math.sin(Date.now() * 0.001) * 100;
camera.position.z = Math.cos(Date.now() * 0.001) * 100;
camera.lookAt(new THREE.Vector3(0, 15, 0));
renderer.render(scene, camera);
}
// 初始化并启动
const { scene, camera, renderer } = initScene();
const wall = createWall(scene);
animate(scene, camera, renderer, wall);
扩展与优化方向
功能扩展
-
端面处理:当前实现为开放端面,可添加封闭端面选项
-
纹理支持:扩展材质以支持纹理贴图,丰富墙体外观
-
动态参数配置:增加更多可配置的动态效果参数,如波浪幅度、频率等
-
事件系统:添加交互事件支持,如鼠标悬停、点击等
性能优化
-
几何体优化:对于大型场景,可根据相机距离动态调整分段数
-
批量渲染 :使用
InstancedMesh
实现多个墙体的批量渲染 -
LOD支持:实现层次细节(Level of Detail),远距离使用简化模型
高级效果
-
光影效果:修改着色器以支持光照,使墙体更真实
-
透明渐变:实现墙体透明度随高度变化的效果
-
复杂波形:扩展波形函数,实现更复杂的动态效果
-
材质混合:支持多种材质混合,创建更丰富的视觉效果
总结
通过封装Wall2
类,我们实现了一个功能完整的动态圆柱墙体组件,具有以下特点:
- 支持圆柱几何参数自定义
- 通过着色器实现动态波浪效果
- 提供颜色、位置等视觉属性配置
- 实现资源管理和状态更新接口