threejs(12)-着色器打造烟雾水云效果

一、自己封装水波纹效果

在这里插入图片描述
src/main/main01.js

import * as THREE from "three";import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import gsap from "gsap";
import * as dat from "dat.gui";
import vertexShader from "../shaders/water/vertex.glsl";
import fragmentShader from "../shaders/water/fragment.glsl";// 目标:设置云烟雾效果//创建gui对象
const gui = new dat.GUI();// console.log(THREE);
// 初始化场景
const scene = new THREE.Scene();// 创建透视相机
const camera = new THREE.PerspectiveCamera(90,window.innerHeight / window.innerHeight,0.1,1000
);
// 设置相机位置
// object3d具有position,属性是1个3维的向量
camera.position.set(0, 0, 2);
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
//   更新摄像机的投影矩阵
camera.updateProjectionMatrix();
scene.add(camera);// 加入辅助轴,帮助我们查看3维坐标轴
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);const params = {uWaresFrequency: 14,uScale: 0.03,uXzScale: 1.5,uNoiseFrequency: 10,uNoiseScale: 1.5,uLowColor: "#ff0000",uHighColor: "#ffff00",uXspeed: 1,uZspeed: 1,uNoiseSpeed: 1,uOpacity: 1,
};const shaderMaterial = new THREE.ShaderMaterial({vertexShader: vertexShader,fragmentShader: fragmentShader,side: THREE.DoubleSide,uniforms: {uWaresFrequency: {value: params.uWaresFrequency,},uScale: {value: params.uScale,},uNoiseFrequency: {value: params.uNoiseFrequency,},uNoiseScale: {value: params.uNoiseScale,},uXzScale: {value: params.uXzScale,},uTime: {value: params.uTime,},uLowColor: {value: new THREE.Color(params.uLowColor),},uHighColor: {value: new THREE.Color(params.uHighColor),},uXspeed: {value: params.uXspeed,},uZspeed: {value: params.uZspeed,},uNoiseSpeed: {value: params.uNoiseSpeed,},uOpacity: {value: params.uOpacity,},},transparent: true,
});gui.add(params, "uWaresFrequency").min(1).max(100).step(0.1).onChange((value) => {shaderMaterial.uniforms.uWaresFrequency.value = value;});gui.add(params, "uScale").min(0).max(0.2).step(0.001).onChange((value) => {shaderMaterial.uniforms.uScale.value = value;});gui.add(params, "uNoiseFrequency").min(1).max(100).step(0.1).onChange((value) => {shaderMaterial.uniforms.uNoiseFrequency.value = value;});gui.add(params, "uNoiseScale").min(0).max(5).step(0.001).onChange((value) => {shaderMaterial.uniforms.uNoiseScale.value = value;});gui.add(params, "uXzScale").min(0).max(5).step(0.1).onChange((value) => {shaderMaterial.uniforms.uXzScale.value = value;});gui.addColor(params, "uLowColor").onFinishChange((value) => {shaderMaterial.uniforms.uLowColor.value = new THREE.Color(value);
});
gui.addColor(params, "uHighColor").onFinishChange((value) => {shaderMaterial.uniforms.uHighColor.value = new THREE.Color(value);
});gui.add(params, "uXspeed").min(0).max(5).step(0.001).onChange((value) => {shaderMaterial.uniforms.uXspeed.value = value;});gui.add(params, "uZspeed").min(0).max(5).step(0.001).onChange((value) => {shaderMaterial.uniforms.uZspeed.value = value;});gui.add(params, "uNoiseSpeed").min(0).max(5).step(0.001).onChange((value) => {shaderMaterial.uniforms.uNoiseSpeed.value = value;});gui.add(params, "uOpacity").min(0).max(1).step(0.01).onChange((value) => {shaderMaterial.uniforms.uOpacity.value = value;});const plane = new THREE.Mesh(new THREE.PlaneBufferGeometry(1, 1, 1024, 1024),shaderMaterial
);
plane.rotation.x = -Math.PI / 2;scene.add(plane);// 初始化渲染器
const renderer = new THREE.WebGLRenderer({ alpha: true });// 设置渲染尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);// 监听屏幕大小改变的变化,设置渲染的尺寸
window.addEventListener("resize", () => {//   console.log("resize");// 更新摄像头camera.aspect = window.innerWidth / window.innerHeight;//   更新摄像机的投影矩阵camera.updateProjectionMatrix();//   更新渲染器renderer.setSize(window.innerWidth, window.innerHeight);//   设置渲染器的像素比例renderer.setPixelRatio(window.devicePixelRatio);
});// 将渲染器添加到body
document.body.appendChild(renderer.domElement);// 初始化控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼
controls.enableDamping = true;const clock = new THREE.Clock();
function animate(t) {const elapsedTime = clock.getElapsedTime();shaderMaterial.uniforms.uTime.value = elapsedTime;requestAnimationFrame(animate);// 使用渲染器渲染相机看这个场景的内容渲染出来renderer.render(scene, camera);
}animate();

