Gerstner wave

Shader "Unlit/GerstnerWaveStandard"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        [Header(BaseShading)]
        _BaseMap ("Example Texture", 2D) = "white" { }
        [HDR]_BaseColor ("Base Colour", Color) = (0, 0.66, 0.73, 1)
        _WaterFogColor ("Water Fog Colour", Color) = (0, 0.66, 0.73, 1)
        _FogDensity ("Fog Density", range(0, 1)) = 0.1
        _NormalMap ("Normal Map", 2D) = "white" { }
        _NormalScale ("Normal Scale", Range(0, 1)) = 0.1
        _Shininess ("High Light Roughness", Range(0, 0.1)) = 0.01
        [Space(20)]
        [Header(Reflection)]
        _Skybox ("Skybox", Cube) = "white" { }
        [Header(Refractive)]
        _AirRefractiveIndex ("Air Refractive Index", Float) = 1.0
        _WaterRefractiveIndex ("Water Refractive Index", Float) = 1.333
        _FresnelPower ("Fresnel Power", Range(0.1, 50)) = 5
        _RefractionStrength ("Refraction Strength", Range(0, 1)) = 0.1
        
        [Space(20)]
        [Header(SSS)]
        _FrontSubsurfaceDistortion ("Front Subsurface Distortion", Range(0, 1)) = 0.5
        _BackSubsurfaceDistortion ("Back Subsurface Distortion", Range(0, 1)) = 0.5
        _FrontSSSIntensity ("Front SSS Intensity", float) = 0.2
        _HeightCorrection ("SSS Height Correction", float) = 6
        
        [Space(20)]
        [Header(Foam)]
        _FoamIntensity ("Foam Intensity", float) = 0.5
        _FoamNoiseTex ("Foam Noise", 2D) = "white" { }
        
        [Space(20)]
        [Header(Caustic)]
        _CausticIntensity ("Caustic Intensity", float) = 0.5
        _CausticTex ("Caustic Texture", 2D) = "white" { }
        _Caustics_Speed ("Caustics Speed,(x,y)&(z,w)", Vector) = (1, 1, -1, -1)
        
        [Space(20)]
        [Header(Waves)]
        _Speed ("Speed", float) = 0.2
        _Frequency ("Frequency", float) = 2
        _WaveA ("Wave A (dir, steepness, wavelength)", Vector) = (1, 0, 0.5, 10)
        _WaveB ("Wave B", Vector) = (0, 1, 0.25, 20)
        _WaveC ("Wave C", Vector) = (1, 1, 0.15, 10)
        _WaveD ("Wave D", Vector) = (0, 1, 0.25, 20)
        _WaveE ("Wave E", Vector) = (1, 1, 0.15, 10)
        _WaveF ("Wave F", Vector) = (0, 1, 0.25, 20)
        _WaveG ("Wave G", Vector) = (1, 1, 0.15, 10)
        _WaveH ("Wave H", Vector) = (0, 1, 0.25, 20)
        _WaveI ("Wave I", Vector) = (1, 1, 0.15, 10)
        _WaveJ ("Wave J", Vector) = (1, 1, 0.15, 10)
        _WaveK ("Wave K", Vector) = (1, 1, 0.15, 10)
        _WaveL ("Wave L", Vector) = (1, 1, 0.15, 10)
        [Space(20)]
        [Header(Tessellation)]
        _TessellationUniform ("Tessellation Uniform", Range(1, 64)) = 1
        _TessellationEdgeLength ("Tessellation Edge Length", Range(5, 100)) = 50
        [Toggle(_TESSELLATION_EDGE)]_TESSELLATION_EDGE ("TESSELLATION EDGE", float) = 0



        [Space(20)]
        [Header(Others)]
        _shadowAttenuation("shadowAttenuation",float)=0.2
        _CameraOpaqueTexture("_CameraOpaqueTexture",2D)="white"{}
    }
    SubShader
    {
        Tags { "RenderType" = "Transparent"  "RenderQueue" = "Transparent" }
        
        ZWrite Off
        ZTest On
        CGPROGRAM
        #include "Lighting.cginc"
        #include "unityCg.cginc"
        float4 _BaseMap_ST, _FoamNoiseTex_ST, _CausticTex_ST;
        float4 _BaseColor, _WaterFogColor, _Caustics_Speed;
        float4 _NormalMap_ST;
        float4 _WaveA, _WaveB, _WaveC, _WaveD, _WaveE, _WaveF, _WaveG, _WaveH, _WaveI, _WaveJ, _WaveK, _WaveL;
        float _Speed, _Frequency, _NormalScale, _AirRefractiveIndex, _WaterRefractiveIndex, _FresnelPower;
        float _RefractionStrength, _FogDensity, _Shininess, _FrontSubsurfaceDistortion, _BackSubsurfaceDistortion;
        float _FrontSSSIntensity, _HeightCorrection, _FoamIntensity, _CausticIntensity;
        ENDCG

        Pass
        {
            Name "Example"
            Tags { "LightMode" = "ForwardBase" }
            
            ZWrite off
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
           // #pragma multi_compile_fog

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

            struct a2v
            {
                float4 positionOS: POSITION;
                float2 uv: TEXCOORD0;
                float3 normal: NORMAL;
                float4 color: COLOR;
            };

            struct v2f
            {
                float4 positionCS: SV_POSITION;
                float2 uv: TEXCOORD0;
                float3 normalWS: TEXCOORD1;
                float3 positionWS: TEXCOORD2;
                float3 tangentWS: TEXCOORD3;
                float4 scrPos: TEXCOORD4;
                float heightOS: TEXCOORD5;
                float fogFactor: TEXCOORD6;
                float4 color: COLOR;
            };

            samplerCUBE _Skybox;
            float4 _Skybox_ST;
            sampler2D _CameraOpaqueTexture;
            float4 _CameraOpaqueTexture_ST;
            sampler2D _FoamNoiseTex;
            float2 _FoamNoiseTex_ST;
            sampler2D _CausticTex;
            float4 _CausticTex_ST;
            float _Speed, _Frequency, _NormalScale, _AirRefractiveIndex, _WaterRefractiveIndex, _FresnelPower;
            float4 _WaveA, _WaveB, _WaveC, _WaveD, _WaveE, _WaveF, _WaveG, _WaveH, _WaveI, _WaveJ, _WaveK, _WaveL;
            float4 _NormalMap_ST;
            float _RefractionStrength, _FogDensity, _Shininess, _FrontSubsurfaceDistortion, _BackSubsurfaceDistortion;
            float4 _BaseColor, _WaterFogColor, _Caustics_Speed;
            float _shadowAttenuation;
            float _FrontSSSIntensity, _HeightCorrection, _FoamIntensity, _CausticIntensity;


            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _NormalMap;

            //-------------GenrateGerstnerWave-------------
            float3 GerstnerWave(
                float4 wave, float3 p, inout float3 tangent, inout float3 binormal
            )
            {
                float steepness = wave.z;
                float wavelength = wave.w;
                float k = 2 * UNITY_PI / wavelength;
                float c = sqrt(9.8 / k);
                float2 d = normalize(wave.xy) * _Frequency;
                float f = k * (dot(d, p.xz) - c * _Time.y * _Speed);
                float a = steepness / k;
        
                tangent += float3(
                    - d.x * d.x * (steepness * sin(f)),
                    d.x * (steepness * cos(f)),
                    - d.x * d.y * (steepness * sin(f))
                );
                binormal += float3(
                    - d.x * d.y * (steepness * sin(f)),
                    d.y * (steepness * cos(f)),
                    - d.y * d.y * (steepness * sin(f))
                );
                return float3(
                    d.x * (a * cos(f)),
                    a * sin(f),
                    d.y * (a * cos(f))
                );
            }
              
            //-----------CalculateFresnel------------------
            float CalculateFresnel(float3 viewDir, float3 normal)
            {
                float R_0 = (_AirRefractiveIndex - _WaterRefractiveIndex) / (_AirRefractiveIndex + _WaterRefractiveIndex);
                R_0 *= R_0;
                return R_0 + (1.0 - R_0) * pow((1.0 - saturate(dot(viewDir, normal))), _FresnelPower);
            }
            
            
            
            
            half3 Highlights(half3 positionWS, half roughness, half3 normalWS, half3 viewDirectionWS)
            {
                //Light mainLight = GetMainLight();
                half roughness2 = roughness * roughness;
                half3 halfDir = normalize(_WorldSpaceLightPos0.xyz + viewDirectionWS);
                half NoH = saturate(dot(normalize(normalWS), halfDir));
                half LoH = saturate(dot(_WorldSpaceLightPos0.xyz, halfDir));
                // GGX Distribution multiplied by combined approximation of Visibility and Fresnel
                half d = NoH * NoH * (roughness2 - 1) + 1.0001;
                half LoH2 = LoH * LoH;
                half specularTerm = roughness2 / ((d * d) * max(0.1, LoH2) * (roughness + 0.5) * 4);
                specularTerm = min(specularTerm, 10);
        
                return specularTerm * _LightColor0.rgb * _shadowAttenuation;
            }
            


            //-------------GetOddNegativeScale----------------
            float GetOddNegativeScale()
            {
                return unity_WorldTransformParams.w;
            }

            //------------CreateTangentToWorld---------------
            float3x3 CreateTangentToWorld(float3 normal, float3 tangent, float flipSign)
            {
            // For odd-negative scale transforms we need to flip the sign
            float sgn = flipSign * GetOddNegativeScale();
            float3 bitangent = cross(normal, tangent) * sgn;

            return float3x3(tangent, bitangent, normal);
            }
            
            //-----------TransformTangentToWorld----------
            float3 TransformTangentToWorld(float3 dirTS, float3x3 tangentToWorld)
            {
                // Note matrix is in row major convention with left multiplication as it is build on the fly
                return mul(dirTS, tangentToWorld);
            }
            float3 GetCameraPositionWS()
            {
                return _WorldSpaceCameraPos;
            }

            //-----------SampleSceneDepth--------------
            sampler2D _CameraDepthTexture;
            sampler2D sampler_CameraDepthTexture;
            float SampleSceneDepth(float2 uv)
            {
                return tex2D(_CameraDepthTexture, UnityStereoTransformScreenSpaceTex(uv)).r;
            }



            float SubsurfaceScattering(float3 viewDir, float3 lightDir, float3 normalDir,
            float frontSubsurfaceDistortion, float backSubsurfaceDistortion, float frontSSSIntensity, float thickness)
            {
            //分别计算正面和反面的次表面散射
            float3 frontLitDir = normalDir * frontSubsurfaceDistortion - lightDir;
            float3 backLitDir = normalDir * backSubsurfaceDistortion + lightDir;
            float frontsss = saturate(dot(viewDir, -frontLitDir));
            float backsss = saturate(dot(viewDir, -backLitDir));
        
            float result = saturate(frontsss * frontSSSIntensity + backsss) * thickness;
            return result;
            }
            /*
            //------------Light------------------
            struct Light
            {
                half3   direction;
                half3   color;
                half    distanceAttenuation;
                half    shadowAttenuation;
            };

            //-----------GetMainLight-------------
            Light GetMainLight()
            {
                Light light;
                light.direction = _WorldSpaceLightPos0.xyz;
                // unity_LightData.z is 1 when not culled by the culling mask, otherwise 0.
                light.distanceAttenuation = unity_LightData.z;
            #if defined(LIGHTMAP_ON) || defined(_MIXED_LIGHTING_SUBTRACTIVE)
                // unity_ProbesOcclusion.x is the mixed light probe occlusion data
                light.distanceAttenuation *= unity_ProbesOcclusion.x;
            #endif
                light.shadowAttenuation = 1.0;
                light.color = _MainLightColor.rgb;

                return light;
            }
            */

            v2f vert (a2v v)
            {
                v2f o;
                float3 tangent = float3(1, 0, 0);
                float3 binormal = float3(0, 0, 1);
                float3 p = v.positionOS;

                p += GerstnerWave(_WaveA, v.positionOS.xyz, tangent, binormal);
                p += GerstnerWave(_WaveB, v.positionOS.xyz, tangent, binormal);
                p += GerstnerWave(_WaveC, v.positionOS.xyz, tangent, binormal);
                p += GerstnerWave(_WaveD, v.positionOS.xyz, tangent, binormal);
                p += GerstnerWave(_WaveE, v.positionOS.xyz, tangent, binormal);
                p += GerstnerWave(_WaveF, v.positionOS.xyz, tangent, binormal);
                p += GerstnerWave(_WaveG, v.positionOS.xyz, tangent, binormal);
                p += GerstnerWave(_WaveH, v.positionOS.xyz, tangent, binormal);
                p += GerstnerWave(_WaveI, v.positionOS.xyz, tangent, binormal);
                p += GerstnerWave(_WaveJ, v.positionOS.xyz, tangent, binormal);
                p += GerstnerWave(_WaveK, v.positionOS.xyz, tangent, binormal);
                p += GerstnerWave(_WaveL, v.positionOS.xyz, tangent, binormal);


                o.heightOS = p.y;
                float3 normal = normalize(cross(binormal, tangent));
                UNITY_INITIALIZE_OUTPUT(v2f, o);
                o.positionCS = UnityObjectToClipPos(p);
                o.normalWS = UnityObjectToWorldNormal(v.normal);
                o.positionWS = mul(unity_ObjectToWorld,v.positionOS);
                o.scrPos = ComputeScreenPos(o.positionCS);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                //UNITY_TRANSFER_FOG(o,o.positionCS);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float3 normalWS = normalize(i.normalWS);
                //-------------normal----------
                float3x3 TtoW = CreateTangentToWorld(i.normalWS, i.tangentWS, 1);
                fixed4 normalTS = tex2D(_NormalMap,i.uv);
                normalTS.xyz = normalize(UnpackNormal(normalTS));
                normalWS = lerp(normalWS,normalize(TransformTangentToWorld(normalTS,TtoW)),_NormalScale);
                normalWS = normalize(normalWS);

                //------------reflection-----------
                float3 viewDirectionWS = normalize(GetCameraPositionWS() - i.positionWS.xyz);
                float3 reflectDir = reflect(-viewDirectionWS, normalWS);
                float4 reflectCol = texCUBE(_Skybox,reflectDir);
                //------------refraction------------
                float2 scrPos = i.scrPos / i.scrPos.w;
                float depth = SampleSceneDepth(scrPos);
                depth = LinearEyeDepth(depth);
                float surfaceDepth = i.scrPos.w;
                float depthDiffer = depth - surfaceDepth;
                float2 uvOffset = normalWS.xz * _RefractionStrength * saturate(depthDiffer);
                float2 offsetPos = scrPos + uvOffset;
                float offsetPosDepth = SampleSceneDepth(offsetPos);
                offsetPosDepth = LinearEyeDepth(offsetPosDepth);
                offsetPos = scrPos + uvOffset * step(surfaceDepth, offsetPosDepth);
                float4 refractCol = tex2D(_CameraOpaqueTexture,offsetPos);
                float depthFactor = depth / surfaceDepth;
                float3 underPos = (i.positionWS - GetCameraPositionWS()) * depthFactor + GetCameraPositionWS();
                float2 causticSampler = (underPos.xy + underPos.xz + underPos.yz) / 100 * _CausticTex_ST.xy;
                float4 caustic1 = tex2D(_CausticTex, causticSampler + _Caustics_Speed.xy * _Time.y/30);
                float4 caustic2 = tex2D(_CausticTex, causticSampler + _Caustics_Speed.zw * _Time.y/30); 
                float4 caustic = min(caustic1, caustic2);
                
                //------------fog-------------
                float offsetDepthDiffer = surfaceDepth > offsetPosDepth ? depthDiffer: offsetPosDepth - surfaceDepth;
                float fogFactor = saturate(1 - exp(-offsetDepthDiffer * _FogDensity / 10)) * _shadowAttenuation;
                float4 waterCol = lerp(_WaterFogColor, _BaseColor, fogFactor);
                refractCol = lerp(waterCol, waterCol * refractCol, saturate(fogFactor));
                refractCol += caustic * pow((1 - saturate(fogFactor)), 10);

                //------------specular----------
                float3 halfDir = normalize(viewDirectionWS + normalize(_WorldSpaceLightPos0.xyz));
                float3 specular = Highlights(i.positionWS, _Shininess, normalWS, viewDirectionWS);
                specular *= _shadowAttenuation;

                //------------SSS---------------
                float SSSValue = SubsurfaceScattering(viewDirectionWS, _WorldSpaceLightPos0.xyz, normalWS, _FrontSubsurfaceDistortion,
                _BackSubsurfaceDistortion, _FrontSSSIntensity, saturate(i.heightOS - _HeightCorrection));
                SSSValue *= _shadowAttenuation;
                float fresnel = CalculateFresnel(viewDirectionWS, normalWS);
                float4 scatterCol = lerp(refractCol, reflectCol, saturate(fresnel));
                
                float3 shading = scatterCol.rgb + specular + SSSValue * _LightColor0.rgb;

                //------------Foam------------------
                float foamOffset = tex2D(_FoamNoiseTex, i.uv * _FoamNoiseTex_ST.xy + _Time.y).x;
                shading = lerp(shading, float3(0.8, 0.8, 0.8), pow(saturate(_FoamIntensity * foamOffset -depthDiffer) * 2, 3) * saturate(depthDiffer));
                //shading = MixFog(shading.rgb, i.fogFactor);
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);
                // apply fog
                //UNITY_APPLY_FOG(i.fogCoord, col);
                return (shading.rgb,1);
            }
            ENDCG
        }
    }
}

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注