Search Unity

  1. How can our website serve you better? Give us your feedback. Take our survey and let us know.
    Dismiss Notice

How do I enable Fog in this custom Roystan Toon Water Shader?

Discussion in 'Shaders' started by neetesh6499, Jun 15, 2021.

  1. neetesh6499


    Dec 24, 2014
    Hey all, so I'm having trouble adding fog on this water shader, I'm not well versed with shaders & the documentations kind of go over my head at the moment, so could anyone help me with what to add to this shader so that it is affected by global fog? Thanks.

    Shader "Roystan/Toon/Water Tut"
    // What color the water will sample when the surface below is shallow.
    _DepthGradientShallow("Depth Gradient Shallow", Color) = (0.325, 0.807, 0.971, 0.725)

    // What color the water will sample when the surface below is at its deepest.
    _DepthGradientDeep("Depth Gradient Deep", Color) = (0.086, 0.407, 1, 0.749)

    // Maximum distance the surface below the water will affect the color gradient.
    _DepthMaxDistance("Depth Maximum Distance", Float) = 1

    // Color to render the foam generated by objects intersecting the surface.
    _FoamColor("Foam Color", Color) = (1,1,1,1)

    // Noise texture used to generate waves.
    _SurfaceNoise("Surface Noise", 2D) = "white" {}

    // Speed, in UVs per second the noise will scroll. Only the xy components are used.
    _SurfaceNoiseScroll("Surface Noise Scroll Amount", Vector) = (0.03, 0.03, 0, 0)

    // Values in the noise texture above this cutoff are rendered on the surface.
    _SurfaceNoiseCutoff("Surface Noise Cutoff", Range(0, 1)) = 0.777

    // Red and green channels of this texture are used to offset the
    // noise texture to create distortion in the waves.
    _SurfaceDistortion("Surface Distortion", 2D) = "white" {}

    // Multiplies the distortion by this value.
    _SurfaceDistortionAmount("Surface Distortion Amount", Range(0, 1)) = 0.27

    // Control the distance that surfaces below the water will contribute
    // to foam being rendered.
    _FoamMaxDistance("Foam Maximum Distance", Float) = 0.4
    _FoamMinDistance("Foam Minimum Distance", Float) = 0.04
    "Queue" = "Transparent"

    // Transparent "normal" blending.
    Blend SrcAlpha OneMinusSrcAlpha
    ZWrite Off

    #define SMOOTHSTEP_AA 0.01

    #pragma vertex vert
    #pragma fragment frag

    #include "UnityCG.cginc"

    // Blends two colors using the same algorithm that our shader is using
    // to blend with the screen. This is usually called "normal blending",
    // and is similar to how software like Photoshop blends two layers.
    float4 alphaBlend(float4 top, float4 bottom)
    float3 color = (top.rgb * top.a) + (bottom.rgb * (1 - top.a));
    float alpha = top.a + bottom.a * (1 - top.a);

    return float4(color, alpha);

    struct appdata
    float4 vertex : POSITION;
    float4 uv : TEXCOORD0;
    float3 normal : NORMAL;

    struct v2f
    float4 vertex : SV_POSITION;
    float2 noiseUV : TEXCOORD0;
    float2 distortUV : TEXCOORD1;
    float4 screenPosition : TEXCOORD2;
    float3 viewNormal : NORMAL;

    sampler2D _SurfaceNoise;
    float4 _SurfaceNoise_ST;

    sampler2D _SurfaceDistortion;
    float4 _SurfaceDistortion_ST;

    v2f vert (appdata v)
    v2f o;

    o.vertex = UnityObjectToClipPos(v.vertex);
    o.screenPosition = ComputeScreenPos(o.vertex);
    o.distortUV = TRANSFORM_TEX(v.uv, _SurfaceDistortion);
    o.noiseUV = TRANSFORM_TEX(v.uv, _SurfaceNoise);
    o.viewNormal = COMPUTE_VIEW_NORMAL;

    return o;

    float4 _DepthGradientShallow;
    float4 _DepthGradientDeep;
    float4 _FoamColor;

    float _DepthMaxDistance;
    float _FoamMaxDistance;
    float _FoamMinDistance;
    float _SurfaceNoiseCutoff;
    float _SurfaceDistortionAmount;

    float2 _SurfaceNoiseScroll;

    sampler2D _CameraDepthTexture;
    sampler2D _CameraNormalsTexture;

    float4 frag (v2f i) : SV_Target
    // Retrieve the current depth value of the surface behind the
    // pixel we are currently rendering.
    float existingDepth01 = tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.screenPosition)).r;
    // Convert the depth from non-linear 0...1 range to linear
    // depth, in Unity units.
    float existingDepthLinear = LinearEyeDepth(existingDepth01);

    // Difference, in Unity units, between the water's surface and the object behind it.
    float depthDifference = existingDepthLinear - i.screenPosition.w;

    // Calculate the color of the water based on the depth using our two gradient colors.
    float waterDepthDifference01 = saturate(depthDifference / _DepthMaxDistance);
    float4 waterColor = lerp(_DepthGradientShallow, _DepthGradientDeep, waterDepthDifference01);

    // Retrieve the view-space normal of the surface behind the
    // pixel we are currently rendering.
    float3 existingNormal = tex2Dproj(_CameraNormalsTexture, UNITY_PROJ_COORD(i.screenPosition));

    // Modulate the amount of foam we display based on the difference
    // between the normals of our water surface and the object behind it.
    // Larger differences allow for extra foam to attempt to keep the overall
    // amount consistent.
    float3 normalDot = saturate(dot(existingNormal, i.viewNormal));
    float foamDistance = lerp(_FoamMaxDistance, _FoamMinDistance, normalDot);
    float foamDepthDifference01 = saturate(depthDifference / foamDistance);

    float surfaceNoiseCutoff = foamDepthDifference01 * _SurfaceNoiseCutoff;

    float2 distortSample = (tex2D(_SurfaceDistortion, i.distortUV).xy * 2 - 1) * _SurfaceDistortionAmount;

    // Distort the noise UV based off the RG channels (using xy here) of the distortion texture.
    // Also offset it by time, scaled by the scroll speed.
    float2 noiseUV = float2((i.noiseUV.x + _Time.y * _SurfaceNoiseScroll.x) + distortSample.x,
    (i.noiseUV.y + _Time.y * _SurfaceNoiseScroll.y) + distortSample.y);
    float surfaceNoiseSample = tex2D(_SurfaceNoise, noiseUV).r;

    // Use smoothstep to ensure we get some anti-aliasing in the transition from foam to surface.
    // Uncomment the line below to see how it looks without AA.
    // float surfaceNoise = surfaceNoiseSample > surfaceNoiseCutoff ? 1 : 0;
    float surfaceNoise = smoothstep(surfaceNoiseCutoff - SMOOTHSTEP_AA, surfaceNoiseCutoff + SMOOTHSTEP_AA, surfaceNoiseSample);

    float4 surfaceNoiseColor = _FoamColor;
    surfaceNoiseColor.a *= surfaceNoise;

    // Use normal alpha blending to combine the foam with the surface.
    return alphaBlend(surfaceNoiseColor, waterColor);