首页 > 其他分享 >H5 WebGL实现水波特效

H5 WebGL实现水波特效

时间:2023-07-11 16:36:59浏览次数:54  
标签:特效 WebGL float coord H5 vec2 texture2D uniform 水波

前言

零几年刚开始玩电脑的时候,经常在安装程序上看到一种水波特效,鼠标划过去的时候,就像用手在水面划过一样,感觉特别有意思。但是后来,就慢慢很少见过这种特效了。最近突然又想起了这种特效,于是开始折磨怎么实现这种效果。

思路

我们知道,水波的运动轨迹可以看成随时间变化的三角函数,那么我们可以记录每个水波形成的原点和运行时间,就能知道任一时刻水波的高度。但是,这种方法的运算量会随着水波数量而线性增长,当水波数量很多时,就很可能出现性能问题。

有没有一种办法,可以根据上一时刻的水波幅度,计算出下一时刻的水波幅度呢?如果对于一个点,如果我们把它与其周围的几个点的均值的差作为加速度运动,会怎样呢?

以二维平面为例,即加速度a有

a = (h(x-1) + h(x+1)) / 2 - h(x)

先用三角函数得到我们的水波的初始状态:

然后套用上面的公式把结果可视化

可见,水波会从中心想四周散开,这和我们平时看到的水波运动轨迹不正好相似吗?我们把它推导成3维的:

a = ( 
    h(x-1, y-1) + h(x-1, y+1) 
    + h(x+1, y-1) + h(x+1, y+1) 
    )/4 - h(x, y)

所以,我们只需要画出第一帧的水波图像,就能通过上面的公式计算出下一帧水波的图像了。

有了水波的图像,再根据冯氏光照模型去计算镜面光,就能模拟出较为真实的水波了。

先来看看最终效果:

<iframe allowfullscreen="true" border="0" frameborder="no" framespacing="0" height="400" scrolling="no" src="//player.bilibili.com/player.html?aid=658341685&bvid=BV12h4y1Z7wz&cid=1192523948&page=1" width="600"> </iframe>

在线体验地址:https://kason.site/

实现

首先,我们需要一个生成初始化水波的着色器

precision highp float;
const float PI = 3.141592653589793;
uniform sampler2D texture;
uniform vec2 centerCoord;
uniform float radius;
uniform float strength;			
varying vec2 coord;
void main() {
    vec4 info = texture2D(texture, coord);
    float d = min(distance(centerCoord, coord) / radius, 1.0);
    info.r += (cos(d * PI) * 0.5 + 0.5) * strength;
    gl_FragColor = info;
}

然后,再搞个更新水波的着色器

precision highp float;
uniform sampler2D texture;
uniform vec2 delta;
varying vec2 coord;
void main() {
    vec4 old = texture2D(texture, coord);
    vec2 dx = vec2(delta.x, 0.0);
    vec2 dy = vec2(0.0, delta.y);
    float avg = (
        texture2D(texture, coord - dx).r + texture2D(texture, coord - dy).r +
        texture2D(texture, coord + dx).r + texture2D(texture, coord + dy).r
    ) / 4.0;
    old.g += avg - old.r;
    old.g *= 0.995;
    old.r += old.g;
    gl_FragColor = old;
}

最后,再来个计算镜面光并完成最终渲染的着色器

precision highp float;
attribute vec2 vertex;
uniform vec2 ripplesRatio;
varying vec2 ripplesCoord;
varying vec2 backgroundCoord;
void main() {
    gl_Position = vec4(vertex, 0.0, 1.0);
    backgroundCoord = vertex * 0.5 + 0.5;
    ripplesCoord = backgroundCoord  * ripplesRatio;
}
`, `
precision highp float;
uniform sampler2D samplerBackground;
uniform sampler2D samplerRipples;
uniform vec2 delta;
uniform float perturbance;
varying vec2 ripplesCoord;
varying vec2 backgroundCoord;

void main() {
    float height = texture2D(samplerRipples, ripplesCoord).r;
    float heightX = texture2D(samplerRipples, vec2(ripplesCoord.x + delta.x, ripplesCoord.y)).r;
    float heightY = texture2D(samplerRipples, vec2(ripplesCoord.x, ripplesCoord.y + delta.y)).r;
    vec3 dx = vec3(delta.x, heightX - height, 0.0);
    vec3 dy = vec3(0.0, heightY - height, delta.y);
    vec2 v = normalize(vec2(1.0, 1.0));
    vec2 r = -normalize(cross(dy, dx)).xz;
    vec4 specular = vec4(0.8, 0.8, 0.8, 1) * pow(max(0.0, dot(v, r)), 5.0);
    gl_FragColor = texture2D(samplerBackground, backgroundCoord + r * perturbance) + specular;
}

