当前位置: 首页 > news >正文

three案例 Three.js波纹效果演示

在这里插入图片描述
波纹效果,在智慧城市可视化开发中经常用到,这里分享一个比较好玩的案例
以下是详细的步骤:

初始化部分:设置 Three.js 环境,包括场景、相机、渲染器和控制器
几何体和纹理:创建平面几何体并加载波纹纹理
着色器材质:使用自定义着色器实现波纹效果,包括顶点着色器和片段着色器
波纹算法:核心是 circleWave 函数,通过计算距离和时间来生成向外扩散的波纹
颜色混合:根据波纹强度混合两种颜色,形成视觉层次感
交互控制:使用 GUI 工具允许用户实时调整波纹颜色
动画循环:通过不断更新时间变量来驱动波纹动画
浏览地址:https://aivogenx.github.io/threejs-cesium-webgpu-vue-js/#/codeMirror?navigation=Three.js%E6%A1%88%E4%BE%8B&classify=shader&id=circleWave
代码

<!DOCTYPE html>
<html lang="zh-CN"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Three.js波纹效果演示</title><!-- 这里可以添加CSS样式文件 -->
</head><body><!-- 导入模块映射,配置Three.js依赖路径 --><script type="importmap">{"imports": {"three": "./threejs/build/three.module.js","three/addons/": "./threejs/examples/jsm/"}}</script><script type="module">// 导入Three.js核心库和辅助工具import * as THREE from 'three'import { OrbitControls } from "three/addons/controls/OrbitControls.js"; import { GUI } from "three/addons/libs/lil-gui.module.min.js";// 获取渲染容器,使用整个body元素const box = document.body;// 创建Three.js场景,作为所有3D对象的容器const scene = new THREE.Scene()// 创建透视相机,参数依次为:视野角度、宽高比、近裁剪面、远裁剪面const camera = new THREE.PerspectiveCamera(50, box.clientWidth / box.clientHeight, 0.1, 1000)// 设置相机位置,从(1,1,1)的位置观察场景camera.position.set(1, 1, 1)// 创建WebGL渲染器,启用抗锯齿、透明背景和对数深度缓冲区const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true })// 设置渲染器尺寸为容器大小renderer.setSize(box.clientWidth, box.clientHeight)// 将渲染器的DOM元素添加到页面中box.appendChild(renderer.domElement)// 创建轨道控制器,允许用户通过鼠标交互旋转和缩放场景const controls = new OrbitControls(camera, renderer.domElement)// 启用阻尼效果,使相机移动更平滑controls.enableDamping = true// 窗口大小变化时的响应函数,保持渲染内容适配窗口window.onresize = () => {// 更新渲染器尺寸renderer.setSize(box.clientWidth, box.clientHeight)// 更新相机的宽高比camera.aspect = box.clientWidth / box.clientHeight// 更新相机投影矩阵camera.updateProjectionMatrix()}// 创建平面几何体,作为波纹效果的载体const geometry = new THREE.PlaneGeometry(2, 2);// 加载波纹纹理,这是实现波纹效果的基础纹理// 注意:FILE_HOST变量需要在实际使用时替换为真实的资源路径const texture = new THREE.TextureLoader().load(FILE_HOST + 'images/channels/wave.png')// 设置纹理在水平和垂直方向上重复texture.wrapS = THREE.RepeatWrappingtexture.wrapT = THREE.RepeatWrapping// 创建自定义着色器材质,实现波纹效果的核心部分const material = new THREE.ShaderMaterial({side: THREE.DoubleSide,          // 双面渲染transparent: true,             // 启用透明度blending: THREE.AdditiveBlending, // 添加混合模式让效果更亮uniforms: {uTime: { value: 0.0 },           // 时间变量,控制波纹动画uScanTex: { value: texture },    // 波纹纹理uScanColor: { value: new THREE.Color(0x00ffff) },    // 主要扫描颜色uScanColorDark: { value: new THREE.Color(0x0088ff) } // 暗部扫描颜色},// 顶点着色器:处理几何体顶点,传递纹理坐标和位置信息给片段着色器vertexShader: `varying vec2 vUv;         // 传递给片段着色器的纹理坐标varying vec3 vPosition;   // 传递给片段着色器的顶点位置void main() {vUv = uv;vPosition = position;gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}`,// 片段着色器:计算每个像素的颜色,实现波纹效果的核心逻辑fragmentShader: `// 波纹原点和波纹扩展速度常量#define uScanOrigin vec3(0.0, 0.0, 0.0)#define uScanWaveRatio1 3.2#define uScanWaveRatio2 2.8uniform float uTime;           // 时间变量uniform sampler2D uScanTex;    // 波纹纹理uniform vec3 uScanColor;       // 波纹主颜色uniform vec3 uScanColorDark;   // 波纹暗部颜色varying vec2 vUv;              // 从顶点着色器传递的纹理坐标varying vec3 vPosition;        // 从顶点着色器传递的顶点位置// 计算圆形波纹效果float circleWave(vec3 p, vec3 origin, float distRatio) {float t = uTime;float dist = distance(p, origin) * distRatio;  // 计算到原点的距离并应用缩放float radialMove = fract(dist - t);            // 创建随时间移动的波纹float fadeOutMask = 1.0 - smoothstep(1.0, 3.0, dist); // 波纹随距离衰减radialMove *= fadeOutMask;float cutInitialMask = 1.0 - step(t, dist);    // 控制波纹从中心向外扩展return radialMove * cutInitialMask;}// 根据位置和纹理计算波纹颜色vec3 getScanColor(vec3 worldPos, vec2 uv, vec3 col) {// 从纹理采样,获取波纹基础图案float scanMask = texture2D(uScanTex, uv).r;// 计算两种不同速度的波纹效果,形成层次感float cw = circleWave(worldPos, uScanOrigin, uScanWaveRatio1);float cw2 = circleWave(worldPos, uScanOrigin, uScanWaveRatio2);// 为第一种波纹创建遮罩,控制波纹的显示范围和强度float mask1 = smoothstep(0.3, 0.0, 1.0 - cw);mask1 *= (1.0 + scanMask * 0.7);  // 结合纹理增强效果// 为第二种波纹创建遮罩float mask2 = smoothstep(0.07, 0.0, 1.0 - cw2) * 0.8;mask1 += mask2;// 创建波纹边缘高亮效果float mask3 = smoothstep(0.09, 0.0, 1.0 - cw) * 1.5;mask1 += mask3;// 根据遮罩强度混合两种颜色,形成波纹的颜色变化vec3 scanCol = mix(uScanColorDark, uScanColor, mask1);return scanCol * mask1; // 返回最终的波纹颜色}void main() {vec3 col = vec3(0.0);// 计算波纹颜色,纹理坐标乘以10.0增强波纹密度col = getScanColor(vPosition, vUv * 10.0, col);// 根据颜色强度计算透明度,使波纹边缘更柔和float alpha = length(col);gl_FragColor = vec4(col, alpha);}`});// 创建网格对象,将几何体和材质组合,并添加到场景中const mesh = new THREE.Mesh(geometry, material);// 将平面旋转90度,使其水平放置mesh.rotation.x = Math.PI / 2scene.add(mesh);// 创建图形界面控制器,允许用户交互调整参数const gui = new GUI()const params = {uScanColor: '#00ffff',         // 波纹主颜色uScanColorDark: '#0088ff'      // 波纹暗部颜色}// 添加颜色控制器,允许用户修改波纹主颜色gui.addColor(params, 'uScanColor').onChange((value) => {material.uniforms.uScanColor.value.set(value)})// 添加颜色控制器,允许用户修改波纹暗部颜色gui.addColor(params, 'uScanColorDark').onChange((value) => {material.uniforms.uScanColorDark.value.set(value)})// 动画循环函数,驱动整个场景的渲染和更新animate()function animate() {// 请求下一帧动画requestAnimationFrame(animate)// 更新控制器状态controls.update()// 渲染场景renderer.render(scene, camera)// 更新时间变量,驱动波纹动画material.uniforms.uTime.value += 0.005;}</script>
</body></html>
http://www.dtcms.com/a/269781.html

