前言:
业务需求需要这么一个效果,然后找各种方法,目前最和心意的两个:一个是js实现的效果,一个是shadertoy上的
本来是想将js的改成C#实现,写的太长太复杂了。看不下去。
然后就剩下搬运shadertoy的效果了,它还偏偏用到了bufferA,网上找了好久都没找到怎么搬运。然后就有了我的另一篇文章专门搬运shadertoy
目前效果是实现了,来写一篇分析下数学原理。
水波纹效果
水波纹效果
老外的一篇原理文章
搬运里的b站视频也可以参考

目标:鼠标点击位置产生一个涟漪
分析:
1.涟漪位置:将鼠标点击位置映射到纹理坐标上;
2.涟漪扩散:从涟漪位置呈圆形向四周扩散;
3.涟漪效果:在涟漪波动位置对纹理做偏移

看了几篇文章发现,缓存是必不可少的
围绕上下左右四个像素来计算当前点的像素。再乘上个衰减系数

 float ux = texture(iChannel0, vec2(uv.x+dx, uv.y)).x;float umx = texture(iChannel0, vec2(uv.x-dx, uv.y)).x;float uy = texture(iChannel0, vec2(uv.x, uv.y+dy)).x;float umy = texture(iChannel0, vec2(uv.x, uv.y-dy)).x;// new elevationfloat nu = u + du + 0.5*(umx+ux+umy+uy-4.0*u);nu = 0.99*nu;// store elevation and velocityfragColor = vec4(nu,nu-u,0.0,0.0);
#define HALFRESvoid mainImage( out vec4 fragColor, in vec2 fragCoord )
{vec2 res = iResolution.xy;res /= 2.;if( fragCoord.x > res.x || fragCoord.y > res.y )return;vec3 e = vec3(vec2(1.)/iResolution.xy,0.);//最小偏移vec2 q = fragCoord.xy/iResolution.xy;//映射vec4 c = texture(iChannel0, q);//当前位置采样float p11 = c.y;//采样y值g值//上下左右像素的 x值 r值float p10 = texture(iChannel0, q-e.zy).x;float p01 = texture(iChannel0, q-e.xz).x;float p21 = texture(iChannel0, q+e.xz).x;float p12 = texture(iChannel0, q+e.zy).x;float d = 0.;if (iMouse.z > 0.) {// Mouse interaction:vec2 m = iMouse.xy;m /= 2.;d = smoothstep(4.5,.5,length(m - fragCoord));//0-1}else{// Simulate rain dropsfloat t = iTime*2.;vec2 pos = fract(floor(t)*vec2(0.456665,0.708618))*res;//iResolution.xy;float amp = 1.-step(.05,fract(t));d = -amp*smoothstep(2.5,.5,length(pos - fragCoord.xy/2.));}// The actual propagation:d += (-(p11-.5)*2. + (p10 + p01 + p21 + p12 - 2.));d *= .99; // dampeningd *= float(iFrame>=2); // clear the buffer at iFrame < 2d = d*.5 + .5;// Put previous state as "y":fragColor = vec4(d, c.x, 0, 0);//d值
}
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{vec2 q = .5*fragCoord.xy/iResolution.xy;vec3 e = 0.5*vec3(vec2(1.)/iResolution.xy,0.);//d值 上下左右float p10 = texture(iChannel0, q-e.zy).x;float p01 = texture(iChannel0, q-e.xz).x;float p21 = texture(iChannel0, q+e.xz).x;float p12 = texture(iChannel0, q+e.zy).x;// Totally fake displacement and shading:vec3 grad = normalize(vec3(p21 - p01, p12 - p10, 1.));vec4 c = texture(iChannel1, fragCoord.xy*2./iChannelResolution[1].xy + grad.xy*.35);//贴图的采样偏移//莫名其妙的光照vec3 light = normalize(vec3(.2,-.5,.7));float diffuse = dot(grad,light);float spec = pow(max(0.,-reflect(light,grad).z),32.);fragColor = mix(c,vec4(.7,.8,1.,1.),.25)*max(diffuse,0.) + spec;//混合
}

涟漪在编辑器中问题:Maximize下速度快,非maximize和打包出来后涟漪速度慢。 应该是纹理分辨率的问题。
在Quality中将Texture Quality改成一半,发现打包后涟漪变快
心态崩了 速度还跟帧率有关

