WebGL高级实例--利用WebGL+Three.js实现海水波浪场景

通过对webgl和three.js的基础知识学习,发现在三维场景应用实现过程中,完全采用webgl编写需要的工作量非常大,具体可参见我上一篇文章,而且由于片元着色器和顶点着色器是强类型语法,类似C语言,编程过程中有任何的小错误都不好调试与定位。因此,大家经常使用的做法是采用一个开源引擎框架结合webgl开展,目前大部分浏览器都支持webgl,比如采用three.js+webgl编写本文提到的海水波浪应用,当然也可以完全基于three.js来实现,而完全利用three.js实现动态的三维管道效果,请参考另一篇文章

开发环境:vue-2.5.2,Three.js-0.142.0,开发工具webstorm2021.2.3,前端用chrome109.0.5414.120,其他默认。

以下是海水波浪场景示例的功能描述和关键核心代码。

1.实现功能简述:在浏览器中实现海浪波动的三维效果,不能安装插件,支持旋转、放大缩小,并支持在线调整海浪的各类参数,比如波高、波频、波速等等。

2.海浪效果:

  

3.关键代码如下(完整代码请联系我):

在three.js中通过import引入webgl编写的两个着色器:顶点着色器和片元着色器。

import * as THREE from "three"; //引入Threejs
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import waterVertexShader from './shaders/vertex0.glsl';//引入顶点着色器的GLSL文件
import waterFragmentShader from './shaders/fragment0.glsl';//引入片元着色器的GLSL文件

在thee.js中的init方法中构建原始材质,关键代码如下:

// 构建材质贴图
const textureLoader = new THREE.TextureLoader();
const flagTexture = textureLoader.load( '/static/data/waternormals.jpg', function ( texture ) {
  texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
});

// 构建材质,以便后续
const planeMaterial = new THREE.RawShaderMaterial({
  vertexShader: waterVertexShader,
  fragmentShader: waterFragmentShader,
  // transparent: true,
  uniforms:
  {
    //uFrequency: { value: 20 },
    side:THREE.DoubleSide,
    uBigWavesElevation: { value: 0.2 },//波高
    uBigWavesSpeed: { value: 0.75 },//波速
    uFrequency: { value: new THREE.Vector2(5, 7)},
    uTime: { value:10 },
    uColor: { value: new THREE.Color('orange') },
    uTexture: { value: flagTexture }
  }

// 创建三维水面Mesh,并加载的场景中。
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.material.opacity = 0.3;
plane.material.transparent = true;
that.scene.add(plane);

// 创建右上角的gui控制面板
let gui=new GUI();
gui.add(planeMaterial.uniforms.uBigWavesElevation, 'value')
  .min(0)
  .max(1)
  .step(0.001)
  .name('uBigWavesElevation')
gui.add(planeMaterial.uniforms.uBigWavesSpeed, 'value')
  .min(0)
  .max(4)
  .step(0.001)
  .name('uBigWavesSpeed')

// 同时为了让水面动起来,需要创建animate和tick方法,与init方法类似
animate() {
  this.tick();
  requestAnimationFrame( this.animate );//调用自己
  const delta = this.clock.getDelta();
  if ( this.mixer ) this.mixer.update( delta );
  this.renderer.render( this.scene, this.camera );
  this.controls.update();
  this.stats.update();
},

// 循环执行
tick() {
  let elapsedTime = this.clock.getElapsedTime()*2;
  // Update material
  this.material.uniforms.uTime.value = elapsedTime;
}

 

three.js是一个基于WebGLJavaScript库,用于创建复杂的3D图形和动画。要实现波浪线的效果,你可以采用以下步骤: 1. **设置场景和相机**: 首先,创建一个新的Three.js场景,并配置好视角和相机位置。 ```javascript const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.z = 2; ``` 2. **创建几何体**: 创建一个基础的几何体,如线段或曲线路径,作为波浪的基础形状。THREE.Geometry可以手动绘制点,也可以用THREE.CylinderGeometry等预设模型来创建类似的效果。 ```javascript const geometry = new THREE.Geometry(); for (let i = 0; i <= waveLength; i += stepSize) { // 添加波浪节点的位置 geometry.vertices.push(new THREE.Vector3(i, amplitude * Math.sin(waveFrequency * i), 0)); } ``` 3. **动态修改几何体**: 利用requestAnimationFrame函数创建动画循环,通过改变波长、频率、振幅等参数,模拟波浪的起伏变化。 ```javascript function animate() { requestAnimationFrame(animate); // 更新波浪参数 amplitude *= 0.98; // 振幅衰减 waveLength += speed; // 波长变化 // 更新几何体 for (let i = 0; i <= waveLength; i += stepSize) { const position = amplitude * Math.sin(waveFrequency * i); geometry.vertices[i].y = position; } renderer.render(scene, camera); } animate(); ``` 4. **渲染和附加材质**: 将几何体赋予材质并添加到场景中,然后用合适的着色器(如基本材质、噪波纹理等)来增强视觉效果。 ```javascript const material = new THREE.LineBasicMaterial({ color: 0x00ff00 }); const line = new THREE.Line(geometry, material); scene.add(line); ``` 5. **显示结果**: 最后,实例THREE.WebGLRenderer并将场景渲染到HTML元素上。 ```javascript const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); ```
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一望无际的大草原

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值