【11】深入解析 Three.js 中的 GPGPU水面模拟示例代码(webgl_gpgpu_water.html)

【11】深入解析 Three.js 中的 GPGPU水面模拟示例代码(webgl_gpgpu_water.html)

探秘Three.js:官方GPGPU水面模拟示例深度解析💧

(零基础友好版 | 附快速集成指南)

对于刚接触Three.js的开发者来说,GPGPU(通用计算着色器)听起来可能很复杂,但其实这个水面模拟示例的核心逻辑可以拆解成简单易懂的模块!今天我们就从零基础视角解析这个示例,还会教你如何快速把效果集成到自己的项目里🌊

在这里插入图片描述

一、先搞懂:这个示例到底在做什么?

简单来说,这个示例实现了:
✅ 用GPU模拟真实的水面波动(比如丢石子的涟漪效果)
✅ 鼠标点按/拖动时,水面会跟着产生波纹
✅ 小黄鸭能"浮"在水面上,跟着水波晃动
✅ 水面有反光、折射,看起来像真的水

你可以把它想象成:用代码做了一个"电子水池",还能伸手进去搅水玩~

二、核心模块拆解(零基础也能懂)

1. 基础环境搭建:先搭好"舞台"

就像演戏要先搭舞台一样,Three.js做3D效果也需要先准备基础环境:

// 创建相机(相当于你的眼睛) camera =newTHREE.PerspectiveCamera(75, 窗口宽/窗口高,0.1,1000);// 创建场景(放所有3D物体的"盒子") scene =newTHREE.Scene();// 创建渲染器(负责把3D场景画到网页上) renderer =newTHREE.WebGLRenderer({ antialias:true});// 把渲染结果放到网页里 document.body.appendChild(renderer.domElement);

零基础小贴士:这三行是Three.js的"标配",几乎所有项目都要写,记住就好!

2. GPGPU水面计算:让水"动"起来

这里是核心,但我们不用懂复杂的GPU原理,只需要知道:
👉 用GPUComputationRenderer帮我们算水面波动
👉 用"高度图"(一张看不见的图片)记录每个位置的水面高度
👉 着色器(Shader)负责计算波纹怎么扩散

// 初始化GPU计算工具(128x128是计算精度,数字越大效果越好但越卡) gpuCompute =newGPUComputationRenderer(128,128, renderer);// 创建高度图(存水面高度的"秘密图片")const heightmap = gpuCompute.createTexture();// 添加计算任务:让着色器处理水面波动 heightmapVariable = gpuCompute.addVariable('heightmap', 着色器代码, heightmap);

零基础小贴士:你可以把GPU计算理解成"找了个超级计算器专门算水面",比CPU算得快10倍!

3. 水面渲染:把计算结果画出来

有了水面高度数据,还要用"材质"把水画出来:

// 自定义水面材质(继承Three.js自带的材质)classWaterMaterialextendsTHREE.MeshStandardMaterial{onBeforeCompile(shader){// 关键:根据高度图让顶点"凸起",形成波浪 shader.vertexShader = shader.vertexShader.replace('#include <begin_vertex>',`float height = texture2D(heightmap, uv).x; vec3 transformed = vec3(position.x, position.y + height, position.z);`);}}// 创建水面(用平面几何体+水面材质)const waterGeometry =newTHREE.PlaneGeometry(6,6);// 6x6是水面大小const waterMesh =newTHREE.Mesh(waterGeometry,newWaterMaterial()); waterMesh.rotation.x =-Math.PI/2;// 把平面旋转成水平(默认是垂直的) scene.add(waterMesh);

零基础小贴士PlaneGeometry是"平面",旋转后就成了水面;材质负责让它看起来像水~

4. 鼠标交互:用鼠标"搅水"

想要鼠标点水时产生波纹,只需要两步:
👉 检测鼠标点在水面的哪个位置
👉 把位置传给GPU计算着色器

// 鼠标按下时记录位置 document.addEventListener('pointerdown',()=>{ mousedown =true;});// 鼠标移动时计算波纹functionraycast(){if(mousedown){// 用射线检测鼠标点到的水面位置 raycaster.setFromCamera(mouseCoords, camera);const intersects = raycaster.intersectObject(waterMesh);if(intersects.length >0){// 把鼠标位置传给GPU,让这里产生波纹 heightmapVariable.material.uniforms.mousePos.value = intersects[0].point;}}}

