首页/新闻资讯/正文详情

Three.js 粒子星空教程

发布时间:2026/9/24 10:43:19 来源:云帆数科 栏目:资讯中心
Three.js 粒子星空教程
粒子星空 ·Starry Sky· ▶ 在线运行案例案例合集三维可视化功能案例threehub.cn开源仓库github地址https://github.com/z2586300277/three-cesium-examples400个案例代码:网盘链接你将学到什么ShaderMaterial 自定义着色器实现核心视觉效果OrbitControls 相机轨道交互requestAnimationFrame渲染循环与resize自适应效果说明本案例演示粒子星空效果基于 WebGL 实现「粒子星空」可视化效果附完整可运行源码核心用到 ShaderMaterial、OrbitControls。建议先打开文首在线案例查看动态画面再对照下方源码逐步理解。核心概念Scene / Camera / WebGLRenderer构成最小渲染闭环大场景可开logarithmicDepthBuffer缓解 Z-fighting。ShaderMaterial通过uniforms 自定义 GLSL 控制逐像素/逐点效果透明粒子常配合depthTest: false。OrbitControls提供轨道旋转/缩放开启enableDamping后需在 animate 中controls.update()。实现步骤搭建 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.jsconst box document.getElementById(box)const scene new THREE.Scene()const camera new THREE.PerspectiveCamera(75, box.clientWidth / box.clientHeight, 0.1, 1000)camera.position.set(0, 0, 0.6)const renderer new THREE.WebGLRenderer({ antialias: true, alpha: true, logarithmicDepthBuffer: true })renderer.setSize(box.clientWidth, box.clientHeight)box.appendChild(renderer.domElement)const controls new OrbitControls(camera, renderer.domElement)controls.enableDamping truewindow.onresize () {renderer.setSize(box.clientWidth, box.clientHeight)camera.aspect box.clientWidth / box.clientHeightcamera.updateProjectionMatrix()}const uniforms {iTime: {value: 0},iResolution: {value: new THREE.Vector2(box.clientWidth, box.clientHeight)}}const geometry new THREE.PlaneGeometry(1, 1)const material new THREE.ShaderMaterial({uniforms,transparent: true,side: THREE.DoubleSide,vertexShader:varying vec3 vPosition; varying vec2 vUv; void main() { vUv uv; vec4 mvPosition modelViewMatrix * vec4(position, 1.0); gl_Position projectionMatrix * mvPosition; }, fragmentShader:uniform float iTime; uniform vec2 iResolution; varying vec2 vUv;#define PASS_COUNT 1 vec4 iMouse vec4(.0, 0, 0.2, 0); float fBrightness 2.5;// Number of angular segments float fSteps 121.0;float fParticleSize 0.015; float fParticleLength 0.5 / 60.0;// Min and Max star position radius. Min must be present to prevent stars too near camera float fMinDist 0.8; float fMaxDist 5.0;float fRepeatMin 1.0; float fRepeatMax 2.0;// fog density float fDepthFade 0.8;float Random(float x) { return fract(sin(x123.456)23.4567 sin(x345.678)45.6789 sin(x456.789)56.789); }vec3 GetParticleColour( const in vec3 vParticlePos, const in float fParticleSize, const in vec3 vRayDir ) { vec2 vNormDir normalize(vRayDir.xy); float d1 dot(vParticlePos.xy, vNormDir.xy) / length(vRayDir.xy); vec3 vClosest2d vRayDir * d1;vec3 vClampedPos vParticlePos;vClampedPos.z clamp(vClosest2d.z, vParticlePos.z - fParticleLength, vParticlePos.z fParticleLength);float d dot(vClampedPos, vRayDir);vec3 vClosestPos vRayDir * d;vec3 vDeltaPos vClampedPos - vClosestPos; float fClosestDist length(vDeltaPos) / fParticleSize;float fShade clamp(1.0 - fClosestDist, 0.0, 1.0); fShade fShadeexp2(-dfDepthFade) * fBrightness;return vec3(fShade); }vec3 GetParticlePos( const in vec3 vRayDir, const in float fZPos, const in float fSeed ) { float fAngle atan(vRayDir.x, vRayDir.y); float fAngleFraction fract(fAngle / (3.14 * 2.0));float fSegment floor(fAngleFraction * fSteps fSeed) 0.5 - fSeed; float fParticleAngle fSegment / fSteps(3.142.0);float fSegmentPos fSegment / fSteps; float fRadius fMinDist Random(fSegmentPos fSeed) * (fMaxDist - fMinDist);float tunnelZ vRayDir.z / length(vRayDir.xy / fRadius);tunnelZ fZPos;float fRepeat fRepeatMin Random(fSegmentPos 0.1 fSeed) * (fRepeatMax - fRepeatMin);float fParticleZ (ceil(tunnelZ / fRepeat) - 0.5) * fRepeat - fZPos;return vec3( sin(fParticleAngle)fRadius, cos(fParticleAngle)fRadius, fParticleZ ); }vec3 Starfield( const in vec3 vRayDir, const in float fZPos, const in float fSeed ) { vec3 vParticlePos GetParticlePos(vRayDir, fZPos, fSeed);return GetParticleColour(vParticlePos, fParticleSize, vRayDir); }vec3 RotateX( const in vec3 vPos, const in float fAngle ) { float s sin(fAngle); float c cos(fAngle);vec3 vResult vec3( vPos.x, cvPos.y svPos.z, -svPos.y cvPos.z);return vResult; }vec3 RotateY( const in vec3 vPos, const in float fAngle ) { float s sin(fAngle); float c cos(fAngle);vec3 vResult vec3( cvPos.x svPos.z, vPos.y, -svPos.x cvPos.z);return vResult; }vec3 RotateZ( const in vec3 vPos, const in float fAngle ) { float s sin(fAngle); float c cos(fAngle);vec3 vResult vec3( cvPos.x svPos.y, -svPos.x cvPos.y, vPos.z);return vResult; }void mainVR( out vec4 fragColor, in vec2 fragCoord, vec3 vRayOrigin, vec3 vRayDir ) { /* vec2 vScreenUV fragCoord.xy / iResolution.xy;vec2 vScreenPos vScreenUV * 2.0 - 1.0; vScreenPos.x * iResolution.x / iResolution.y;vec3 vRayDir normalize(vec3(vScreenPos, 1.0));vec3 vEuler vec3(0.5 sin(iTime0.2)0.125, 0.5 sin(iTime0.1)0.125, iTime0.1 sin(iTime0.3) * 0.5); if(iMouse.z 0.0) { vEuler.x -((iMouse.y / iResolution.y) * 2.0 - 1.0); vEuler.y -((iMouse.x / iResolution.x) * 2.0 - 1.0); vEuler.z 0.0; } vRayDir RotateX(vRayDir, vEuler.x); vRayDir RotateY(vRayDir, vEuler.y); vRayDir RotateZ(vRayDir, vEuler.z); */ float fShade 0.0; float a 0.2; float b 10.0; float c 1.0; float fZPos 5.0 iTimec sin(iTimea) * b; float fSpeed c abcos(a * iTime);fParticleLength 0.25 * fSpeed / 60.0;float fSeed 0.0;vec3 vResult mix(vec3(0.005, 0.0, 0.01), vec3(0.01, 0.005, 0.0), vRayDir.y * 0.5 0.5);for(int i0; ifragColor vec4(sqrt(vResult),1.0); }void main(void) { vec2 vScreenUV (vUv - 0.5) * 10.0;vec2 vScreenPos vScreenUV * 2.0 - 1.0; vScreenPos.x * iResolution.x / iResolution.y;vec3 vRayDir normalize(vec3(vScreenPos, 1.0));vec3 vEuler vec3(0.5 sin(iTime0.2)0.125, 0.5 sin(iTime0.1)0.125, iTime0.1 sin(iTime0.3) * 0.5); if(iMouse.z 0.0) { vEuler.x -((iMouse.y / iResolution.y) * 2.0 - 1.0); vEuler.y -((iMouse.x / iResolution.x) * 2.0 - 1.0); vEuler.z 0.0; } vRayDir RotateX(vRayDir, vEuler.x); vRayDir RotateY(vRayDir, vEuler.y); vRayDir RotateZ(vRayDir, vEuler.z);float fShade 0.0; float a 0.2; float b 10.0; float c 1.0; float fZPos 5.0 iTimec sin(iTimea) * b; float fSpeed c abcos(a * iTime);fParticleLength 0.25 * fSpeed / 60.0;float fSeed 0.0;vec3 vResult mix(vec3(0.005, 0.0, 0.01), vec3(0.01, 0.005, 0.0), vRayDir.y * 0.5 0.5);for(int i0; igl_FragColor vec4(sqrt(vResult),1.0); }})const mesh new THREE.Mesh(geometry, material)scene.add(mesh)animate()function animate() {uniforms.iTime.value 0.01requestAnimationFrame(animate)controls.update()renderer.render(scene, camera)}完整源码GitHub小结本文提供粒子星空完整 Three.js 源码与在线 Demo建议先运行案例再改 uniform/参数做二次实验更多 Three.js 实战案例见 three-cesium-examples 合集 与 GitHub 开源仓库