贴上完整代码:
shader 计算波纹数据:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'Shader "CalculateBuffer"{ Properties{iMouse ("Mouse Pos", Vector) = (100, 100, 0, 0)iChannel0("iChannel0", 2D) = "white" {}  iChannelResolution0 ("iChannelResolution0", Vector) = (100, 100, 0, 0)}CGINCLUDE    #include"UnityCG.cginc"   #pragma target 3.0#define vec2 float2#define vec3 float3#define vec4 float4#define mat2 float2x2#define mat3 float3x3#define mat4 float4x4#define iTime _Time.y//#define iGlobalTime _Time.y#define mod fmod#define mix lerp#define fract frac#define texture tex2D//#define texture2D tex2D#define iResolution _ScreenParams#define gl_FragCoord ((_iParam.scrPos.xy/_iParam.scrPos.w) * _ScreenParams.xy)#define PI2 6.28318530718#define pi 3.14159265358979#define halfpi (pi * 0.5)#define oneoverpi (1.0 / pi)float4 iMouse;sampler2D iChannel0;fixed4 iChannelResolution0;struct v2f {    float4 pos : SV_POSITION;    float4 scrPos : TEXCOORD0;   };              v2f vert(appdata_base v) {  v2f o;o.pos = UnityObjectToClipPos (v.vertex);o.scrPos = ComputeScreenPos(o.pos);return o;}  vec4 main(vec2 fragCoord);fixed4 frag(v2f _iParam) : COLOR0 { vec2 fragCoord = gl_FragCoord;return main(gl_FragCoord);}  vec4 main(vec2 fragCoord) {vec2 res = iResolution.xy;//渲染目标的分辨率res *= 0.5;if( fragCoord.x > res.x || fragCoord.y > res.y )discard;vec3 e = vec3(vec2(1,1)/iResolution.xy,0.);//最小偏移量vec2 q = fragCoord.xy/iResolution.xy;//0-1映射  这里只映射了分辨率的xy的一半vec4 c = texture(iChannel0, q);//这里采样也是xy的一半 即1/4float p11 = c.y;//y值   g值//上下左右点的x值float p10 = texture(iChannel0, q-e.zy).x;float p01 = texture(iChannel0, q-e.xz).x;float p21 = texture(iChannel0, q+e.xz).x;float p12 = texture(iChannel0, q+e.zy).x;float d = 0.;if (iMouse.z > 0.) {// Mouse interaction:vec2 m = iMouse.xy;m /= 2.;//平滑过渡  在 【0.5,4.5】之间获取【1,0】d = smoothstep(1.5,0.5,length(m - fragCoord));}else{// Simulate rain dropsfloat t = iTime*2.;vec2 pos = fract(floor(t)*vec2(0.456665,0.708618))*res;//iResolution.xy/2;float amp = 1.-step(.05,fract(t));d = -amp*smoothstep(.9,.5,length(pos - fragCoord.xy/2.));}// The actual propagation:((-(p11-.5)*2.)【-1,1】d += (-(p11-.5)*2. + (p10 + p01 + p21 + p12 - 2.));//波纹模拟的计算方式d *= .99; // dampening//衰减//  d *= float(iFrame>=2); // clear the buffer at iFrame < 2d = d*.5 + .5;//再转换成【0-1】// Put previous state as "y"://fragColor =;return  vec4(d, c.x, 0, 0);//x是扰动后的x值,y是原来x值}ENDCG    SubShader {    Pass {    CGPROGRAM    #pragma vertex vert#pragma fragment frag#pragma fragmentoption ARB_precision_hint_fastestENDCG    }    }     FallBack Off
}

