Three.js 蒸汽粒子教程

发布时间:2026/8/27 12:38:01

Three.js 蒸汽粒子教程
蒸汽粒子 ·Steam Particle· ▶ 在线运行案例案例合集三维可视化功能案例threehub.cn开源仓库github地址https://github.com/z2586300277/three-cesium-examples400个案例代码:网盘链接你将学到什么ShaderMaterial 自定义着色器实现核心视觉效果OrbitControls 相机轨道交互THREE.Points 粒子点渲染BufferGeometry 自定义顶点/索引数据requestAnimationFrame渲染循环与resize自适应效果说明本案例演示蒸汽粒子效果基于 WebGL 实现「蒸汽粒子」可视化效果附完整可运行源码核心用到 ShaderMaterial、OrbitControls、THREE.Points。建议先打开文首在线案例查看动态画面再对照下方源码逐步理解。核心概念Scene / Camera / WebGLRenderer构成最小渲染闭环大场景可开logarithmicDepthBuffer缓解 Z-fighting。ShaderMaterial通过uniforms 自定义 GLSL 控制逐像素/逐点效果透明粒子常配合depthTest: false。OrbitControls提供轨道旋转/缩放开启enableDamping后需在 animate 中controls.update()。THREE.Points将每个顶点渲染为可控大小的粒子可用自定义 attribute如u_index驱动片元/顶点动画。实现步骤搭建 Scene、PerspectiveCamera、WebGLRenderer挂载 canvas 并处理resize定义 uniforms / onBeforeCompile 或 ShaderMaterial编写 GLSL 与材质参数创建 OrbitControls及 Raycaster 等交互控件若源码包含在requestAnimationFrame循环中更新状态并 renderCesium 为viewer.render或自动渲染代码要点import * as THREE from threeimport { OrbitControls } from three/examples/jsm/controls/OrbitControls.js import { GUI } from dat.gui// 初始化场景 const box document.getElementById(box) const scene new THREE.Scene() scene.background new THREE.Color(0x445566)const camera new THREE.PerspectiveCamera(50, box.clientWidth / box.clientHeight, 0.1, 1000) camera.position.set(0, 8, 20)// 设置渲染器 const renderer new THREE.WebGLRenderer({ antialias: true, alpha: true }) renderer.setSize(box.clientWidth, box.clientHeight) box.appendChild(renderer.domElement)// 轨道控制器 const controls new OrbitControls(camera, renderer.domElement) controls.enableDamping truescene.add(new THREE.AmbientLight(0xffffff, 0.5))// 可配置参数 const config { particleCount: 3000, particleSize: 1.2, width: 12, depth: 2, height: 15, riseSpeed: 0.4, spread: 0.3, turbulence: 0.3, density: 0.4, }const uniforms { time: { value: 0 }, baseColor: { value: new THREE.Color(0xffffff) }, height: { value: config.height }, turbulence: { value: config.turbulence }, density: { value: config.density }, }const material new THREE.ShaderMaterial({ uniforms, vertexShader:attribute float size; attribute float phase; attribute vec3 velocity; uniform float time; uniform float height; uniform float turbulence; varying float vAlpha; varying float vAge; void main() { float age mod(time * 0.3 phase, 1.0); vAge age; vec3 pos position velocityageheight; pos.x sin(age8.0 phase20.0)turbulence(0.5 age); pos.z cos(age6.0 phase15.0)turbulence(0.3 age * 0.5); pos.x (1.0 age1.5); pos.z (1.0 age0.8); vec4 mvPosition modelViewMatrix * vec4(pos, 1.0); gl_Position projectionMatrix * mvPosition; gl_PointSize size(1.0 age3.0) * (250.0 / -mvPosition.z); float fadeIn smoothstep(0.0, 0.1, age); float fadeOut 1.0 - smoothstep(0.6, 1.0, age); vAlpha fadeIn * fadeOut; }, fragmentShader:uniform vec3 baseColor; uniform float density; varying float vAlpha; varying float vAge; void main() { float dist length(gl_PointCoord - 0.5) * 2.0; if (dist 1.0) discard; float edge 1.0 - smoothstep(0.3, 1.0, dist); vec3 color mix(baseColor, vec3(0.85, 0.88, 0.92), vAge * 0.3); gl_FragColor vec4(color, vAlphaedgedensity); }, blending: THREE.NormalBlending, depthWrite: false, transparent: true, })function buildGeometry() { const geo new THREE.BufferGeometry() const positions [], sizes [], phases [], velocities [] for (let i 0; i config.particleCount; i) { positions.push( (Math.random() - 0.5) * config.width, Math.random() * 0.3, (Math.random() - 0.5) * config.depth ) sizes.push(config.particleSize(0.6 Math.random()0.8)) phases.push(Math.random()) velocities.push( (Math.random() - 0.5) * config.spread, config.riseSpeed(0.8 Math.random()0.4), (Math.random() - 0.5)config.spread0.5 ) } geo.setAttribute(position, new THREE.Float32BufferAttribute(positions, 3)) geo.setAttribute(size, new THREE.Float32BufferAttribute(sizes, 1)) geo.setAttribute(phase, new THREE.Float32BufferAttribute(phases, 1)) geo.setAttribute(velocity, new THREE.Float32BufferAttribute(velocities, 3)) return geo }const steam new THREE.Points(buildGeometry(), material) scene.add(steam)// GUI const gui new GUI() gui.add(config, height, 5, 30).name(上升高度).onChange(v uniforms.height.value v) gui.add(config, turbulence, 0, 1).name(湍流强度).onChange(v uniforms.turbulence.value v) gui.add(config, density, 0.1, 1).name(浓度).onChange(v uniforms.density.value v) gui.add(config, width, 1, 20).name(喷口宽度).onChange(() { steam.geometry.dispose(); steam.geometry buildGeometry() }) gui.add(config, depth, 0.5, 10).name(喷口深度).onChange(() { steam.geometry.dispose(); steam.geometry buildGeometry() }) gui.add(config, riseSpeed, 0.1, 1).name(上升速度).onChange(() { steam.geometry.dispose(); steam.geometry buildGeometry() }) gui.add(config, particleCount, 500, 8000, 500).name(粒子数量).onChange(() { steam.geometry.dispose(); steam.geometry buildGeometry() }) gui.add(config, particleSize, 0.3, 3).name(粒子大小).onChange(() { steam.geometry.dispose(); steam.geometry buildGeometry() }) gui.addColor({ color: #ffffff }, color).name(蒸汽颜色).onChange(v uniforms.baseColor.value.set(v))// 动画 const clock new THREE.Clock()function animate() { requestAnimationFrame(animate) uniforms.time.value clock.getElapsedTime() controls.update() renderer.render(scene, camera) }animate()window.onresize () { renderer.setSize(box.clientWidth, box.clientHeight) camera.aspect box.clientWidth / box.clientHeight camera.updateProjectionMatrix() }完整源码GitHub小结本文提供蒸汽粒子完整 Three.js 源码与在线 Demo建议先运行案例再改 uniform/参数做二次实验更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库