src/shaders/water/fragment.glsl

precision lowp float;uniform vec3 uHighColor;
uniform vec3 uLowColor;
varying float vElevation;
uniform float uOpacity;void main(){float a = (vElevation+1.0)/2.0;vec3 color = mix(uLowColor,uHighColor,a);gl_FragColor = vec4(color,uOpacity);
}

src/shaders/water/vertex.glsl

precision lowp float;
uniform float uWaresFrequency;
uniform float uScale;
uniform float uNoiseFrequency;
uniform float uNoiseScale;
uniform float uXzScale;
uniform float uTime;
uniform float uXspeed;
uniform float uZspeed;
uniform float uNoiseSpeed;// 计算出的高度传递给片元着色器
varying float vElevation;// 随机函数
float random (vec2 st) {return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.5453123);
}// 旋转函数
vec2 rotate(vec2 uv, float rotation, vec2 mid)
{return vec2(cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x,cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y);
}// 噪声函数
float noise (in vec2 _st) {vec2 i = floor(_st);vec2 f = fract(_st);// Four corners in 2D of a tilefloat a = random(i);float b = random(i + vec2(1.0, 0.0));float c = random(i + vec2(0.0, 1.0));float d = random(i + vec2(1.0, 1.0));vec2 u = f * f * (3.0 - 2.0 * f);return mix(a, b, u.x) +(c - a)* u.y * (1.0 - u.x) +(d - b) * u.x * u.y;
}//	Classic Perlin 2D Noise 
//	by Stefan Gustavson
//
vec4 permute(vec4 x)
{return mod(((x*34.0)+1.0)*x, 289.0);
}vec2 fade(vec2 t)
{return t*t*t*(t*(t*6.0-15.0)+10.0);
}float cnoise(vec2 P)
{vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0);vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0);Pi = mod(Pi, 289.0); // To avoid truncation effects in permutationvec4 ix = Pi.xzxz;vec4 iy = Pi.yyww;vec4 fx = Pf.xzxz;vec4 fy = Pf.yyww;vec4 i = permute(permute(ix) + iy);vec4 gx = 2.0 * fract(i * 0.0243902439) - 1.0; // 1/41 = 0.024...vec4 gy = abs(gx) - 0.5;vec4 tx = floor(gx + 0.5);gx = gx - tx;vec2 g00 = vec2(gx.x,gy.x);vec2 g10 = vec2(gx.y,gy.y);vec2 g01 = vec2(gx.z,gy.z);vec2 g11 = vec2(gx.w,gy.w);vec4 norm = 1.79284291400159 - 0.85373472095314 * vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11));g00 *= norm.x;g01 *= norm.y;g10 *= norm.z;g11 *= norm.w;float n00 = dot(g00, vec2(fx.x, fy.x));float n10 = dot(g10, vec2(fx.y, fy.y));float n01 = dot(g01, vec2(fx.z, fy.z));float n11 = dot(g11, vec2(fx.w, fy.w));vec2 fade_xy = fade(Pf.xy);vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x);float n_xy = mix(n_x.x, n_x.y, fade_xy.y);return 2.3 * n_xy;
}void main(){vec4 modelPosition = modelMatrix * vec4(position,1.0);float elevation = sin(modelPosition.x*uWaresFrequency+uTime*uXspeed)*sin(modelPosition.z*uWaresFrequency*uXzScale+uTime*uZspeed);elevation += -abs(cnoise(vec2(modelPosition.xz*uNoiseFrequency+uTime*uNoiseSpeed))) *uNoiseScale;vElevation = elevation;elevation *= uScale;modelPosition.y += elevation;gl_Position = projectionMatrix * viewMatrix *modelPosition;
}