shader 混合数据和纹理

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'Shader "BlenderShader"{ Properties{iMouse ("Mouse Pos", Vector) = (100, 100, 0, 0)iChannel0("iChannel0", 2D) = "white" {}  iChannel1("iChannel1", 2D) = "white" {} iChannelResolution0 ("iChannelResolution0", Vector) = (100, 100, 0, 0)iChannelResolution1 ("iChannelResolution1", Vector) = (100, 100, 0, 0)_AddLight("AddLight",Color)=(0.1,0.1,0.1,1)}CGINCLUDE    #include"UnityCG.cginc"   #pragma target 3.0#define vec2 float2#define vec3 float3#define vec4 float4#define mat2 float2x2#define mat3 float3x3#define mat4 float4x4#define iTime _Time.y//#define iGlobalTime _Time.y#define mod fmod#define mix lerp#define fract frac#define texture tex2D//#define texture2D tex2D#define iResolution _ScreenParams#define gl_FragCoord ((_iParam.scrPos.xy/_iParam.scrPos.w) * _ScreenParams.xy)#define PI2 6.28318530718#define pi 3.14159265358979#define halfpi (pi * 0.5)#define oneoverpi (1.0 / pi)fixed4 iMouse;sampler2D iChannel0;fixed4 iChannelResolution0;sampler2D iChannel1;fixed4 iChannelResolution1;fixed4 _AddLight;struct v2f {    float4 pos : SV_POSITION;    float4 scrPos : TEXCOORD0;   };              v2f vert(appdata_base v) {  v2f o;o.pos = UnityObjectToClipPos (v.vertex);o.scrPos = ComputeScreenPos(o.pos);return o;}  vec4 main(vec2 fragCoord);fixed4 frag(v2f _iParam) : COLOR0 { vec2 fragCoord = gl_FragCoord;return main(gl_FragCoord);}  vec4 main(vec2 fragCoord) {vec2 q = .5*fragCoord.xy/iResolution.xy;  // bufferA保存的是xy的一半所以用1/4映射到分辨率vec3 e = 0.5*vec3(vec2(1,1)/iResolution.xy,0.);//1/4后的偏移//取到bufferA中数据扰动数据float p10 = texture(iChannel0, q-e.zy).x;float p01 = texture(iChannel0, q-e.xz).x;float p21 = texture(iChannel0, q+e.xz).x;float p12 = texture(iChannel0, q+e.zy).x;//因为bufferA中的扰动数据x    可以看做是波的上下偏移量  所以 p21-p01  p12-p10为 偏移方向// Totally fake displacement and shading:vec3 grad = normalize(vec3(p21 - p01, p12 - p10, 1.));vec4 c = texture(iChannel1, fragCoord.xy*1./iChannelResolution1.xy + grad.xy*0.35);//去采样偏移位置的颜色vec3 light = normalize(vec3(.2,-.5,.7));//光 为啥光的方向是这边?float diffuse = dot(grad,light);//漫反射float spec = pow(max(0.,-reflect(light,grad).z),32.);//高光//fragColor = mix(c,vec4(.7,.8,1.,1.),.25)*max(diffuse,0.) + spec;//混合颜色()return mix(c,vec4(.7,.8,1.,1.),.05)*max(diffuse,0.) + spec +_AddLight;}ENDCG    SubShader {    Pass {    CGPROGRAM    #pragma vertex vert#pragma fragment frag#pragma fragmentoption ARB_precision_hint_fastestENDCG    }    }     FallBack Off
}

