1-前言
小编刷着公众号,发现我喜欢的博主发表了一篇手势操控3d粒子动画的文章,立马跟着去试了一下,发现确实挺不错的,也是开始研究其源码来了。
2-Github地址
stark-shapes Github 地址:https://github.com/collidingScopes/stark-shapes/tree/main
stark-shapes 在线体验地址:https://collidingscopes.github.io/stark-shapes/
3-项目运行
HTTP:git clone https://github.com/collidingScopes/stark-shapes.git
SSH:·git clone git@github.com:collidingScopes/stark-shapes.git
然后cd stark-shapes
然后运行npx --yes http-server .
发现启动成功了,就可以去玩啦。
4-项目特点
-
手势控制
- 右手:通过捏合手势实现缩放控制
- 左手:通过旋转手势实现相机轨道控制
- 双手拍手:切换到下一个几何图案
-
丰富的几何图案
- 基础形状:立方体、球体
- 数学曲线:螺旋线、螺旋桨
- 复杂形状:星系、莫比乌斯带、克莱因瓶
- 自然形态:花朵、分形树
- 数学图案:Voronoi图
-
视觉效果
- 平滑的图案过渡动画
- 粒子波动效果
- 动态颜色变化
- 景深效果
- 粒子发光效果
5-技术实现
核心技术栈
- Three.js:3D图形渲染
- MediaPipe:手势识别
- dat.GUI:调试界面
主要功能模块
-
粒子系统
- 使用BufferGeometry优化性能
- 支持15,000个粒子的实时渲染
- 实现粒子大小、颜色、透明度等属性的动态控制
-
相机控制
- 实现平滑的缩放过渡
- 支持水平和垂直方向的轨道控制
- 设置合理的视角限制,防止相机翻转
-
手势识别
- 实时检测左右手位置
- 计算手指捏合距离
- 识别拍手动作
- 平滑的手势响应
-
图案转换
- 支持14种不同的几何图案
- 实现平滑的形状过渡动画
- 颜色渐变效果
6-使用说明
-
环境要求
- 现代浏览器(支持WebGL)
- 摄像头权限(用于手势识别)
-
操作指南
- 允许浏览器访问摄像头
- 右手捏合控制缩放
- 左手旋转控制视角
- 双手拍手切换图案
-
调试面板
- 波动强度调节
- 过渡速度控制
- 粒子大小设置
- 手动切换图案
7-开发者说明
项目结构:
main.js
:主程序逻辑geometry.js
:几何图案生成chromatic-shader.js
:着色器效果index.html
:页面结构styles.css
:样式定义
www.instagram.com/stereo.drif…)
8- main.js 代码分析
核心功能模块
1. 手势控制系统
项目使用 MediaPipe 实现手势识别,主要变量包括:
let hands;
let handDetected = false;
let isLeftHandPresent = false;
let isRightHandPresent = false;
let leftHandLandmarks = null;
let rightHandLandmarks = null;
手势控制功能:
- 右手捏合手势:控制场景缩放
- 左手旋转:控制相机轨道运动
- 双手拍手:切换几何图案
2. 相机控制系统
相机系统实现了平滑的缩放和旋转效果:
// 相机缩放参数
let targetCameraZ = 100;
const MIN_CAMERA_Z = 20;
const MAX_CAMERA_Z = 200;
// 相机旋转参数
let targetCameraAngleX = 0;
let currentCameraAngleX = 0;
let targetCameraAngleY = 0;
let currentCameraAngleY = 0;
3. 粒子系统
粒子系统是项目的核心视觉元素:
const params = {
particleCount: 15000,
transitionSpeed: 0.005,
waveIntensity: 0.0,
particleSize: 0.5
};
主要特点:
- 支持 15000 个粒子的渲染
- 实现了平滑的粒子过渡动画
- 包含波浪效果动画
- 使用 Three.js 的 PointsMaterial 实现粒子渲染
4. 几何图案系统
项目支持多种几何图案:
const patterns = [
createGrid, createSphere, createSpiral,
createHelix, createTorus, createVortex,
createGalaxy, createWave, createMobius,
createSupernova, createKleinBottle,
createFlower, createVoronoi, createFractalTree
];
5. 颜色系统
项目定义了多组颜色配置:
const colorPalettes = [
[ new THREE.Color(0x3399ff), new THREE.Color(0x44ccff), new THREE.Color(0x0055cc) ],
[ new THREE.Color(0xff3399), new THREE.Color(0xcc00ff), new THREE.Color(0x660099) ],
// ... 更多颜色配置
];
9-Geometry.js 代码分析
Geometry.js 文件包含了多个几何图案生成函数,用于创建不同的3D粒子分布模式。每个函数都通过数学算法精确控制粒子在三维空间中的分布,实现了丰富的视觉效果。
主要函数
1. createGrid(i, count)
- 创建立方体网格结构
- 将粒子均匀分布在立方体的六个面上
- 参数:
- i: 当前粒子索引
- count: 总粒子数
- 实现细节:
- 计算立方体边长和间距
- 将粒子均匀分布在六个面上
- 每个面的粒子按照二维网格排列
2. createSphere(i, count)
- 生成球形分布
- 使用球面坐标系实现均匀分布
- 特点:
- 使用黄金分割比进行分布优化
- 固定半径的表面分布
3. createSpiral(i, count)
- 创建螺旋形状
- 特点:
- 支持多臂螺旋(默认3臂)
- 使用数学公式控制螺旋展开角度
- 粒子沿螺旋线均匀分布
4. createHelix(i, count)
- 生成双螺旋结构
- 特点:
- 两条平行螺旋线
- 可调节螺旋半径和高度
- 粒子均匀分布在螺旋线上
5. createTorus(i, count)
- 创建圆环体
- 参数控制:
- 主半径:圆环中心到管壁中心的距离
- 次半径:管壁的半径
- 使用参数方程实现均匀分布
6. createVortex(i, count)
- 生成漩涡效果
- 特点:
- 从底部到顶部逐渐扩大的半径
- 可控制旋转圈数
- 添加随机偏移实现自然效果
7. createGalaxy(i, count)
- 创建星系形态
- 特点:
- 支持多条旋臂(默认4臂)
- 扭曲因子控制旋臂弯曲程度
- 垂直方向的厚度随距离变化
- 包含随机偏移实现自然分布
8. createWave(i, count)
- 生成波浪效果
- 特点:
- 二维平面上的波动分布
- 可调节波浪高度和密度
- 支持多重波叠加
技术特点
- 使用Three.js的Vector3对象表示三维坐标
- 通过数学公式精确控制粒子分布
- 支持参数化调节几何形状
- 添加随机性实现自然效果
- 优化的粒子分布算法确保视觉效果
使用方式
每个函数都接收两个参数:
- i: 当前粒子的索引
- count: 总粒子数量
返回值:
- 返回THREE.Vector3对象,表示粒子的三维坐标
9-Chromatic Shader 代码分析
Chromatic-shader.js 实现了色差(色像差)后期处理效果,这是一种模拟相机镜头色差的视觉效果,使图像的RGB通道产生细微的位移,创造出独特的视觉效果。
核心组件
1. 着色器配置
const ChromaticAberrationShader = {
uniforms: {
"tDiffuse": { value: null },
"resolution": { value: new THREE.Vector2(1, 1) },
"strength": { value: 0.5 }
}
// ...
}
tDiffuse
: 输入纹理,存储渲染的场景resolution
: 屏幕分辨率strength
: 色差效果强度
2. 顶点着色器
vertexShader: /* glsl */`
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`
- 实现基础的顶点变换
- 传递UV坐标到片段着色器
3. 片段着色器
fragmentShader: /* glsl */`
uniform sampler2D tDiffuse;
uniform vec2 resolution;
uniform float strength;
varying vec2 vUv;
void main() {
// 计算到中心的距离
vec2 uv = vUv - 0.5;
float dist = length(uv);
// 平滑过渡
float factor = smoothstep(0.0, 0.4, dist);
// 计算偏移
vec2 direction = normalize(uv);
vec2 redOffset = direction * strength * factor * dist;
vec2 greenOffset = direction * strength * 0.6 * factor * dist;
vec2 blueOffset = direction * strength * 0.3 * factor * dist;
// 采样各个颜色通道
float r = texture2D(tDiffuse, vUv - redOffset).r;
float g = texture2D(tDiffuse, vUv - greenOffset).g;
float b = texture2D(tDiffuse, vUv - blueOffset).b;
gl_FragColor = vec4(r, g, b, 1.0);
}
`
实现细节
1. 距离计算
- 计算每个像素到屏幕中心的距离
- 使用该距离来控制色差效果的强度
2. 平滑过渡
- 使用smoothstep实现从中心到边缘的平滑过渡
- 中心区域保持清晰,边缘区域色差效果更强
3. 颜色通道偏移
- 红色通道:最大偏移
- 绿色通道:中等偏移(0.6倍)
- 蓝色通道:最小偏移(0.3倍)
使用效果
- 在场景边缘产生RGB通道分离效果
- 中心区域保持清晰
- 可通过strength参数调节效果强度
性能考虑
- 使用向量运算优化性能
- 避免复杂的数学计算
- 使用smoothstep实现平滑过渡,避免硬边界