二、使用官方提供的water方法

在这里插入图片描述

src/main/main.js

import * as THREE from "three";import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import gsap from "gsap";
import * as dat from "dat.gui";import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";// 导入water
import { Water } from "three/examples/jsm/objects/Water2";// 目标:认识shader//创建gui对象
const gui = new dat.GUI();// console.log(THREE);
// 初始化场景
const scene = new THREE.Scene();// 创建透视相机
const camera = new THREE.PerspectiveCamera(90,window.innerHeight / window.innerHeight,0.1,1000
);
// 设置相机位置
// object3d具有position,属性是1个3维的向量
camera.position.set(5, 5, 5);
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
//   更新摄像机的投影矩阵
camera.updateProjectionMatrix();
scene.add(camera);// 加入辅助轴,帮助我们查看3维坐标轴
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);// const water = new Water(new THREE.PlaneBufferGeometry(1, 1, 1024, 1024), {
//   color: "#ffffff",
//   scale: 1,
//   flowDirection: new THREE.Vector2(1, 1),
//   textureHeight: 1024,
//   textureWidth: 1024,
// });
// water.rotation.x = -Math.PI / 2;// scene.add(water);// 加载场景背景
const rgbeLoader = new RGBELoader();
rgbeLoader.loadAsync("./assets/050.hdr").then((texture) => {texture.mapping = THREE.EquirectangularReflectionMapping;scene.background = texture;scene.environment = texture;
});// 加载浴缸
const gltfLoader = new GLTFLoader();
gltfLoader.load("./assets/model/yugang.glb", (gltf) => {console.log(gltf);const yugang = gltf.scene.children[0];yugang.material.side = THREE.DoubleSide;const waterGeometry = gltf.scene.children[1].geometry;const water = new Water(waterGeometry, {color: "#ffffff",scale: 1,flowDirection: new THREE.Vector2(1, 1),textureHeight: 1024,textureWidth: 1024,});scene.add(water);scene.add(yugang);
});const light = new THREE.AmbientLight(0xffffff); // soft white light
light.intensity = 10;
scene.add(light);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
scene.add(directionalLight);// 初始化渲染器
const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.toneMapping = THREE.ACESFilmicToneMapping;// 设置渲染尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);// 监听屏幕大小改变的变化,设置渲染的尺寸
window.addEventListener("resize", () => {//   console.log("resize");// 更新摄像头camera.aspect = window.innerWidth / window.innerHeight;//   更新摄像机的投影矩阵camera.updateProjectionMatrix();//   更新渲染器renderer.setSize(window.innerWidth, window.innerHeight);//   设置渲染器的像素比例renderer.setPixelRatio(window.devicePixelRatio);
});// 将渲染器添加到body
document.body.appendChild(renderer.domElement);// 初始化控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼
controls.enableDamping = true;const clock = new THREE.Clock();
function animate(t) {const elapsedTime = clock.getElapsedTime();requestAnimationFrame(animate);// 使用渲染器渲染相机看这个场景的内容渲染出来renderer.render(scene, camera);
}animate();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/169615.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

江西开放大学引领学习新时代:电大搜题助力学子迈向成功