零基础小贴士:射线检测就像"从鼠标位置发射一道激光",看激光打到哪个物体上~

5. 小黄鸭漂浮:让物体跟着水动

小黄鸭能浮在水面,核心是:
👉 读取水面在小黄鸭位置的高度
👉 把小黄鸭的Y坐标(上下)设成水面高度

functionupdateDuck(){// 读取水面在鸭子位置的高度const waterHeight =getWaterHeight(duck.position.x, duck.position.z);// 让鸭子跟着水面高度走 duck.position.y = waterHeight;}

零基础小贴士:就像你站在蹦床上,蹦床凹下去你也会跟着下去~

三、快速集成到你的项目(复制即用)

下面是精简版代码,直接复制到HTML文件就能运行:

<!DOCTYPEhtml><html><head><title>我的水面效果</title><style>body{margin: 0;}</style></head><body><scripttype="importmap">{"imports":{"three":"https://unpkg.com/[email protected]/build/three.module.js","three/addons/":"https://unpkg.com/[email protected]/examples/jsm/"}}</script><scripttype="module">import*asTHREEfrom'three';import{ GPUComputationRenderer }from'three/addons/misc/GPUComputationRenderer.js';// 1. 基础环境const scene =newTHREE.Scene();const camera =newTHREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight,0.1,1000);const renderer =newTHREE.WebGLRenderer({ antialias:true}); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); camera.position.set(0,2,4);// 2. 初始化GPU计算const gpuCompute =newGPUComputationRenderer(128,128, renderer);const heightmap = gpuCompute.createTexture();// 填充初始高度(随便填点噪声让水面有初始波动)const data = heightmap.image.data;for(let i =0; i < data.length; i +=4){ data[i]= Math.random()*0.1;// 初始高度}// 3. 水面计算着色器(核心:波纹扩散公式)const heightmapShader =` uniform vec2 mousePos; uniform float mouseSize; void main() { vec2 uv = gl_FragCoord.xy / resolution.xy; vec4 prev = texture2D(heightmap, uv); // 简单波纹公式(不用懂,复制就行) float dist = length(uv * 6 - mousePos); float wave = dist < mouseSize ? 0.1 : 0.0; gl_FragColor = vec4(prev.x * 0.95 + wave, 0, 0, 1); } `;const heightmapVariable = gpuCompute.addVariable('heightmap', heightmapShader, heightmap); gpuCompute.init();// 4. 创建水面classWaterMaterialextendsTHREE.MeshStandardMaterial{constructor(){super({ color:0x9bd2ec, metalness:0.9, roughness:0});}onBeforeCompile(shader){ shader.uniforms.heightmap ={ value:null}; shader.vertexShader = shader.vertexShader.replace('#include <begin_vertex>',`float h = texture2D(heightmap, uv).x; vec3 transformed = vec3(position.x, position.y + h, position.z);`);}}const waterGeo =newTHREE.PlaneGeometry(6,6,128,128);const waterMat =newWaterMaterial();const waterMesh =newTHREE.Mesh(waterGeo, waterMat); waterMesh.rotation.x =-Math.PI/2; scene.add(waterMesh);// 5. 鼠标交互const raycaster =newTHREE.Raycaster();const mouse =newTHREE.Vector2();let mousedown =false; window.addEventListener('pointerdown',()=> mousedown =true); window.addEventListener('pointerup',()=> mousedown =false); window.addEventListener('pointermove',(e)=>{ mouse.x =(e.clientX / window.innerWidth)*2-1; mouse.y =-(e.clientY / window.innerHeight)*2+1;});// 6. 动画循环functionanimate(){requestAnimationFrame(animate);// 计算水面 gpuCompute.compute(); waterMat.heightmap = gpuCompute.getCurrentRenderTarget(heightmapVariable).texture;// 鼠标交互if(mousedown){ raycaster.setFromCamera(mouse, camera);const intersects = raycaster.intersectObject(waterMesh);if(intersects.length >0){const p = intersects[0].point; heightmapVariable.material.uniforms.mousePos.value = p; heightmapVariable.material.uniforms.mouseSize.value =0.5;}} renderer.render(scene, camera);}animate();</script></body></html>

四、零基础避坑指南

  1. 运行方式:必须用本地服务器(比如VSCode的Live Server插件),直接双击HTML文件会报错!
  2. 性能问题:如果卡,把128改成64(计算精度降低,效果稍差但更流畅)
  3. 水面颜色:改0x9bd2ec就能换颜色(比如0x00ffff是浅蓝色)
  4. 波纹大小:改mouseSize.value = 0.5里的0.5,数字越大波纹范围越广

五、总结

其实Three.js的GPGPU水面效果并没有想象中难,核心就是:
👉 用GPU算水面高度 → 用材质画水面 → 加交互让水"活"起来

哪怕你是零基础,只要复制上面的代码,改改参数(比如水面大小、颜色、波纹强度),就能快速做出自己的水面效果!后续可以再慢慢深入学习着色器和物理公式~🚀

Read more

【AI】学习大语言模型原理必看的 10 篇论文

【AI】学习大语言模型原理必看的 10 篇论文

🔥小龙报:个人主页 🎬作者简介:C++研发,嵌入式,机器人等方向学习者 ❄️个人专栏:《AI》 ✨ 永远相信美好的事情即将发生 文章目录 * 前言 * 一、Transformer * 二、GPT-3 * 三、InstructGPT * 四、Sparrow * 五、RLHF * 六、TATAMER * 七、PPO * 八、In-Context Learning * 8.1 Why Can GPT Learn In-Context * 8.2 What learning algorithm is in-context learning * 九、Prompt * 总结 前言 从 Transformer

By Ne0inhk
AI Agent 平台横评:ZeroClaw vs OpenClaw vs Nanobot

AI Agent 平台横评:ZeroClaw vs OpenClaw vs Nanobot

AI Agent 平台横评:ZeroClaw vs OpenClaw vs Nanobot 前言 在之前的文章中,我们详细介绍了 ZeroClaw 的功能特性和安装部署方法。本文将从多个维度对当前主流的 AI Agent 平台进行横向对比,帮助开发者选择最适合自己项目的工具。 一、对比产品概述 1.1 ZeroClaw ZeroClaw 是基于 100% Rust 编写的轻量级 AI Agent 基础设施,强调高性能和安全性。 * 语言:Rust * 特点:二进制仅 ~3.4 MB,启动极快,内存占用低 * GitHub:https://github.com/theonlyhennygod/zeroclaw 1.2 OpenClaw

By Ne0inhk
被问爆的Agent实战:从0到1搭建可落地AI智能体

被问爆的Agent实战:从0到1搭建可落地AI智能体

🎁个人主页:User_芊芊君子 🎉欢迎大家点赞👍评论📝收藏⭐文章 🔍系列专栏:AI 文章目录: * 【前言】 * 一、先搞懂:2026年爆火的AI Agent,到底是什么? * 1.1 Agent的核心定义 * 1.2 Agent的4大核心能力 * 1.3 2026年Agent的3个热门落地场景 * 二、框架选型:2026年6大主流Agent框架,新手该怎么选? * 三、实战环节:从0到1搭建可落地的“邮件处理Agent”(全程代码+步骤) * 3.1 实战准备:环境搭建(10分钟搞定) * 3.1.1 安装Python环境 * 3.1.2 创建虚拟环境(避免依赖冲突) * 3.

By Ne0inhk
Obsidian接入AI完整配置指南

Obsidian接入AI完整配置指南

🚀 Obsidian接入AI完整配置指南 📋 目录导航 * 核心工具介绍 * 免费接入方案 * 详细配置步骤 * 模型选择建议 * 实用功能配置 * 使用场景示例 * 常见问题解决 * 高级技巧 🎯 核心工具:Copilot插件 Copilot是Obsidian中最强大的AI助手插件,让你的笔记体验智能化升级! 安装步骤(3步搞定) 1. 打开设置:Obsidian → 设置 → 社区插件 2. 搜索安装:搜索"Copilot"并点击安装 3. 启用重启:启用插件并重启Obsidian 💰 免费AI接入方案:OpenRouter OpenRouter提供多个免费AI模型,是性价比最高的选择! 第一步:注册账号 * 🌐 访问:https://openrouter.ai/ * 🔗 使用GitHub或Google快速注册 * 🔑 在Keys页面生成API密钥 第二步:添加模型配置 模型添加方法: 1. ✅ 模型名称必须正确 2. 🌐 URL同图片地址

By Ne0inhk