Unity3D Shader——水的折射

这里依然用的是vertex 和fragment shader来解决水的反射的问题。

首先,准备两个平面,一个平面作为底图,一个平面模拟水的波动。这里要用到抓取底图的通道 GrabPass{}。然后把抓取的通道图放到水面的那张图上。另外一个难点就是要模拟水的波动,水的波动的原理如下图: 
这里写图片描述

其中顶点函数代码和片段函数代码如下:
v2f vert(appdata v){
         float w=2*3.1415926/_L;
         float f=_S*w;

         v.vertex.y+=_A*sin(v.vertex.xz*w+_Time.x*f);

         v2f o;
         o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
         o.uv=TRANSFORM_TEX(v.uv,_MainTex);
         o.proj=ComputeGrabScreenPos(o.pos);
         return o;
        }

        float4 frag(v2f IN):SV_Target{
        IN.proj.xy+=0.01*sin(IN.proj.xy*3.14*10+_Time.y*2);
        float4 col=tex2Dproj(_GrabTexture,IN.proj)*0.5;
        return col;
        }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

这里写图片描述

如果想最后的贴图是随着法线变化,那么就要用到偏导数,计算每个顶点的动态法线。

v2f vert(appdata v){
         float w=2*3.1415926/_L;
         float f=_S*w;

         v.vertex.y+=_A*sin(-length(v.vertex.xz)*w+_Time.x*f);
         float dx=_A*v.vertex.x*w*cos(-length(v.vertex.xz)*w+_Time.x*f);
         float dz=_A*v.vertex.z*w*cos(-length(v.vertex.xz)*w+_Time.x*f);

         float3 B=normalize(float3(1,dx,0));
         float3 T=normalize(float3(0,dz,1));

         v2f o;
         o.N=cross(B,T);
         o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
         o.uv=TRANSFORM_TEX(v.uv,_MainTex);
         o.proj=ComputeGrabScreenPos(o.pos);
         return o;
        }

        float4 frag(v2f IN):SV_Target{
        float d=dot(IN.N,float3(0,1,0));
        IN.proj.xy+=d*0.1;
        //IN.proj.xy+=0.01*sin(IN.proj.xy*3.14*10+_Time.y*2);
        float4 col=tex2Dproj(_GrabTexture,IN.proj)*0.5;
        return col;
        }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

以上还不算完美,可以加上漫反射,让水的颜色随着波纹变化。

v2f vert(appdata v){
         float w=2*3.1415926/_L;
         float f=_S*w;

         v.vertex.y+=_A*sin(-length(v.vertex.xz)*w+_Time.x*f);
         float dx=_A*v.vertex.x*w*cos(-length(v.vertex.xz)*w+_Time.x*f);
         float dz=_A*v.vertex.z*w*cos(-length(v.vertex.xz)*w+_Time.x*f);

         float3 B=normalize(float3(1,dx,0));
         float3 T=normalize(float3(0,dz,1));

         v2f o;
         o.N=cross(B,T);
         o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
         o.uv=TRANSFORM_TEX(v.uv,_MainTex);
         o.proj=ComputeGrabScreenPos(o.pos);
         return o;
        }

        float4 frag(v2f IN):SV_Target{
        float3 ncol=UnpackNormal(tex2D(_MainTex,IN.uv+_Time.x))*0.3;
        IN.N=IN.N+ncol;

        float d=dot(IN.N,float3(0,1,0));
        float diff=max(0,dot(IN.N,float3(1,0,0)));  //漫反射
        IN.proj.xy+=d*0.1;
        //IN.proj.xy+=0.01*sin(IN.proj.xy*3.14*10+_Time.y*2);
        float4 col=tex2Dproj(_GrabTexture,IN.proj)*(0.3+diff);
        return col;
        }
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

最终的效果: 
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值