用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 接口可以达到我们的目的,该接口会返回本地所有网卡的信…...
LLM提示词工程实战:开源模板库与浏览器扩展提升AI对话效率
1. 项目概述:一个为大型语言模型准备的“提示词武器库”如果你和我一样,日常工作中需要频繁地与ChatGPT、Claude、文心一言这类大型语言模型打交道,那你一定有过这样的体验:同一个问题,换种问法,得到的答案…...
QKeyMapper:5个技巧让你在Windows上实现零重启的按键映射
QKeyMapper:5个技巧让你在Windows上实现零重启的按键映射 【免费下载链接】QKeyMapper [按键映射工具] QKeyMapper,Qt开发Win10&Win11可用,不修改注册表、不需重新启动系统,可立即生效和停止。支持游戏手柄映射到键鼠…...
要想口腔溃疡好的快,认准这个方法 口腔溃疡 硬核健康科普行动 口疮 醋酸地塞米松口腔贴片——这个确实可以止痛,大家觉得呢,还有更好的药物吗?
要想口腔溃疡好的快,认准这个方法 口腔溃疡 硬核健康科普行动 口疮 醋酸地塞米松口腔贴片——这个确实可以止痛,大家觉得呢,还有更好的药物吗? 要想口腔溃疡好的快,认准这个方法 口腔溃疡 硬核健康科普行动 口疮 醋酸地…...
AI自动化报告生成:从数据到文档的智能解决方案
1. 项目概述:告别手动填表,让AI帮你写报告如果你和我一样,每周、每月都要花上几个小时,对着Excel表格和PPT模板,绞尽脑汁地“攒”出一份商务报告,那么今天分享的这个工具,可能会让你眼前一亮。它…...
AIDD开源框架harness:模块化设计加速AI药物发现全流程
1. 项目概述:当药物研发遇上AI,一个开源框架的诞生在生物医药领域,药物研发一直是一项周期漫长、成本高昂且充满不确定性的“探险”。从靶点发现到最终上市,平均需要超过10年时间和数十亿美元的投入,而失败率却高得惊人…...
G-Helper完整指南:如何用这个免费工具让你的华硕笔记本性能飙升300%?
G-Helper完整指南:如何用这个免费工具让你的华硕笔记本性能飙升300%? 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProA…...
如何为 Linux 之父,打造一台让他满意的最强主机?
今天在B站刷到了一个堪称 “世纪同框” 的视频,我关注的 LTT 频道,请来了 Linux 和 Git 之父——Linus Torvalds 本尊! 这绝对是每个技术宅的梦想时刻:当科技圈最能“整活”的 Linus,遇上最硬核的 Linus,他…...
生成式AI在软件质量保障中的应用:从测试生成到智能维护
1. 生成式AI如何重塑软件质量保障的底层逻辑在软件开发的漫长周期里,质量保障(SQA)一直是那个既关键又繁重的环节。传统上,它高度依赖工程师的经验、严谨的流程和大量重复性的人工操作——从编写测试用例、执行回归测试࿰…...
ARM ITS寄存器架构与中断翻译机制详解
1. ARM ITS寄存器架构概述在ARMv8/v9架构中,中断翻译服务(Interrupt Translation Service, ITS)是通用中断控制器(GIC)的关键组件,负责将设备产生的中断事件(EventID)转换为对应的LPI(Locality-specific Peripheral Interrupt)中断。ITS通过一组精心设计…...
2026年5月9日 8 个国外小项目背后,真正能卖钱的是“窄需求”
今天不追 AI 风口:8 个国外小项目背后,真正能卖钱的是“窄需求” 日期:2026年5月9日 栏目定位:只拆具体国外项目、帖子、工具和需求信号。不是项目搬运,也不是副业鸡汤,而是判断:这个信号背后有…...
