用html写一个雨的特效

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>雨特效</title><link rel="stylesheet" href="./style.css">
</head>
<body>
<div id="wrap-texture"><div id="canvas"></div><div class="plane"><img data-sampler="dispImage" id="texture" src="https://source.unsplash.com/MFW8BGYKNIE" crossorigin="anonymous"/></div>
</div>
<!-- partial --><script src="https://www.curtainsjs.com/build/curtains.min.js"></script>
<script src="./script.js"></script>
</body>
</html>
window.onload = () => {const shader = {vertex: ` #ifdef GL_ESprecision mediump float;#endif// lib设置的强制属性attribute vec3 aVertexPosition;attribute vec2 aTextureCoord;// lib设置的强制统一,包含模型视图和投影矩阵uniform mat4 uMVMatrix;uniform mat4 uPMatrix;uniform mat4 dispImageMatrix;// 将顶点和纹理坐标传递给着色器varying vec3 vVertexPosition;varying vec2 vTextureCoord;void main() {vec3 vertexPosition = aVertexPosition;gl_Position = uPMatrix * uMVMatrix * vec4(vertexPosition, 1.0);// 设置varyingsvTextureCoord = (dispImageMatrix * vec4(aTextureCoord, 0., 1.)).xy;vVertexPosition = vertexPosition;}`,fragment: `#ifdef GL_ESprecision mediump float;#endif#define PI2 6.28318530718#define PI 3.14159265359#define S(a,b,n) smoothstep(a,b,n)// 获得varyingsvarying vec3 vVertexPosition;varying vec2 vTextureCoord;// 用uniform声明uniform float uTime;uniform vec2 uReso;uniform vec2 uMouse;// 纹理采样器uniform sampler2D dispImage;uniform sampler2D blurImage;// 噪声float N12(vec2 p){p = fract(p * vec2(123.34, 345.45));p += dot(p, p + 34.345);return fract(p.x * p.y);}vec3 Layer(vec2 uv0, float t){vec2 asp = vec2(2., 1.);vec2 uv1 = uv0 * 3. * asp;uv1.y += t * .25;vec2 gv = fract(uv1) - .5;vec2 id = floor(uv1);float n = N12(id);t+= n * PI2;float w = uv0.y * 10.;float x = (n - .5) * .8;x += (.4 - abs(x)) * sin(3. * w) * pow(sin(w), 6.) * .45;float y = -sin(t + sin(t + sin(t) * .5)) * (.5 - .06);y -= (gv.x - x) * (gv.x - x); // sesgar;vec2 dropPos = (gv - vec2(x, y)) / asp; float drop = S(.03, .02, length(dropPos));vec2 trailPos = (gv - vec2(x, t * .25)) / asp; trailPos.y = (fract(trailPos.y * 8.) - .5) / 8.;float trail = S(.02, .015, length(trailPos));float fogTrail = S(-.05, .05, dropPos.y);fogTrail *= S(.5, y, gv.y);trail *= fogTrail;fogTrail *= S(.03, .015, abs(dropPos.x));vec2 off = drop * dropPos + trail * trailPos;return vec3(off, fogTrail);}void main() { float dist = 5.;float blurSize = 5.;float t = mod(uTime * .03, 7200.);vec4 c = vec4(0);vec2 uv = vTextureCoord; vec3 drops = Layer(uv, t);drops += Layer(uv * 1.25 + 7.54, t);drops += Layer(uv * 1.35 + 1.54, t);drops += Layer(uv * 1.57 - 7.54, t);float blur = blurSize * 7. * (1. - drops.z);vec4 col = vec4(0.);int numSamples = 32;float a = N12(uv) * PI2;blur *= .0005;uv += drops.xy * dist;for(int n = 0; n < 32; n++){vec2 off = vec2(sin(a), cos(a)) * blur;float d = fract(sin((float(n) + 1.) * 546.) * 5424.);d = sqrt(d); off *= d;col += texture2D(dispImage, uv + off);a++;}col /= float(numSamples);gl_FragColor = col;}`};// canvasconst canvasContainer = document.getElementById("canvas");const mouse = {x: 0,y: 0};// 设置WebGL,并将canvas附加到containerconst webGLCurtain = new Curtains({container: "canvas"});// 获取平面元素const planeElement = document.getElementsByClassName("plane")[0];// 设置初始参数const params = {vertexShader: shader.vertex, // 顶点着色器fragmentShader: shader.fragment, // framgent着色器widthSegments: 40,heightSegments: 40, // 现在有40*40*6=9600个顶点uniforms: {time: {name: "uTime", // 传递给着色器统一名称type: "1f", value: 0},mousepos: {name: "uMouse",type: "2f",value: [mouse.x, mouse.y]},resolution: {name: "uReso",type: "2f",value: [innerWidth, innerHeight]}}};// 创建平面网格const plane = webGLCurtain.addPlane(planeElement, params);plane.onRender(() => {plane.uniforms.time.value++; // 更新统一值plane.uniforms.resolution.value = [innerWidth, innerHeight];});canvasContainer.addEventListener("mousemove", ({ clientX, clientY }) => {mouse.x = clientX;mouse.y = clientY;plane.uniforms.mousepos.value = [mouse.x, mouse.y];});};
body {position: relative;width: 100%;height: 100vh;margin: 0;overflow: hidden;
}#wrap-texture {position: relative;
}#canvas {/* canvas 的大小 */position: absolute;top: 0;right: 0;bottom: 0;left: 0;
}.plane {/* 限制 plane 的大小 */width: 100%;height: 100vh;
}.plane img {/* 隐藏 img 对象 */display: none;
}
相关文章:
用html写一个雨的特效
<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>雨特效</title><link rel"stylesheet" href"./style.css"> </head> <body> <div id"wrap-textu…...
前端 接口返回来的照片太大 加载慢如何解决
现象 解决 1. 添加图片懒加载 背景图懒加载 对背景图懒加载做的解释 和图片懒加载不同,背景图懒加载需要使用 v-lazy:background-image,值设置为背景图片的地址,需要注意的是必须声明容器高度。 <div v-for"img in imageList&quo…...
003 传参
文章目录 传参http 状态码传参方式(1)URL请求参数 key 与 方法中的形参名一致(2)URL请求参数 key与RequestParam("id") 中的别名一致(3) 形参是POJO类,URL 参数 key 与pojo类的 set方…...
QT写Windows按键输出(外挂)
一、前言 玩游戏的时候遇到些枯燥无味反反复复的按鼠标键盘的情况时,就想写个外挂自动释放。刚好在学qt所以试验了下QT能不能对外输出按键与鼠标。 二、思路 qt中的按键鼠标全是输入,没有直接对外输出键盘鼠标指令的类,但是我们换个思路&…...
Stable Diffusion之文生图模型训练
1、数据准备 提前准备好一组相关的照片。 在线的图片处理网站 BIRME - Bulk Image Resizing Made Easy 2.0 (Online & Free) 将图片转成统一大小,支持批量处理,效率高 2、生成提示词 进入stable diffusion webui页面 旧版直接使用 train/proproc…...
SpringBoot整合支付宝沙箱支付
环境说明:SpringBoot3.0.2 支付宝沙箱地址:沙箱地址 获取配置信息 因支付需要回调地址,回调地址必须是公网,如果有公网的话,那直接在下面配置文件填写自己的公网,没有的话,就需要我们借助第三…...
探索进程控制第一弹(进程终止、进程等待)
文章目录 进程创建初识fork函数fork函数返回值fork常规用法fork调用失败的原因 写时拷贝进程终止进程终止是在做什么?进程终止的情况代码跑完,结果正确/不正确代码异常终止 如何终止 进程等待概述进程等待方法wait方法waitpid 进程创建 初识fork函数 在…...
在mac环境下使用shell脚本实现tree命令
文章目录 使用ls实现tree使用find实现tree 使用ls实现tree 实现思路 使用ls -F 打印文件类型,如果是目录后面跟/,如果是可执行文件后面跟*;使用grep -v /$ 筛选文件排除目录,-v为反向筛选;使用grep /$ 仅筛选目录&am…...
递归时间复杂度分析方法:Master 定理
编写算法时,可能因为对自己代码的复杂度的不清晰而导致错失良机,对于普通的递推或者说循环的代码,仅用简单的调和级数或者等差数列和等比数列即可分析,但是对于递归的代码,简单的递归树法并不方便,理解并记…...
实例名不规范导致mds创建失败
概述 在部署ceph集群时,规划主机名、关闭防火墙、配置免密、关闭selinux,配置hosts文件这几步同样重要,都是初期部署一次麻烦,方便后续运维的动作。遇到过很多前期稀里糊涂部署,后续运维和配置时候各种坑。 近期遇到…...
OpenGL中的纹理过滤GL_NEAREST和GL_LINEAR
一、GL_NEAREST(最近邻插值) 1.1 原理 当需要从纹理中采样颜色时,GL_NEAREST模式会选择离采样点最近的纹理像素(通常是最接近采样点的纹理元素的中心),并直接使用该像素的颜色值作为输出。这种模式不进行任…...
vue 性能优化
data 层级不要太深 data 层级太深会增加响应式监听的计算,导致页面初次渲染时卡顿。 合理使用 v-show 和 v-if 频繁切换时,使用 v-show无需频繁切换时,使用 v-if 合理使用 computed computed 有缓存,data 不变时不会重新计算&…...
互联网大厂ssp面经(操作系统:part1)
1. 什么是进程和线程?它们之间有什么区别? a. 进程是操作系统中运行的一个程序实例。它拥有独立的地址空间和资源,可以独立执行。 b. 线程是进程内的一个执行单元,一个进程可以包含多个线程。 c. 线程共享进程的资源,…...
Android Activity 启动涉及几个进程
Zygote进程: Zygote进程在Android系统启动时被初始创建,并且初始化了虚拟机(Dalvik或ART),预加载了Android系统的核心类库。所有的Android应用进程都是通过fork()从Zygote进程派生出来的,这允许应用快速启动࿰…...
说说你对链表的理解?常见的操作有哪些?
一、是什么 链表(Linked List)是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的,由一系列结点(链表中每一个元素称为结点)组成 每个结点包括两个部分&…...
每天五分钟深度学习:逻辑回归算法的损失函数和代价函数是什么?
本文重点 前面已经学习了逻辑回归的假设函数,训练出模型的关键就是学习出参数w和b,要想学习出这两个参数,此时需要最小化逻辑回归的代价函数才可以训练出w和b。那么本节课我们将学习逻辑回归算法的代价函数是什么? 为什么不能平方差损失函数 线性回归的代价函数我们使用…...
llama-factory SFT系列教程 (二),大模型在自定义数据集 lora 训练与部署
文章目录 简介支持的模型列表2. 添加自定义数据集3. lora 微调4. 大模型 lora 权重,部署问题 参考资料 简介 文章列表: llama-factory SFT系列教程 (一),大模型 API 部署与使用llama-factory SFT系列教程 (二),大模型在自定义数…...
C语言游戏实战(11):贪吃蛇大作战(多人对战)
成果展示: 贪吃蛇(多人对战) 前言: 这款贪吃蛇大作战是一款多人游戏,玩家需要控制一条蛇在地图上移动,吞噬其他蛇或者食物来增大自己的蛇身长度和宽度。本游戏使用C语言和easyx图形库编写,旨在…...
腾讯测试岗位的面试经历与经验分享【一面、二面与三面】
腾讯两个月的实习一转眼就结束了,回想起当时面试的经过,感觉自己是跌跌撞撞就这么过了,多少有点侥幸.马上腾讯又要来校招了,对于有意愿想投腾讯测试岗位的同学们,写了一些那时候面试的经历和自己的想法,算不上经验,仅供参考吧! 一面 — —技术基础,全面…...
手机移动端网卡信息获取原理分析
有些场景我们需要获取当前手机上的网卡信息(如双卡双待、Wifi等)。本文准备研究一下这块的原理,以便更好的掌握相关技术原理。 1、底层系统接口 getifaddrs 使用 getifaddrs 接口可以达到我们的目的,该接口会返回本地所有网卡的信…...
OpenClaw任务编排:Qwen3-4B-Thinking-2507-GPT-5-Codex-Distill-GGUF处理依赖型工作流
OpenClaw任务编排:Qwen3-4B-Thinking-2507-GPT-5-Codex-Distill-GGUF处理依赖型工作流 1. 为什么需要任务编排 去年夏天,我接手了一个数据分析项目,需要定期从十几个网站抓取数据,清洗后生成分析报告,再邮件发送给团…...
Docker镜像管理全攻略:从拉取到自定义镜像的完整流程
Docker镜像管理全攻略:从拉取到自定义镜像的完整流程 容器技术正在重塑现代软件交付的范式。想象一下这样的场景:开发团队在本地构建的应用,无需任何修改就能在生产环境以完全相同的方式运行;运维人员不再需要为不同服务器的依赖冲…...
07_微服务划分与团队人数之渐进式拆分与团队演进
微服务划分与团队人数之渐进式拆分与团队演进 体系内容 演进方法:单体优先、边界识别、服务化拆分、平台能力沉淀 组织演进:小团队、部落-小队、平台团队、架构治理机制 Spring Cloud Alibaba 路线:Nacos、Gateway、Sentinel、RocketMQ、Seata 逐步引入 决策重点:什么时候…...
告别杂乱飞线!用Allegro约束管理器高效规划你的单片机板卡布局布线
告别杂乱飞线!用Allegro约束管理器高效规划你的单片机板卡布局布线 在单片机板卡设计中,工程师们常常面临一个共同的痛点:随着元件密度增加和信号速率提升,传统的"先布局后修补"模式会导致后期出现大量飞线交叉、电源噪…...
高速移动场景下无线信道的延迟-多普勒域建模与优化
1. 高速移动场景下的无线信道挑战 想象一下你正坐在时速120公里的高铁上刷视频,突然画面开始卡顿——这就是典型的高速移动场景通信问题。当收发端相对速度超过100km/h时,传统无线信道模型就会像老式收音机遇到隧道一样"失灵"。我在参与某车企…...
YOLOv11涨点改进| AAAI 2025 |自研创新首发、特征融合改进篇| 使用TAMoE任务自适应混合专家模块,多专家协同合作,各司其职,助力各种任务的目标检测,图像分割,多模态融合目标检测涨点
一、本文介绍 🔥本文给大家介绍使用 TAMoE任务自适应混合专家模块 改进YOLOv11网络模型,把原本固定的特征传递与融合方式改造成一种自适应的特征分配机制,使模型能够根据不同检测层和不同目标尺度的需求,动态选择更合适的特征组合来参与主干网络、颈部网络或检测头的融合…...
记录生活中的一件小事(佚名整理)
(转发需官方授权)记录生活中的一件小事(佚名整理)(佚名整理)记录生活中的一件小事,如果喊错了那才是麻烦事情的开始:曾经有一个人家里有两个姐姐,这个人上高中的时候和两…...
AGX Orin 部署PyTorch生态:从JetPack适配到torchvision编译避坑指南
1. AGX Orin开发环境初始化 刚拿到AGX Orin开发套件时,很多开发者会直接开始安装PyTorch,但往往忽略了基础环境配置的重要性。我去年在部署一个工业质检项目时就踩过这个坑——当时为了赶进度跳过了JetPack版本检查,结果导致后续torchvision编…...
IEEE旗下通信类期刊全解析:从影响因子看学术风向标(2023最新版)
IEEE通信类期刊2023全景透视:影响因子背后的学术趋势与选刊策略 翻开最新发布的《期刊引证报告》(JCR2023),IEEE旗下通信类期刊的影响因子变化再次成为学界热议焦点。作为全球最大的专业技术组织之一,IEEE出版的期刊向…...
5分钟搞懂阻抗匹配:从L型网络到Smith圆图实战指南(附ADS仿真步骤)
5分钟搞懂阻抗匹配:从L型网络到Smith圆图实战指南(附ADS仿真步骤) 引言:为什么阻抗匹配如此重要? 想象一下,你正在调试一块射频电路板,信号强度总是达不到预期。用频谱仪观察波形时,…...