逻辑控制代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class NewWater : MonoBehaviour
{//shader计算缓存public RenderTexture bufferA;public RenderTexture tempRT;public RenderTexture xxx;public Texture _Texture;//采用直接挂shader的方式了//public RenderTexture ShowRT;//public Shader blendShader;//public Material blendMat;public Shader bufferShader;public Material bufferMat;public Camera mainCamera;public RawImage image;// Start is called before the first frame updatevoid Start(){Application.targetFrameRate = 200;mainCamera = Camera.main;bufferA = CreateRT();tempRT = CreateRT();//  ShowRT = CreateRT();bufferMat = new Material(bufferShader);//  blendMat = new Material(blendShader);// image.texture = ShowRT;GetComponent<Renderer>().material.SetTexture("iChannel0", bufferA);GetComponent<Renderer>().material.SetTexture("iChannel1", xxx);}// Update is called once per framevoid Update(){if (Input.GetMouseButton(0)){DrawAt(Input.mousePosition.x, Input.mousePosition.y, 1);// Debug.Log(Input.mousePosition.x);//Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);//RaycastHit hit;//if(Physics.Raycast(ray,out hit))//{//    DrawAt(Input.mousePosition.x, Input.mousePosition.y, 1);//    Debug.Log(Input.mousePosition.x);//    // DrawAt(hit.textureCoord.x, hit.textureCoord.y,1);//}}else{DrawAt(100, 100, 0);}//blendMat.SetTexture("iChannel0", bufferA);//blendMat.SetTexture("iChannel1", _Texture);//Graphics.Blit(null, ShowRT, blendMat);//通过涟漪计算shader 将数据保存在tempRT中Graphics.Blit(TempRT, PrevRT);RenderTexture rt = PrevRT;PrevRT = CurrentRT;CurrentRT = rt;}public void DrawAt(float x,float y,float z){bufferMat.SetTexture("iChannel0", bufferA);bufferMat.SetVector("iMouse", new Vector4(x, y,z));//通过drawMat shader将数据存储在TempRT中   类似于shadertoy中的输出到buffer中Graphics.Blit(null, tempRT, bufferMat);RenderTexture rt = tempRT;tempRT = bufferA;bufferA = rt;}public RenderTexture CreateRT(){RenderTexture rt = new RenderTexture(1920, 1080, 0, RenderTextureFormat.ARGBFloat)//new RenderTexture(1920, 1080, 0, RenderTextureFormat.ARGB32);rt.Create();return rt;}}

普通的Shader-水涟漪效果相关推荐

  1. 震惊!原来Android OpenGL ES可以这样用,实现 (水波纹)涟漪效果超惊艳!

    用几行代码实现惊艳的特效. 作者:字节流动 链接:https://juejin.im/post/5ed9c9445188254344768bd6 水波纹效果原理 最近一个做视频滤镜的朋友,让我给他做一 ...

  2. OpenGL ES 实现动态(水波纹)涟漪效果

    该原创文章首发于微信公众号:字节流动 水波纹效果原理 最近一个做视频滤镜的朋友,让我给他做一个动态水波纹效果,具体就是:点击屏幕上的某一位置,然后波纹以该位置为中心向周围扩散.接到这个需求,一开始就尝 ...

  3. 用shader做水波纹效果

    用shader做水波纹效果 1.效果展示: 2.代码: shader代码: Shader "Unlit/Water" {Properties{_MainTex("Text ...

  4. shader graph落在地面的水滴涟漪效果制作思路

    (以下内容为不知什么地方看来的教学视频后的复盘整理笔记.) 0思路:在现有的材质上添加一个涟漪序列帧动画作为nomal输出,做出序列帧动画,控制大小,虚实让它看起来更自然 1:水面涟漪首先需要一个反射 ...

  5. html5 水波式按钮_css3+jQuery实现按钮水波纹效果

    水波纹按钮 /*自定义按钮样式*/ .btns{ height: 30px; line-height: 30px; text-align: center; width: 200px; color: # ...

  6. UE4 Material 101学习笔记——23-29 水涟漪/水深/折射反射/Gerstner海浪/波光焦散/泡沫/FlowMap

    UE4 Material 101学习笔记--23-29 水涟漪/水深/折射反射/Gerstner海浪/波光焦散/泡沫/FlowMap Lec23 水的表面涟漪 Water Ripples Shader ...

  7. css波纹波动效果,CSS 冲击波(水波纹)效果

    实现冲击波--数学知识很重要 *{ margin:0; padding:0; box-sizing:border-box; } html,body{ font-family:"微软雅黑&qu ...

  8. Android 水波效果 | 涟漪效果 实现

    在Xml 里面实现 给Button设置一个background <Buttonandroid:text="Ripple水波纹Background"android:layout ...

  9. Android点击水波纹扩散效果整理(附带一个自定义的水波纹效果控件)

    很久很久没有写博客了,说来也有点惭愧.正好最近整理自己的项目工程目录,看到一些值得分享的控件,准备在之后的几篇博客中准备把它们陆续搬运上来. 这篇博客准备整理一下Android Material De ...

最新文章

  1. iphone html5直播,【小技巧】解决iPhone中video视频的行内播放
  2. 超好:web app变革之rem
  3. 激动人心!柳叶刀杂志执行主编回柳叶刀烧烤吃烧烤了!
  4. 计算机仿真在电力领域的应用,仿真技术在电力系统中的应用实例
  5. python读取tiff文件进行波段计算_python+tifffile之tiff文件读写方式
  6. 机器学习笔记七之机器学习诊断
  7. hibernate 联合主键
  8. 是什么浪费了运维的工作时间?
  9. linux远程配置ssh服务,Linux远程服务之OpenSSH配置
  10. java数据类型简介
  11. 重新学习FPGA(一):EDA技术
  12. excel设置下拉菜单多选_如何设置多选Excel下拉菜单
  13. IBX 常见问题解答(译)
  14. Spacy 常见词性标注
  15. 计算机毕业设计springboot+vue基本微信小程序的考试系统
  16. 家喻户晓的足力健,凭什么征服中老年人?
  17. R语言学习笔记(四)--数据结构
  18. 【NOIP or 省选】Melancholy ——线段树+容斥原理
  19. java科技说明文范文800_说明文范文:生活因成功而精彩
  20. Markdown-img使用指南

热门文章

  1. apolloconfig分布式部署
  2. linux execl函数讲解,Linux下execl函数学习
  3. Android调用系统相机程序
  4. MATLAB三维绘图基础meshgrid函数的用法解析
  5. R语言—豆瓣搜索电影
  6. 语义分割算法Mask RCNN论文解读
  7. Bert-pytorch-英文文本多分类
  8. 一位程序员工作10年总结的13个忠告,却让很多人惋惜
  9. 华为路由器、H3C交换机和TPLINK无线路由器组建无线网
  10. iPhone软件开发之多线程初步