Three.js 粒子线教程
粒子线 ·Wire· ▶ 在线运行案例案例合集三维可视化功能案例threehub.cn开源仓库github地址https://github.com/z2586300277/three-cesium-examples400个案例代码:网盘链接你将学到什么ShaderMaterial 自定义着色器实现核心视觉效果THREE.Points 粒子点渲染BufferGeometry 自定义顶点/索引数据requestAnimationFrame渲染循环与resize自适应效果说明本案例演示粒子线效果基于 WebGL 实现「粒子线」可视化效果附完整可运行源码核心用到 ShaderMaterial、THREE.Points、BufferGeometry。建议先打开文首在线案例查看动态画面再对照下方源码逐步理解。核心概念Scene / Camera / WebGLRenderer构成最小渲染闭环大场景可开logarithmicDepthBuffer缓解 Z-fighting。ShaderMaterial通过uniforms 自定义 GLSL 控制逐像素/逐点效果透明粒子常配合depthTest: false。THREE.Points将每个顶点渲染为可控大小的粒子可用自定义 attribute如u_index驱动片元/顶点动画。实现步骤搭建 Scene、PerspectiveCamera、WebGLRenderer挂载 canvas 并处理resize定义 uniforms / onBeforeCompile 或 ShaderMaterial编写 GLSL 与材质参数在requestAnimationFrame循环中更新状态并 renderCesium 为viewer.render或自动渲染代码要点import * as THREE from threeconst container document.getElementById(box);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);container.appendChild(renderer.domElement);const particlesGeometry new THREE.BufferGeometry();const particleCount 300;const posArray new Float32Array(particleCount * 3);const velocityArray new Float32Array(particleCount * 3);for (let i 0; i particleCount * 3; i) { posArray[i] (Math.random() - 0.5)8; velocityArray[i] (Math.random() - 0.5)0.02;}particlesGeometry.setAttribute(position, new THREE.BufferAttribute(posArray, 3));particlesGeometry.setAttribute(velocity, new THREE.BufferAttribute(velocityArray, 3));const particleMaterial new THREE.ShaderMaterial({ vertexShader:uniform float uTime; uniform vec2 uMouse; attribute vec3 velocity; varying vec3 vPosition; varying float vDistance; void main() { vPosition position; vec3 pos position; float dist length(pos.xy - uMouse); float influence 1.0 - clamp(dist / 2.0, 0.0, 1.0); pos.xy uMouseinfluence0.1; pos velocitysin(uTime position.x2.0); pos.y sin(uTime0.5 position.x)0.2; vec4 mvPosition modelViewMatrix * vec4(pos, 1.0); vDistance influence; gl_PointSize mix(3.0, 8.0, influence) * (1.0 / -mvPosition.z); gl_Position projectionMatrix * mvPosition; }, fragmentShader:uniform float uTime; varying vec3 vPosition; varying float vDistance; void main() { float distanceToCenter length(gl_PointCoord - vec2(0.5)); if (distanceToCenter 0.5) discard; vec3 baseColor vec3(0.3, 0.6, 1.0); vec3 pulseColor vec3(1.0, 0.4, 0.8); vec3 color mix(baseColor, pulseColor, vDistance); color color 0.2 * sin(uTime vPosition.xyx vec3(0,2,4)); float alpha 1.0 - distanceToCenter * 2.0; alpha 0.8 0.2sin(uTime * 2.0); gl_FragColor vec4(color, alpha); }, uniforms: { uTime: { value: 0 }, uMouse: { value: new THREE.Vector2(0, 0) } }, transparent: true, blending: THREE.AdditiveBlending });const particleSystem new THREE.Points(particlesGeometry, particleMaterial); scene.add(particleSystem);const linesMaterial new THREE.ShaderMaterial({ vertexShader:uniform float uTime; uniform vec2 uMouse; varying vec3 vPosition; varying float vDistance; void main() { vPosition position; vec3 pos position; float dist length(pos.xy - uMouse); float influence 1.0 - clamp(dist / 2.0, 0.0, 1.0); pos.xy uMouseinfluence0.1; pos.y sin(uTime0.5 position.x)0.2; vDistance influence; gl_Position projectionMatrixmodelViewMatrixvec4(pos, 1.0); }, fragmentShader:uniform float uTime; varying vec3 vPosition; varying float vDistance; void main() { vec3 baseColor vec3(0.3, 0.6, 1.0); vec3 pulseColor vec3(1.0, 0.4, 0.8); vec3 color mix(baseColor, pulseColor, vDistance); color color 0.2 * sin(uTime vPosition.xyx vec3(0,2,4)); float alpha 0.15 0.1 * vDistance; alpha 0.8 0.2sin(uTime * 2.0); gl_FragColor vec4(color, alpha); }, uniforms: { uTime: { value: 0 }, uMouse: { value: new THREE.Vector2(0, 0) } }, transparent: true, blending: THREE.AdditiveBlending });const linesGeometry new THREE.BufferGeometry(); const linePositions []; for (let i 0; i particleCount; i) { for (let j i 1; j particleCount; j) { const dist Math.sqrt( Math.pow(posArray[i3] - posArray[j3], 2) Math.pow(posArray[i3 1] - posArray[j3 1], 2) ); if (dist 2) { linePositions.push( posArray[i3], posArray[i3 1], posArray[i * 3 2], posArray[j3], posArray[j3 1], posArray[j * 3 2] ); } } } linesGeometry.setAttribute(position, new THREE.Float32BufferAttribute(linePositions, 3));const lines new THREE.LineSegments(linesGeometry, linesMaterial);scene.add(lines);camera.position.z 5;const mouse new THREE.Vector2(); let isMouseDown false;function onMouseMove(event) { mouse.x (event.clientX / window.innerWidth)2 - 1; mouse.y -(event.clientY / window.innerHeight)2 1; particleMaterial.uniforms.uMouse.value mouse; linesMaterial.uniforms.uMouse.value mouse; }function onMouseDown() { isMouseDown true; }function onMouseUp() { isMouseDown false; }window.addEventListener(mousemove, onMouseMove);window.addEventListener(mousedown, onMouseDown);window.addEventListener(mouseup, onMouseUp);window.addEventListener(touchstart, () isMouseDown true);window.addEventListener(touchend, () isMouseDown false);function animate(timestamp) {requestAnimationFrame(animate); const time timestamp * 0.001;particleMaterial.uniforms.uTime.value time; linesMaterial.uniforms.uTime.value time;const positions particlesGeometry.attributes.position.array; const velocities particlesGeometry.attributes.velocity.array;for (let i 0; i positions.length; i 3) {if (isMouseDown) { velocities[i] (Math.random() - 0.5)0.001; velocities[i 1] (Math.random() - 0.5)0.001; }positions[i] velocities[i]; positions[i 1] velocities[i 1];if (Math.abs(positions[i]) 4) velocities[i] -0.9; if (Math.abs(positions[i 1]) 4) velocities[i 1] -0.9;}particlesGeometry.attributes.position.needsUpdate true;const linePositions linesGeometry.attributes.position.array; let lineIndex 0; for (let i 0; i particleCount; i) { for (let j i 1; j particleCount; j) { const dist Math.sqrt(Math.pow(positions[i3] - positions[j3], 2) Math.pow(positions[i3 1] - positions[j3 1], 2)); if (dist 2) { linePositions[lineIndex] positions[i3]; linePositions[lineIndex] positions[i3 1]; linePositions[lineIndex] positions[i3 2]; linePositions[lineIndex] positions[j3]; linePositions[lineIndex] positions[j3 1]; linePositions[lineIndex] positions[j3 2]; } } } linesGeometry.attributes.position.needsUpdate true;renderer.render(scene, camera); }function onWindowResize() { camera.aspect window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize(window.innerWidth, window.innerHeight);}window.addEventListener(resize, onWindowResize); animate(0);完整源码GitHub小结本文提供粒子线完整 Three.js 源码与在线 Demo建议先运行案例再改 uniform/参数做二次实验更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库

