unity-shader 水的效果WaterEffect

1.水实现的效果:用到的知识点有点多。
(1)水的深浅影响透明度和颜色,浅处能看到水底:深度图
(2)反射和折射:菲涅尔,GrabPass截屏,cubeMap,噪声贴图
(3)水面波纹荡漾:切线空间法线扰动
(3)高光和漫反射:diffuse 和 specular
(4)波浪:切线空间法线扰动
(5)水的半透明:Transparent
效果图:(最后附百度云demo资源)
在这里插入图片描述![在这里插入图片描述](https://img-blog.csdnimg.cn/20200521010408620.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2pzMDkwNw==,size_16,color_FFFFFF,t_70

Shader "Unlit/water_unitl"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _WaterColor01("water Color 01",Color)=(1,1,1,1)
        _WaterColor02("water Color 02",Color)=(1,1,1,1)
        _TranAmount("TransAmount",Range(0,100))=5
        _DepthRange("Depth Range",Range(1,100))=1
        // bumpMap
        _NormalTex ("bump map",2D) = "bump" {}
        _WaterSpeed("Water speed",float) = 5
        _BumpSacle("bump scale",float) = 1
        _Specular ("Specualr",Color) = (1,1,1,1)
        _Gloss("Gloss",Range(0,256))=8
        //波浪
        _WaveTex("WaveTex",2D) = "white" {}
        _NoiseTex("Noise",2D) = "white" {}
        _WaveSpeed("Wave speed",float) = 1
        _WaveRange("wave range",float) = 0.5
        _WaveRangeA("wave rangeA",float) = 1
        _WaveDetal("wave offset  Detal",float) = 0.5
        // grabpass
        _Distortion("Distortion",float) = 1
        // cubemap
        _CubeMap("CubeMap",Cube) = "SkyBox"{}
        _FresnelSacle("Fresnel Sacle",float) = 1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue"="Transparent"}
        LOD 100
        Blend SrcAlpha OneMinusSrcAlpha
        ZWrite off
        GrabPass {"_GrabPassTex"}
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag


            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #include "AutoLight.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D_float _CameraDepthTexture;
            fixed4 _WaterColor01;
            fixed4 _WaterColor02;
            float _TranAmount;
            float _DepthRange;
            sampler2D _NormalTex;
            float4 _NormalTex_ST;
            float _BumpSacle;
            float _WaterSpeed;
            float4 _Specular;
            float _Gloss;
            sampler2D _WaveTex; float4 _WaveTex_ST;
            sampler2D _NoiseTex; float4 _NoiseTex_ST;
            float _WaveSpeed;
            float _WaveRange;
            float _WaveRangeA;
            float _WaveDetal;
            sampler2D _GrabPassTex;
            float4 _GrabPassTex_TexelSize;
            float _Distortion;
            samplerCUBE _CubeMap;
            float _FresnelSacle;
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;                
                float4 pos : SV_POSITION;
                float4 proj : TEXCOORD1;
                float2 uv_NormalTex : TEXCOORD2;
                float4 TtoW0 : TEXCOORD3;
                float4 TtoW1 : TEXCOORD4;
                float4 TtoW2 : TEXCOORD5;
                LIGHTING_COORDS(6,7) //阴影+衰减
                float2 uv_WaveTex : TEXCOORD8;
                float2 uv_NoiseTex : TEXCOORD9;
            };



            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.uv_NormalTex = TRANSFORM_TEX(v.uv, _NormalTex);
                o.uv_WaveTex = TRANSFORM_TEX(v.uv, _WaveTex);
                o.uv_NoiseTex = TRANSFORM_TEX(v.uv, _NoiseTex);
                o.proj = ComputeScreenPos(o.pos);
                COMPUTE_EYEDEPTH(o.proj.z);

                float3 worldPos = mul(unity_ObjectToWorld,v.vertex);
                float3 tangent = UnityObjectToWorldDir(v.tangent.xyz);
                float3 normal = UnityObjectToWorldNormal(v.normal);
                float3 biTangent = cross(tangent,normal) * v.tangent.w;
                o.TtoW0 = fixed4(tangent.x,biTangent.x,normal.x,worldPos.x);
                o.TtoW1 = fixed4(tangent.y,biTangent.y,normal.y,worldPos.y);
                o.TtoW2 = fixed4(tangent.z,biTangent.z,normal.z,worldPos.z);
                //包含光照衰减和阴影				
                TRANSFER_VERTEX_TO_FRAGMENT(o);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                half depth = LinearEyeDepth(tex2Dproj(_CameraDepthTexture,UNITY_PROJ_COORD(i.proj)).r);
                half deltaDepth = depth - i.proj.z;

                // sample the textureUNITY_PROJ_COORD()i.proj
                fixed4 col = lerp(_WaterColor01,_WaterColor02,min(_DepthRange,deltaDepth)/_DepthRange); //tex2D(_MainTex, i.uv);
                col.a = min(_TranAmount,deltaDepth)/_TranAmount;// col.a * _TranAmount;

                // normal
                float4 bumpOffset1 = tex2D(_NormalTex,i.uv_NormalTex + float2(_WaterSpeed * _Time.y,0));
                float4 bumpOffset2 = tex2D(_NormalTex,float2( 1 - i.uv_NormalTex.y,i.uv_NormalTex.x) + float2(_WaterSpeed * _Time.y/10,0));
                float4 offsetColor = (bumpOffset1 + bumpOffset2)/2;
                float3 normal = UnpackNormal(offsetColor);
                normal.xy *= _BumpSacle;                
                float4 bumpColor1 = tex2D(_NormalTex,i.uv_NormalTex + normal.xy + float2(_WaterSpeed * _Time.y,0));
                float4 bumpColor2 = tex2D(_NormalTex,float2( 1 - i.uv_NormalTex.y,i.uv_NormalTex.x) + normal.xy + float2(_WaterSpeed * _Time.y/10,0));
                normal = UnpackNormal((bumpColor1 + bumpColor2)/2).xyz;
                fixed2 offset = normal.xy;
                normal = normalize(half3(dot(i.TtoW0.xyz,normal),dot(i.TtoW1.xyz,normal),dot(i.TtoW2.xyz,normal)));
                
                //光照参数
                float3 worldPos = float3(i.TtoW0.w,i.TtoW1.w,i.TtoW2.w);
                float3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));
                float3 worldLightDir = normalize(UnityWorldSpaceLightDir(worldPos));
                float3 halfDir = normalize(worldLightDir + worldViewDir);
                //包含光照衰减以及阴影,但是base光源一般没有衰减
				UNITY_LIGHT_ATTENUATION(atten, i, worldPos);
                float3 diffuseFactor = max(0, dot(normal,worldLightDir));
                float3 specualrFactor = pow(max(0,dot(normal,halfDir)),_Gloss);
                col.rgb = atten * (col.rgb * _LightColor0.rgb * diffuseFactor + _Specular.rgb * specualrFactor * _LightColor0.rgb);
                col.a = col.a + _Specular.a * specualrFactor;

                // 波浪
                float waveA = 1 - min(_WaveRangeA,deltaDepth) / _WaveRangeA; 

                fixed4 noiseColor = tex2D(_NoiseTex,i.uv_NoiseTex);
                fixed4 waveColor1 = tex2D(_WaveTex,float2(waveA + _WaveRange * sin(_Time.x * _WaveSpeed + noiseColor.r),1 )+ offset);
                waveColor1.rgb *= (1-(sin(_Time.x * _WaveSpeed + noiseColor.r)+1)/2) * noiseColor.r;
                fixed4 waveColor2 = tex2D(_WaveTex,float2(waveA + _WaveRange * sin(_Time.x * _WaveSpeed + _WaveDetal + noiseColor.r),1)+offset);
                waveColor2.rgb *= (1-sin(_Time.x * _WaveSpeed + _WaveDetal + noiseColor.r)+1)/2 * noiseColor.r; 
                col.rgb = col.rgb + (waveColor1.rgb + waveColor2.rgb) * waveA;
                //grabpass计算折射
                //对屏幕图像的采样坐标进行偏移
				//选择使用切线空间下的法线方向来进行偏移是因为该空间下的法线可以反映顶点局部空间下的法线方向
                offset = offset * _Distortion * _GrabPassTex_TexelSize.xy;
                //对scrPos偏移后再透视除法得到真正的屏幕坐标
                i.proj.xy = offset * i.proj.z + i.proj.xy;
                fixed3 refraCol = tex2D(_GrabPassTex,i.proj.xy/i.proj.w).rgb;
                
                //反射
                fixed3 reflectDir = reflect(-worldViewDir,normal);
                fixed3 reflection = texCUBE(_CubeMap,reflectDir);
                fixed3 fresnel = _FresnelSacle + (1-_FresnelSacle) * pow(1 - dot(worldViewDir,normal),5);
                fixed3 refraAndRefle = lerp(reflection,refraCol,fresnel);
                col.rgb *= refraAndRefle;
                return col;
            }
            ENDCG
        }
    }
}

百度云:链接: https://pan.baidu.com/s/1GcPiJpRXJMzskUNbcbkTXA 提取码: 9yhk
环境是unity2019.2.12f1

  • 6
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值