相关新闻

如何从‘能聊天’升级到‘让别人愿意主动找你聊’的系统?

如何从‘能聊天’升级到‘让别人愿意主动找你聊’的系统?

2026/8/27 1:08:10

一、第一刀:为什么大多数人只能“能聊天”,不能“被找聊”? 因为他们停留在:被动对话系统✔ 特征: 别人发起你回应你维持但不会“积累吸引力”👉 本质:只是“对话节点”,不是“对话源…

高效电机驱动方案:TC78H660FTG与STM32G071RB实战解析

高效电机驱动方案:TC78H660FTG与STM32G071RB实战解析

2026/8/26 19:35:39

1. 项目背景与核心器件选型在工业自动化和消费电子领域,电机驱动系统的效率提升一直是工程师们关注的焦点。最近我在一个AGV小车项目中,需要设计一套兼顾性能和功耗的驱动方案,最终选择了东芝的TC78H660FTG电机驱动芯片搭配ST的STM32G071RB微…

深度学习图像识别实战:从CNN原理到PyTorch实现

深度学习图像识别实战:从CNN原理到PyTorch实现

2026/8/27 10:57:07

1. 项目概述:深度学习驱动的图像识别实战作为一名长期混迹在计算机视觉领域的从业者,我完整参与了李哥深度学习班的图像识别课程。这个系列课程最打动我的地方在于:它用工业级的代码标准教会学员如何从零搭建可落地的图像识别系统。不同于市面…