相关新闻

Twitter账号活跃度与搜索权重优化策略

Twitter账号活跃度与搜索权重优化策略

1. 社交平台流量分配的基本逻辑在讨论Twitter账号活跃度与搜索权重的关系前,我们需要先理解社交平台流量分配的基本机制。所有主流社交平台都采用类似的底层逻辑:平台需要平衡内容供给与用户需求,同时最大化用户停留时长和广告收益。平台算法…

2026/7/4 16:50:06阅读更多 →
大模型安全实战:从漏洞复现到防御体系构建

大模型安全实战:从漏洞复现到防御体系构建

1. 从“智能助手”到“安全靶场”:大模型安全为何成为新战场最近几年,大模型(Large Language Model, LLM)的浪潮席卷了几乎所有行业。从写代码、做PPT的智能助手,到分析数据、生成创意的超级大脑,它似乎无所…

2026/7/4 16:45:06阅读更多 →
Python+OpenCV实现轻量级人脸识别系统

Python+OpenCV实现轻量级人脸识别系统

1. 项目概述人脸识别作为计算机视觉领域最基础也最实用的技术之一,已经广泛应用于安防监控、手机解锁、支付验证等日常生活场景。这次我将分享一个基于OpenCV和Python的轻量级人脸识别实现方案,特别适合刚入门计算机视觉的开发者练手。这个项目不需要昂贵…

2026/7/4 16:45:06阅读更多 →
机器学习生产化:从模型部署到系统级稳定性实战指南

机器学习生产化:从模型部署到系统级稳定性实战指南