至此,核心着色器的代码都写完了,只需要结合requestAnimationFrame调用WebGL接口完成最终渲染即可。

完整代码可以查看本人Github: https://github.com/kasonyang/ripples.js

标签:特效,WebGL,float,coord,H5,vec2,texture2D,uniform,水波
From: https://www.cnblogs.com/kason/p/17545125.html

相关文章

  • 广州H5开发如何提高用户留存率?
    随着当今互联网的发展,广州H5开发已经成为吸引用户的其中一个重要手段。但是仅仅只靠一个吸引人的H5页面来吸引用户访问是远远不够的,关键在于广州H5开发如何提高用户留存率,因此可以在设计开发的过程中采取一些策略和技巧。接下来,名锐讯动MRT将带大家探讨一些有效的广州H5开发的策略......
  • ios系统微信浏览器打开H5,调用接口status = 0失败的问题?
    最近写了一个很简单的小项目,以为不会有什么问题,今天突然说出问题了,说ios用户打开没有请求到数据。经测试,安卓,pc,都没有问题,只有ios出问题了。因为这次的涉及到时间,我以为ios时间处理上出问题了,仔细看了看,并不是,于是开启了漫长的寻找bug的过程。使用vConsole查看接口请求情况,发现......
  • 解决微信H5的图片缓存问题
    一、缓存可以解决什么问题?他的缺点是什么?1、缓存可以解决什么问题:减少不必要的网络传输,节约宽带更快的加载页面减少服务器负载,避免服务器过载的情况出现2、缓存的缺点:占内存,有些缓存会被存到内存中页面更新不及时,使用过时的图片、样式文件3、总结来说:开发阶段需要频......
  • 试一下粒子吸附特效
    试一下粒子吸附特效<scriptid="c_n_script"src="https://blog-static.cnblogs.com/files/xiaokang01/js.js"color="240,230,140"opacity="1"count="75"zindex="-2">if(/Android|webOS|iPhone|iPod|BlackBerr......
  • h5通过scheme地址唤起App或打开下载App的应用商店
    实现目标:可以在h5页面点击按钮唤起App,如果没有下载改App,则打开应用市场对应的APP的下载页面。实现步骤2步: 将打开App按钮设置为<a>标签,href值设置为App的scheme地址。   <a href='scheme' target='_self'/> 同时开启定时器,3-5秒后跳转对应的应用商店(后面会说明......
  • 视频素材批量剪辑,批量加特效的方法
    经常逛自媒体平台的小伙伴不难发现,要想原创的短视频更有创造性,内容更丰富,给视频添加特效效果算是比较常用的一个方法了。今天小编要分享的可不只是单一地给视频添加特效这么简单,我要给大家分享如何才能快速地批量给视频素材添加特效效果,一起来看看操作环节吧。在分享具体操作步骤之......
  • 小程序、APP、WEB、H5、UNIAPP通用的canvas导出图片,html转为图片多端通用版
    小程序、APP、WEB、H5、UNIAPP通用的canvas导出图片,html转为图片多端通用版 <canvasv-show="zhangdanImageShow" style="width:380px;height:500px;background-color:white;border-radius:5px;"canvas-id="postCanvars" id="postCanvars"&......
  • IOS下的微信H5页面的底部前进后退横栏如何隐藏
    header里增加<metaname="viewport"content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"/>重点:viewport-fit=cover加上后向下滚动时自动隐藏前进后退横栏,一定程度上解决了遮挡底部的问题,向上滚动后又会出现......
  • uni.app 给大家推荐一个 非常牛的 插件 上传图片 上传 word 上传xlsx 上传pdf
     插件地址地址:https://ext.dcloud.net.cn/plugin?name=lsj-upload兼容vue2 vue3微信小程序 等等等等图片放在下面了使用方法里面有介绍又到了码农 最重要的时刻了ctrlc  ctrlv  大法   ......
  • 微信小程序使用web-view 在web-view选择商品 跳回微信小程序里面支付 微信小程序跳
                  孩 你好  在微信公众平台添加web-view业务域名。 实现需求是  在web-view里面购买商品要支付的时候跳到小程序里面支付支付成功在回去跳到web-view订单页。 由于微信内置浏览器js-sdk不支持微信小程序支付,而且......