halcon之第4讲--亚像素以及相应算子学习

halcon之第4讲--亚像素以及相应算子学习

2026/8/27 12:37:59

文章目录前言亚像素(XLD)介绍生成XLD的常用算子edges_sub_pixthreshold_sub_pixgen_contour_region_xld筛选、分割、拼接轮廓select_contours_xldsegment_contours_xldsplit_contours_xld拟合常用算子fit_line_contour_xldfit_circle_contour_xld算子fit…

Python构建AI股票分析系统:从数据获取到策略回测全流程详解

Python构建AI股票分析系统:从数据获取到策略回测全流程详解

2026/8/27 12:37:59

简介:机器学习与深度学习作为人工智能的核心技术,通过从数据中自动学习模式与规律,为复杂决策提供支持。其原理在于利用算法构建模型,对历史数据进行训练,从而实现对未知数据的预测或分类。在金融科技领域,…

回归分析实战指南:从线性回归到Cox模型,掌握数据建模核心

回归分析实战指南:从线性回归到Cox模型,掌握数据建模核心

2026/8/27 12:37:59

1. 从“相关性”到“因果性”的桥梁:回归分析到底是什么?如果你在数据分析、金融风控、市场研究甚至生物统计领域工作过,那么“回归分析”这个词你肯定不陌生。它可能是你工具箱里最常用,但也最容易用错的一把“瑞士军刀”。很多人…

基于大数据的专业智能导学系统的设计与实现(毕业设计项目源码+文档)

基于大数据的专业智能导学系统的设计与实现(毕业设计项目源码+文档)

2026/8/27 12:37:59

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

LVD+CFCR:线性调频信号参数估计的工程实战指南

LVD+CFCR:线性调频信号参数估计的工程实战指南

2026/8/27 12:37:59

简介:在雷达、声呐与振动分析等工程领域,线性调频(Chirp)信号的频率随时间线性变化,精确估计其中心频率与调频斜率是关键任务。传统短时傅里叶变换受窗长限制分辨率不足,Wigner-Ville分布则易受交叉项干扰。…

从蓝桥杯真题解析“车的放置”:组合数学与回溯算法的实战应用

从蓝桥杯真题解析“车的放置”:组合数学与回溯算法的实战应用

2026/8/27 12:27:58

1. 项目概述:从一道蓝桥杯真题看“车的放置”问题最近在整理蓝桥杯的备赛资料,翻到了ALGO-996这道题——“车的放置”。这题目名字听起来平平无奇,不就是国际象棋里“车”(Rook)的摆放问题吗?但真正上手去解…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/27 11:10:02

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/27 7:25:23

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/26 17:50:58

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

Go语言构建企业级AI服务网关:统一管理英伟达等AI接口调用

Go语言构建企业级AI服务网关:统一管理英伟达等AI接口调用

2026/8/27 0:07:12

1. 项目概述:从零构建一个企业级的AI服务网关 最近在帮一个做内容审核的团队做技术架构升级,他们原来的业务里,每天有几十万张图片和短视频需要过审,最初是接了几个开源的AI模型自己部署,但效果和性能一直不太稳定。后…

LeetCode Hot100(51-60)算法精解与面试技巧

LeetCode Hot100(51-60)算法精解与面试技巧

2026/8/27 0:07:12

1. 题目背景与核心价值"hot100(51-60)"这个标题看起来像是某个编程题库或算法练习集中的一组题目编号。在技术社区中,类似命名通常指向LeetCode、牛客网等平台的热门题目集合。作为刷过300题的算法老手,我理解这类题目的核心价值在于&#xff…

CRC校验实战:从模2除法到HJ212协议排错

CRC校验实战:从模2除法到HJ212协议排错

2026/8/27 0:07:12

1. 为什么一个“校验码”能扛住工业现场90%的数据 corruption? 你有没有遇到过这样的场景:嵌入式设备通过RS-485上传温湿度数据,上位机偶尔收到一帧乱码——温度显示成-273℃,湿度跳到999%,但串口波形看起来完全正常&a…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/22 2:02:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/26 18:07:30

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/26 17:57:52

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…