1. 项目概述:当模型走出笔记本,真正开始“呼吸”现实空气你有没有经历过这样的时刻?花了三个月时间调参、优化、交叉验证,AUC冲到0.92,特征重要性图漂亮得能当屏保,团队在周会上集体鼓掌,PM当场…

2026/7/4 17:55:14阅读更多 →
DayZ单机离线模式终极指南:5分钟开启完整免费生存体验

DayZ单机离线模式终极指南:5分钟开启完整免费生存体验

DayZ单机离线模式终极指南:5分钟开启完整免费生存体验 【免费下载链接】DayZCommunityOfflineMode A community made offline mod for DayZ Standalone 项目地址: https://gitcode.com/gh_mirrors/da/DayZCommunityOfflineMode 想要在DayZ中享受无网络延迟、…

2026/7/4 17:55:14阅读更多 →
彻底告别网络依赖:DBeaver驱动包一键配置终极指南

彻底告别网络依赖:DBeaver驱动包一键配置终极指南

彻底告别网络依赖:DBeaver驱动包一键配置终极指南 【免费下载链接】dbeaver-driver-all dbeaver所有jdbc驱动都在这,dbeaver all jdbc drivers ,come and download with me , one package come with all jdbc drivers. 项目地址: https://gitcode.com/…

2026/7/4 17:55:14阅读更多 →
AI Agent安全架构对比:从OpenClaw静态工具箱到HermesAgent动态学徒的防御演进

AI Agent安全架构对比:从OpenClaw静态工具箱到HermesAgent动态学徒的防御演进

1. 项目概述:当AI学会“行动”,安全边界如何重绘?最近在AI Agent的圈子里,OpenClaw和HermesAgent的对比讨论热度一直没降下来。从去年OpenClaw掀起“全民养虾”的热潮,到今年HermesAgent以“自进化执行体”的姿态迅速崛…

2026/7/4 17:55:14阅读更多 →
简单快速免费:如何用SRWE突破游戏窗口限制实现分辨率自由?

简单快速免费:如何用SRWE突破游戏窗口限制实现分辨率自由?

简单快速免费:如何用SRWE突破游戏窗口限制实现分辨率自由? 【免费下载链接】SRWE Simple Runtime Window Editor 项目地址: https://gitcode.com/gh_mirrors/sr/SRWE 你是否曾经为了截取完美的游戏画面而烦恼?是否需要在不同设备上测试…

2026/7/4 17:55:14阅读更多 →
终极SMAPI安装指南:快速掌握星露谷物语模组API的完整教程

终极SMAPI安装指南:快速掌握星露谷物语模组API的完整教程

终极SMAPI安装指南:快速掌握星露谷物语模组API的完整教程 【免费下载链接】SMAPI The modding API for Stardew Valley. 项目地址: https://gitcode.com/gh_mirrors/smap/SMAPI SMAPI(Stardew Valley Modding API)是星露谷物语的官方模…

2026/7/4 17:50:14阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月,Boris Cherny 公开宣布自己卸载了 IDE。一时间,Vibe Coding 成了全行业最热的话题。6个月后,当我们回过头来拉一份真实账本,发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/7/4 14:25:39阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言:审计结束三个月了,审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间,内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中,审计…

2026/7/4 14:57:00阅读更多 →
端到端自动驾驶:从GTC‘26看工程可信落地的核心逻辑

端到端自动驾驶:从GTC‘26看工程可信落地的核心逻辑

1. 项目概述:当算法工程师走进GTC26展厅,看到的不是芯片,而是“端到端”的呼吸节奏“端到端”这三个字,在GTC’26现场出现的频率,高得像NVLink带宽测试时的峰值曲线——它不再是一个论文里的技术路径选项,而…

2026/7/4 0:02:48阅读更多 →
缺牙修复科普:常见义齿类型与选择参考

缺牙修复科普:常见义齿类型与选择参考

缺牙修复科普:常见义齿类型与选择参考牙齿缺失是中老年人群中较为常见的口腔问题,不仅会造成咀嚼不便、进食受影响,长期还可能对营养摄入与日常社交带来困扰。义齿是改善缺牙问题的常用方式,目前市面上的义齿种类较多,…

2026/7/4 0:02:48阅读更多 →
STM32F091RC与LTC6904实现高精度方波信号生成

STM32F091RC与LTC6904实现高精度方波信号生成

1. 项目概述:LTC6904与STM32F091RC的精准方波生成方案在嵌入式系统开发中,精确的时钟信号和定时控制往往是项目成败的关键。LTC6904作为一款低功耗、高精度的可编程振荡器芯片,与STM32F091RC这款ARM Cortex-M0内核微控制器的组合,…

2026/7/4 0:02:48阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/4 1:16:56阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/4 2:33:55阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/4 2:33:55阅读更多 →