江西开放大学(简称江西电大)一直以来致力于为学子提供灵活便捷的学习服务。近年来,携手电大搜题微信公众号,江西开放大学以其卓越的教学质量和创新的教学手段,为广大学子开启了一扇通向成功的大门。 作为一家知名的远…

深入了解JVM和垃圾回收算法

1.什么是JVM? JVM是Java虚拟机(Java Virtual Machine)的缩写,是Java程序运行的核心组件。JVM是一个虚拟的计算机,它提供了一个独立的运行环境,可以在不同的操作系统上运行Java程序。 2.如何判断可回收垃圾…

远程电脑未连接显示器时分辨率太小的问题处理

背景:单位电脑显示器坏了,使用笔记本通过向日葵远程连接,发现分辨率只有800*600并且不能修改,网上找了好久找到了处理方法这里记录一下,主要用到的是一个虚拟显示器软件usbmmidd_v2 1)下载usbmmidd_v2 2)…

js案例:打地鼠游戏(打灰太狼)

效果预览图 游戏规则 当灰太狼出现的时候鼠标左键点击灰太狼加10分,小灰灰出现的时候鼠标左键点小灰灰击减10分,不点击不减分不加分。 整体思路 1.把获取背景图片中每个地洞的位置,把所有位置放到一个数组中。 2.封装随机数函数,随…

RSA 2048位算法的主要参数N,E,P,Q,DP,DQ,Qinv,D分别是什么意思 哪个是通常所说的公钥与私钥 -安全行业基础篇5

非对称加密算法RSA 在RSA 2048位算法中,常见的参数N、E、P、Q、DP、DQ、Qinv和D代表以下含义: N(Modulus):模数,是两个大素数P和Q的乘积。N的长度决定了RSA算法的安全性。 E(Public Exponent&a…

vite基础学习笔记:14.路由跳转(二)携带query参数

说明:自学做的笔记和记录,如有错误请指正 1. 路由跳转(携带query参数) (1)第一层路由(点击卡片路由跳转至新页面-携带query参数) 知识点: query传参对应的是path和qu…

移动医疗科技:开发互联网医院系统源码

在这个数字化时代,互联网医院系统成为了提供便捷、高效医疗服务的重要手段。本文将介绍利用移动医疗科技开发互联网医院系统的源码,为医疗行业的数字化转型提供有力支持。 智慧医疗、互联网医院这一类平台可以通过线上的形式进行部分医疗服务&#xff…

数据结构与算法C语言版学习笔记(3)-线性表的链式结构:链表

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言:回顾顺序表的优缺点:为什么要引入链式结构的线性表? 一、什么是链表?二、链表的分类①为什么要设置头节点&…

【计网 传输层概述】 中科大郑烇老师笔记 (十)

目录 0 引言1 概述1.1 传输服务和协议1.2 传输层 vs 网络层1.3 Internet传输层协议 TCP和UDP 2 多路复用、解复用2.1 UDP的多路复用2.2 TCP的多路复用 3 UDP3.1 概述3.2 UDP报文段3.3 拓展:TCP报文段 🙋‍♂️ 作者:海码007📜 专栏…

Apipost-Helper:IDEA中的类postman工具

今天给大家推荐一款IDEA插件:Apipost-Helper-2.0,写完代码IDEA内一键生成API文档,无需安装、打开任何其他软件;写完代码IDEA内一键调试,无需安装、打开任何其他软件;生成API目录树,双击即可快速…

postman上传照片,视频,音频等上传文件操作测试方法

Postman上传照片,视频,音频等上传文件操作测试方法 新建一个request,更改请求方式,点击Body 勾选form-data ,key后面下拉框选择File 上一步勾选后Value即出现选择本地文件按钮,填写Key,选择文件即可 此时…

国际阿里云:无法ping通ECS实例公网IP的排查方法!!!

无法ping通ECS实例的原因较多,您可以参考本文进行排查。 问题现象 本地客户端无法ping通目标ECS实例公网IP,例如: 本地客户端为Linux系统,ping目标ECS实例公网IP时无响应,如下所示: 本地客户端为Windo…