作者:柳杉前端
标签:#Three.js #WebGL #开源项目 #游戏开发 #Shader特效
大家好,我是柳杉!今天给大家带来两个极具视觉冲击力的开源项目测评——一个是把经典台球游戏搬进太空的 Cosmic Pool,一个是用纯手写 Shader 打造的 Force Shield VFX。这两个项目分别代表了 WebGL 在游戏和视觉特效领域的巅峰玩法,无论你是想做游戏还是想学 Shader,都值得深入研究!
🎱 项目一:Cosmic Pool —— 太空台球美学巅峰
开源地址: github.com/lespuch-v/c…
项目简介
Cosmic Pool 是一款基于浏览器和 Three.js 的 8 球台球游戏原型。但别被"原型"二字骗了——它把传统台球桌搬进了浩瀚宇宙,用星球取代了普通球,整个视觉风格是太空奢华风 (Space-Luxury),看一眼就让人上头!
技术栈
| 技术 | 版本/说明 |
|---|---|
| 构建工具 | Vite |
| 语言 | TypeScript |
| 3D 引擎 | Three.js |
| 物理引擎 | 自定义台球物理系统 |
| 代码规范 | ESLint |
核心玩法测评
1. 拖拽式击球系统
// 核心交互逻辑:鼠标拖拽控制力度和方向
this.interactionController = new GameInteractionController({
mountElement: this.mountElement,
// 拖拽时实时计算力度
strikeCueBall: (direction, shotPower) =>
this.billiardsWorld.strikeCueBall(direction, shotPower),
// 精准瞄准模式(按住 Shift)
precisionAimEnabled: this.interactionController.isPrecisionAimEnabled(),
})
体验点评: 拖拽力度条的设计很直观,按住 Shift 进入精准模式时会降低鼠标灵敏度,这个细节非常贴心。整个击球手感流畅自然,球杆动画跟手性很强。
2. 太空主题视觉系统
项目最核心的亮点在于多层视觉叠加:
🌌 星空穹顶 (Cosmic Dome)
// 旋转的星空背景
this.cosmicDome.mesh.rotation.y += delta * 0.0012
⭐ 动态星场 (Starfield)
// 内外双层星场漂移效果
this.starfield.rotation.y += delta * GAME_CONFIG.environment.innerStarfield.driftSpeed.y
this.starfield.rotation.x = Math.sin(elapsedTime * 0.12) *
GAME_CONFIG.environment.innerStarfield.driftSpeed.x
🌠 银河系背景 (Milky Way)
台球桌本身也很讲究:
- 边缘线条带 Bloom 辉光效果
- 星球球体表面纹理精致(从截图看有类似木星、火星的纹理)
- 桌布采用深空色系,与环境融为一体
3. 物理引擎实现
项目没有使用现成的物理引擎,而是手写了一套台球物理系统:
// BilliardsWorld 核心类
export class BilliardsWorld {
// 球体碰撞检测
update(delta: number): void
// 球袋检测
consumeEvents(): BilliardsEvent[]
// 白球放置验证
previewCueBallPlacement(position: Vector2): boolean
}
包含的物理特性:
- 球与球的弹性碰撞
- 球与桌边的反弹
- 球袋判定(Pocket Detection)
- 白球自由放置(Cue Ball in Hand)
- 球体静止检测(Settled Detection)
4. AI 对战系统
CPU 对手的智能度可以调节(简单/普通/困难):
// CPU 决策流程
export interface CpuTurnState {
currentTurn: 'human' | 'cpu'
humanGroup: 'solids' | 'stripes' | null
cpuGroup: 'solids' | 'stripes' | null
}
// AI 找最佳击球路线
const bestShot = findBestShot(balls, rulesState, difficulty)
// 构建安全球策略
const safeShot = buildSafeShot(balls, rulesState)
AI 行为特点:
- 难度影响口袋容错率和瞄准精度
- 会主动寻找最佳进球路线
- 无法进攻时会尝试打安全球
- 思考时间模拟(1.2秒延迟)
5. 后处理特效管线
// Bloom 辉光效果实现
const BLOOM_LAYER = 1
// 星星和特效启用 Bloom 层
this.starfield.traverse((obj) => obj.layers.enable(BLOOM_LAYER))
// EffectComposer 管线
this.bloomComposer = new EffectComposer(renderer)
this.bloomComposer.addPass(new UnrealBloomPass(/* ... */))
this.bloomComposer.addPass(new SMAAPass(/* 抗锯齿 */))
特效分层处理:
- 先渲染需要 Bloom 的物体到单独层
- UnrealBloomPass 提取高亮部分
- SMAAPass 抗锯齿
- OutputPass 输出最终画面
项目架构亮点
src/
├── entities/ # 游戏实体(球、球桌)
├── environment/ # 环境(星空、银河)
├── gameplay/ # 游戏玩法逻辑
├── physics/ # 物理引擎
├── rules/ # 8球规则引擎
├── cpu/ # AI 逻辑
├── effects/ # 特效系统
├── audio/ # 音频管理
└── ui/ # HUD 控制器
设计模式亮点:
- 状态机模式:InteractionState 管理游戏流程
- 组件化设计:Ball、Table、CueStick 都是独立实体
- 观察者模式:BilliardsEvent 事件系统解耦物理与逻辑
可玩性评分
| 维度 | 评分 | 评价 |
|---|---|---|
| 视觉效果 | ⭐⭐⭐⭐⭐ | 太空主题执行得非常到位 |
| 操作手感 | ⭐⭐⭐⭐ | 流畅自然,精准模式加分 |
| 游戏性 | ⭐⭐⭐ | 基础规则完整,但内容较浅 |
| 代码质量 | ⭐⭐⭐⭐ | TypeScript + 模块化,结构清晰 |
| 学习价值 | ⭐⭐⭐⭐⭐ | 物理引擎实现值得学习 |
🛡️ 项目二:Force Shield VFX —— 电影级能量盾 Shader
开源地址: github.com/cortiz2894/…
项目简介
这是一个生产级品质的 WebGL 能量盾特效,用纯手写 GLSL Shader 实现。作者 Christian Ortiz 是创意开发领域的顶尖高手,这个项目被设计为学习资源和创作起点,代码注释详尽,架构优雅。
先看效果:
技术栈
| 技术 | 版本/说明 |
|---|---|
| 框架 | Next.js 16.1 (App Router) |
| 3D 引擎 | Three.js + React Three Fiber |
| Shader | 手写 GLSL (Vertex + Fragment) |
| 后处理 | @react-three/postprocessing |
| GUI 控制 | Leva |
| 样式 | Tailwind CSS 4 |
Shader 核心实现解析
1. 六边形网格 (Hex Grid)
能量盾最标志性的特征就是蜂窝状网格:
// 三平面投影 (Tri-planar Projection)
// 从三个轴向投影六边形纹理,避免球面 UV 变形
vec3 hexTriplanar(vec3 pos, vec3 normal, float scale) {
vec3 xPlane = hexGrid(pos.yz * scale);
vec3 yPlane = hexGrid(pos.xz * scale);
vec3 zPlane = hexGrid(pos.xy * scale);
// 根据法线方向混合三个平面
vec3 weights = abs(normal);
weights = pow(weights, sharpness);
weights /= dot(weights, vec3(1.0));
return xPlane * weights.x + yPlane * weights.y + zPlane * weights.z;
}
技术难点: 球面上直接用 UV 映射六边形会产生拉伸变形。三平面投影从 XYZ 三个方向分别投影,然后根据表面法线混合,完美解决这个问题!
2. 菲涅尔发光 (Fresnel Glow)
边缘高亮是能量盾的灵魂:
// 菲涅尔效应 - 视线与法线夹角越大越亮
float fresnel = pow(1.0 - abs(dot(viewDirection, normal)), fresnelPower);
vec3 glowColor = baseColor * fresnel * fresnelIntensity;
3. 流动噪波 (Flow Noise)
// 多层 Simplex 噪波叠加
float flowNoise(vec3 pos, float time) {
float noise = 0.0;
float amplitude = 1.0;
float frequency = 1.0;
for(int i = 0; i < 4; i++) {
noise += simplexNoise(pos * frequency + time * flowSpeed) * amplitude;
amplitude *= 0.5;
frequency *= 2.0;
}
return noise;
}
FBM (Fractal Brownian Motion) 分形布朗运动,通过叠加不同频率的噪波创造丰富的表面细节。
4. 受击系统 (Hit System)
这是我最惊艳的部分——最多同时追踪 6 个受击点:
// Ring Buffer 存储受击信息
uniform vec3 hitPositions[6]; // 受击位置
uniform float hitTimes[6]; // 受击时间
uniform float hitStrengths[6]; // 受击强度
// 每个受击点产生扩散的噪波环
float calculateHitWave(vec3 worldPos, vec3 hitPos, float time, float hitTime) {
float elapsed = time - hitTime;
float distance = length(worldPos - hitPos);
float waveRadius = elapsed * expansionSpeed;
// 噪波扰动的环形波
float wave = smoothstep(waveRadius + thickness, waveRadius, distance);
wave *= smoothstep(waveRadius - thickness, waveRadius, distance);
wave *= noise(worldPos * 10.0 + elapsed); // 添加噪波扰动
return wave * exp(-elapsed * decayRate); // 随时间衰减
}
效果拆解:
- Geodesic Wavefront - 从受击点向外扩散的噪波环
- Hex Highlight Zone - 受击点附近六边形格子高亮
- Life Damage - 每次受击扣减护盾生命值
- 颜色渐变 - 护盾从蓝色渐变为红色表示受损
5. 显隐动画 (Reveal Animation)
// 基于 Simplex 噪波的溶解效果
float dissolveMask = simplexNoise(worldPos * dissolveScale) + (revealProgress * 2.0 - 1.0);
float edgeGlow = smoothstep(0.0, edgeWidth, dissolveMask) * smoothstep(edgeWidth * 2.0, edgeWidth, dissolveMask);
// 边缘发光
if (dissolveMask > 0.0 && dissolveMask < edgeThreshold) {
emission += edgeColor * edgeIntensity;
}
discard; // 完全溶解的像素丢弃
参数化控制
作者用 Leva 做了完整的 GUI 控制面板,所有视觉属性都可以实时调节:
| 参数类别 | 可调项 |
|---|---|
| 网格 | 六边形大小、缝隙宽度、闪烁频率 |
| 材质 | 基础色、发光强度、透明度、底部淡出 |
| 噪波 | 流动速度、噪波层级、扰动强度 |
| 受击 | 波扩散速度、衰减率、六边形高亮范围 |
| 生命系统 | 总血量、单次受伤比例、恢复速度 |
| 后处理 | Bloom 强度、阈值、胶片噪点 |
场景预设 (Presets)
项目提供了两个精心调教的场景预设:
- Default - 漂浮的能量球,中性展示场景
- Droideka - 星球大战中毁灭者的护盾效果,环绕在机器人模型周围
切换预设会同时修改 Shader 参数、光照设置和相机角度,一键体验完全不同的视觉风格。
代码架构赏析
app/
├── shaders/
│ ├── vertex.glsl # 顶点着色器
│ ├── fragment.glsl # 片段着色器
│ └── uniforms.ts # Shader 参数定义
├── components/
│ ├── ShieldMesh.tsx # 护盾网格组件
│ └── Scene.tsx # 3D 场景
├── controls/
│ └── useShieldControls.ts # Leva 控制器
└── presets/
├── default.ts
└── droideka.ts
架构亮点:
- Shader 代码完全手写,无外部依赖,学习价值极高
- 参数与 UI 通过 Leva 绑定,实时调试体验极佳
- 预设系统方便保存和分享配置
学习价值评分
| 维度 | 评分 | 评价 |
|---|---|---|
| 视觉效果 | ⭐⭐⭐⭐⭐ | 电影级品质,可直接用于项目 |
| Shader 技术 | ⭐⭐⭐⭐⭐ | 涵盖多个高级技巧 |
| 代码质量 | ⭐⭐⭐⭐⭐ | 注释详尽,结构清晰 |
| 可扩展性 | ⭐⭐⭐⭐ | 参数化程度高 |
| 学习价值 | ⭐⭐⭐⭐⭐ | 最佳 Shader 学习资源之一 |
🎯 两个项目的对比与选型建议
| 维度 | Cosmic Pool | Force Shield VFX |
|---|---|---|
| 核心领域 | 游戏开发 | 视觉特效 |
| 技术重点 | 物理引擎、游戏逻辑 | Shader、图形学 |
| 学习难度 | 中等 | 较高 |
| 适用场景 | 休闲游戏、原型开发 | 游戏特效、展示页面 |
| 亮点 | 完整游戏循环 | 生产级 Shader |
你应该选哪个?
选择 Cosmic Pool 如果你:
- 想学习 Three.js 游戏开发
- 需要了解物理引擎的实现原理
- 想做休闲类游戏项目
- 喜欢太空/科幻主题
选择 Force Shield VFX 如果你:
- 想深入学习 GLSL Shader
- 需要炫酷的护盾/能量特效
- 想了解后处理管线
- 追求视觉品质
🚀 快速上手指南
Cosmic Pool
# 克隆仓库
git clone https://github.com/lespuch-v/cosmic-pool.git
cd cosmic-pool
# 安装依赖
npm install
# 启动开发服务器
npm run dev
# 打开 http://localhost:5173
Force Shield VFX
# 克隆仓库
git clone https://github.com/cortiz2894/flow-shield-effect.git
cd flow-shield-effect
# 安装依赖(推荐用 pnpm)
pnpm install
# 启动开发服务器
pnpm dev
# 打开 http://localhost:3000
💡 最后的碎碎念
这两个项目代表了 WebGL 领域的两种极致追求:
-
Cosmic Pool 证明了用 Web 技术也能做出有品质的 3D 游戏,它的物理引擎实现虽然不如 Cannon.js 完善,但对于台球这种相对简单的场景完全够用。
-
Force Shield VFX 则展示了 Shader 的强大魅力——同样的几何体,通过不同的着色器可以呈现完全不同的视觉效果。作者 Christian Ortiz 的代码风格非常优雅,注释详尽,是学习 Shader 的绝佳素材。
如果你也对 WebGL 感兴趣,强烈推荐:
- 先把两个项目跑起来体验效果
- 然后啃一遍核心代码
- 尝试修改参数,看效果变化
- 最后尝试移植到你自己的项目中
希望这篇测评对你有帮助!如果觉得不错,点个在看支持一下~ 🌟
📌 开源地址汇总:
- Cosmic Pool: github.com/lespuch-v/c…
- Force Shield VFX: github.com/cortiz2894/…
👨💻 作者信息:
- Cosmic Pool: @lespuch-v
- Force Shield VFX: Christian Ortiz (@cortiz2894)
本文完,感谢阅读!有任何问题欢迎在评论区交流~