1. 程式人生 > >Unity3D Shader(17)——水的折射

Unity3D Shader(17)——水的折射

這裡引用的是蠻牛的Unity3D Shader的進階教程裡的程式碼。諮詢:qq254033230

這裡依然用的是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; }

這裡寫圖片描述

如果想最後的貼圖是隨著法線變化,那麼就要用到偏導數,計算每個頂點的動態法線。

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; }

以上還不算完美,可以加上漫反射,讓水的顏色隨著波紋變化。

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;
        }

最終的效果:
這裡寫圖片描述