基于 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类,我们实现了一个功能完整的动态圆柱墙体组件,具有以下特点:

  • 支持圆柱几何参数自定义
  • 通过着色器实现动态波浪效果
  • 提供颜色、位置等视觉属性配置
  • 实现资源管理和状态更新接口
相关推荐
red润4 小时前
THREE.Ray 和 THREE.Raycaster 用途和功能
three.js
YAY_tyy14 小时前
Three.js 开发实战教程(五):外部 3D 模型加载与优化实战
前端·javascript·3d·three.js
入秋1 天前
Three.js 实战之电子围栏可根据模型自动生成
前端·前端框架·three.js
答案answer2 天前
three.js着色器(Shader)实现数字孪生项目中常见的特效
前端·three.js
KallkaGo7 天前
threejs复刻原神渲染(三)
前端·webgl·three.js
刘皇叔code9 天前
如何给Three.js中ExtrudeGeometry的不同面设置不同材质
webgl·three.js
vivo互联网技术9 天前
拥抱新一代 Web 3D 引擎,Three.js 项目快速升级 Galacean 指南
前端·three.js
你真的可爱呀14 天前
5.Three.js 学习(基础+实践)
学习·three.js