相关推荐

聪明的小羊
聪明的小羊

一只小羊翻过了2个栅栏 fa{fe13f590lg6d46d0d0}考点:栅栏换位密码、杂项字符过滤。根据题目提示,是“栅栏密码”,又因为描述中有“2”,所以,key2. 使用在线工具: http://www.hiencode.com/railfence.html 得… · 2026/8/6 19:00:22

鸿蒙应用安全认证实战:基于HUKS密钥库的签名验签方案详解
鸿蒙应用安全认证实战:基于HUKS密钥库的签名验签方案详解

1. 项目概述与核心价值最近在搞鸿蒙应用开发,特别是涉及到用户身份认证这块,发现很多开发者对如何安全、合规地实现认证逻辑有点摸不着头脑。直接明文传输密码或者把密钥硬编码在代码里,这种操作在稍微有点安全要求的场景下基本等于“裸奔”。… · 2026/7/21 16:42:08

STM32F405RG驱动WS2812 LED的嵌入式开发实践
STM32F405RG驱动WS2812 LED的嵌入式开发实践

1. 项目概述:WS2812与STM32F405RG的完美组合在嵌入式开发领域,LED控制一直是个既基础又充满挑战的话题。而当我第一次将WS2812可编程LED与STM32F405RG这款高性能MCU搭配使用时,那种视觉效果的震撼至今难忘。这个组合不仅能实现绚丽的灯光效果… · 2026/9/13 13:04:45

