基于 Three.js 开发三维引擎-02动态圆柱墙体实现

三维引擎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);
}

初始化方法完成以下核心工作:

  1. 使用CylinderGeometry创建圆柱几何体
  2. 配置ShaderMaterial实现自定义渲染效果
  3. 将几何体与材质组合成Mesh对象
  4. 设置网格位置并添加到当前对象

着色器实现动态效果

着色器代码是实现动态波浪效果的关键:

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;
}

着色器实现了以下效果:

  • 通过多个正弦函数叠加生成复杂波浪曲线
  • 使用uTimeuniform参数驱动动画效果
  • 根据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);

扩展与优化方向

功能扩展

  1. 端面处理:当前实现为开放端面,可添加封闭端面选项

  2. 纹理支持:扩展材质以支持纹理贴图,丰富墙体外观

  3. 动态参数配置:增加更多可配置的动态效果参数,如波浪幅度、频率等

  4. 事件系统:添加交互事件支持,如鼠标悬停、点击等

性能优化

  1. 几何体优化:对于大型场景,可根据相机距离动态调整分段数

  2. 批量渲染 :使用InstancedMesh实现多个墙体的批量渲染

  3. LOD支持:实现层次细节(Level of Detail),远距离使用简化模型

高级效果

  1. 光影效果:修改着色器以支持光照,使墙体更真实

  2. 透明渐变:实现墙体透明度随高度变化的效果

  3. 复杂波形:扩展波形函数,实现更复杂的动态效果

  4. 材质混合:支持多种材质混合,创建更丰富的视觉效果

总结

通过封装Wall2类,我们实现了一个功能完整的动态圆柱墙体组件,具有以下特点:

  • 支持圆柱几何参数自定义
  • 通过着色器实现动态波浪效果
  • 提供颜色、位置等视觉属性配置
  • 实现资源管理和状态更新接口
相关推荐
小桥风满袖4 小时前
Three.js-硬要自学系列38之专项学习缓冲几何体
前端·css·three.js
用户3802258598246 小时前
使用three.js实现3D地球
前端·three.js
三维搬砖者11 小时前
基于 Three.js 开发三维引擎-01点类:从原理到实践
webgl·three.js
魂断蓝桥6661 天前
如何基于three.js(webgl)引擎架构,实现3D微信小游戏(第一课)
webgl·three.js·微信小游戏·three.js路径规划、三维a*算法、javascript三维导航,·three.js小游戏
Mintopia1 天前
Three.js 深度冲突:当像素在 Z 轴上玩起 "挤地铁" 游戏
前端·javascript·three.js
Mintopia2 天前
Three.js 加载模型文件:从二进制到像素的奇幻漂流
前端·javascript·three.js
良辰未晚3 天前
基于全屏 Quad 的 Three.js 后处理全解析
three.js
Mintopia3 天前
Three.js 材质与灯光:一场像素级的光影华尔兹
前端·javascript·three.js
Mintopia3 天前
Three.js 3D 世界中的噪声运动:当数学与像素共舞
前端·javascript·three.js