相关文章:

  • “Jmeter中 xxx.jtl:1:1: Fatal Error! 前言中不允许有内容”的解决办法
  • 开源 SIP 协议栈介绍
  • INNER JOIN, LEFT JOIN, RIGHT JOIN 的区别
  • 字节面试被问到“手机号存储选 Int 还是 String”!
  • 区块链技术促进算力生态发展的具体案例
  • Python 机器学习核心入门与实战进阶 Day 6 - 模型保存与加载(joblib / pickle)
  • 2025年Linux安装MySQL详细教程
  • mysql-笔记
  • 服务器经常出现蓝屏是什么原因导致的?如何排查和修复?
  • Nature子刊:EPFL-ANU团队实现晶格对称性编程手性,双通道光学加密动态范围创1.6新高
  • Element-Plus-全局自动引入图标组件,无需每次import
  • 集群与集群应用
  • 东南亚主播解决方案|东南亚 TikTok 直播专线:纯净住宅 IP 、直播不卡顿
  • Spring自动装配(xml)
  • 芯片之后,AI之争的下一个战场是能源?
  • 小架构step系列08:logback.xml的配置
  • 知识库中如何确实嵌入文本块大小?语义完整性与检索颗粒度的平衡机制
  • 聊一聊软件架构师
  • C++排序算法全解析(加强版)
  • 单调栈通关指南:从力扣 84 到力扣 42
  • 前端技术小结
  • Android Jetpack Compose状态管理与状态提升
  • linux安装CUDA
  • VM文件管理与Vi/vim操作
  • multicore和multithreading
  • 多模态交互HMI全解析:语音、手势、眼动追踪的集成方案
  • rocketmq 刷盘机制 与同步机制区别
  • JavaScript之数组方法详解
  • VSYNC 深度解析
  • Apollo源码架构解析---附C++代码设计示例