SD NAND电平转换实战:STM32与1.8V器件信号完整性设计
SD NAND电平转换实战:STM32与1.8V器件信号完整性设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 10:43:07

掉帧先怪显卡?看看显卡驱动是不是还活在去年
掉帧先怪显卡?看看显卡驱动是不是还活在去年

事情源于一场排位赛。我操作拉满准备收五杀,画面突然卡成PPT,等恢复过来人已经躺在泉水里。队友打字:"兄弟你这闪现挂哪买的?"我百口莫辩。赛后看帧数曲线,团战时帧率从140直接腰斩到50,但我的显… · 2026/9/24 10:43:07

AI芯片选型:主频、TOPS、NPU与SoC全解析
AI芯片选型:主频、TOPS、NPU与SoC全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 10:42:55

Numba 0.59.1 版本解析:np.searchsorted 性能回归与 datetime64/NaT 修复、CUDA 内核缓存及 PEP-695 语法支持
Numba 0.59.1 版本解析:np.searchsorted 性能回归与 datetime64/NaT 修复、CUDA 内核缓存及 PEP-695 语法支持

编译器高性能计算 【免费下载链接】numba NumPy aware dynamic Python compiler using LLVM 项目地址: https://gitcode.com/gh_mirrors/nu/numba 点击查看 免费下载 导读 Numba 0.59.1 是紧随 0.59.0 发布的一个 bug-fix 版本,专门用于修复 0.59.0 引… · 2026/9/24 10:42:43

从Boson NetSim实验拆解VLAN与RIP配置:交换机互联与路由表验证
从Boson NetSim实验拆解VLAN与RIP配置:交换机互联与路由表验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 10:42:43

能源互联网统一接入平台:CPS架构下的多协议适配与设备协同实战
能源互联网统一接入平台:CPS架构下的多协议适配与设备协同实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/24 10:42:36

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码