Water rendering example

water rendering

What I share this time is about the rendering of water bodies. It is the most satisfying effect I have done so far. The specific process is similar to many on the Internet.


running result

insert image description here

Effectiveness analysis

1. Wave effect, you can see the effect that the water surface is sometimes high and sometimes low, and the reef is covered and exposed.
2. Secondly, the effect of horizontal flow
3. The depth effect of the middle part of the water surface is dark and the surrounding color is light

1. Wave effect

The realization of the wave effect is mainly achieved by combining the sin curve with the time coefficient, and then modifying the vertex position along the normal line. However, we also add the effect of z depth here, so that the farther it is, the more obvious the effect of water surface fluctuations is.

The code is as follows (example):

 v2f o;
float3 local_vert = v.vertex;
float3 offset_vert = (_WaveAmplitude * sin(_WaveAmount * local_vert.z + _Time.y)) * v.normal;
v.vertex.xyz += offset_vert;
 o.vertex = UnityObjectToClipPos(v.vertex);

2. Second, the effect of horizontal flow

The effect of water surface flow is to stagger the sampled normal texture and then mix it into a new normal

loat2 panner22 = ( 1.0 * _Time.y * float2( -0.03,0 ) + uv0_WaterNormal);
float2 panner19 = ( 1.0 * _Time.y * float2( 0.04,0.04 ) + uv0_WaterNormal);
float3 normal_1 = UnpackNormal(tex2D(_WaterNormal, panner22));
float3 normal_2 = UnpackNormal(tex2D(_WaterNormal, panner19));
float3 blend_normal = normal_1 + normal_2;
blend_normal.xy *= _NormalScale;
blend_normal = normalize(blend_normal);

The depth effect that the middle part of the water surface is darker and the surrounding color is lighter

Sampling depth map for depth comparison

float depth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.srceen_pos)));

float diff = saturate(pow(abs(depth - i.srceen_pos.z) + _WaterDepth, _WaterFalloff));
float4 lerpResult13 = lerp(_DeepColor, _ShalowColor, diff);

Sample_GrabTexture texture, mixed edge effect

float2 grab_uv = (i.srceen_pos.xy / i.srceen_pos.w);
float4 grab = tex2D(_GrabTexture, (float3(grab_uv, 0) + blend_normal * _Distortion).xy);
float4 lerpResult93 = lerp(lerpResult117, grab, diff);

Basic lighting

 float3 albedo = lerpResult93.rgb;
float3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;
 float3 diffuse = _LightColor0.rgb * albedo * saturate(dot(world_normal, world_light_dir));

float3 half_spec = normalize(world_view_dir + world_light_dir);
float3 specular = _LightColor0.rgb * albedo * pow(saturate(dot(world_normal, half_spec)), _Specular)  * _WaterSmoothness ;

full code

  Properties
    {
    
    
        _WaterNormal("WaterNormal", 2D) = "bump" {
    
    }
        _NormalScale("Normal Scale", Float) = 0
        _DeepColor("DeepColor", Color) = (0, 0, 0, 0)
        _ShalowColor("ShalowColor", Color) = (1, 1 ,1, 1)
        _WaterDepth("Water Depth", Float) = 0
        _WaterFalloff("Water Falloff", Float) = 0
        _Distortion("Distortion", Float) = 0.5
        _Foam("Foam", 2D) = "white" {
    
    }
        _FoamDepth("FoamDepth", Float) = 0
        _FoamFalloff("Foam Falloff", Float) = 0
        _WaveAmplitude("WaveAmpitude", Float) = 0.1
        _WaveAmount("WaveAmount", Float) = 8
        _Specular("Specular", Float) = 2
        _WaterSmoothness("WaterSmoothness", Float) = 1
    }
    SubShader
    {
    
    
        Tags {
    
     "RenderType"="Opaque" "Queue"="Transparent" "LightdMode"="ForwardBase"}
        LOD 100
        GrabPass{
    
     }
        Pass
        {
    
    
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag       

            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            struct appdata
            {
    
    
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float3 normal :NORMAL;
                float4 tangle : TANGENT;
            };

            struct v2f
            {
    
    
                float2 uv : TEXCOORD0;               
                float4 vertex : SV_POSITION;
                float4 srceen_pos :TEXCOORD1  ;
                float4 Ttow0 :TEXCOORD2;
                float4 Ttow1:TEXCOORD3 ;
                float4 Ttow2:TEXCOORD4 ; 
            };

            sampler2D _WaterNormal;
            float4 _WaterNormal_ST;
            float _NormalScale;
            float4 _DeepColor;
            float4 _ShalowColor;
            float _WaterDepth;
            float _WaterFalloff;
            float _Distortion;
            sampler2D _Foam;
            float4 _Foam_ST;
            float _FoamDepth;
            float _FoamFalloff;
            float _WaveAmplitude;
            float _WaveAmount;
            sampler2D _CameraDepthTexture;
            float _Specular;
            float _WaterSmoothness;
            sampler2D _GrabTexture;
            v2f vert (appdata v)
            {
    
    
                v2f o;
                float3 local_vert = v.vertex;
                float3 offset_vert = (_WaveAmplitude * sin(_WaveAmount * local_vert.z + _Time.y)) * v.normal;
                v.vertex.xyz += offset_vert;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.srceen_pos = ComputeScreenPos(o.vertex);
                COMPUTE_EYEDEPTH(o.srceen_pos.z);
                
                float3 world_pos = mul(unity_ObjectToWorld, v.vertex);
                float3 world_normal = UnityObjectToWorldNormal(v.normal);
                float3 world_tangel = UnityObjectToWorldDir(v.tangle);
                float3 world_borind = cross(world_normal, world_tangel) * v.tangle.w;

                o.Ttow0 = float4(world_tangel.x, world_borind.x, world_normal.x, world_pos.x);
                o.Ttow1 = float4(world_tangel.y, world_borind.y, world_normal.y, world_pos.y);
                o.Ttow2 = float4(world_tangel.z, world_borind.z, world_normal.z, world_pos.z);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
    
                  
                float2 uv0_WaterNormal = i.uv * _WaterNormal_ST.xy + _WaterNormal_ST.zw;
                float2 panner22 = ( 1.0 * _Time.y * float2( -0.03,0 ) + uv0_WaterNormal);
                float2 panner19 = ( 1.0 * _Time.y * float2( 0.04,0.04 ) + uv0_WaterNormal);
                float3 normal_1 = UnpackNormal(tex2D(_WaterNormal, panner22));
                float3 normal_2 = UnpackNormal(tex2D(_WaterNormal, panner19));
                float3 blend_normal = normal_1 + normal_2;
                blend_normal.xy *= _NormalScale;
                blend_normal = normalize(blend_normal);

                float3 world_pos = float3(i.Ttow0.w, i.Ttow1.w, i.Ttow2.w);
                float3 world_view_dir = normalize(UnityWorldSpaceViewDir(world_pos));
                float3 world_light_dir = normalize(UnityWorldSpaceLightDir(world_pos));
                float3 world_normal = float3(dot(i.Ttow0.xyz, blend_normal), dot(i.Ttow1.xyz, blend_normal), 
                    dot(i.Ttow2.xyz, blend_normal));

                float depth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.srceen_pos)));

                float diff = saturate(pow(abs(depth - i.srceen_pos.z) + _WaterDepth, _WaterFalloff));
                float4 lerpResult13 = lerp(_DeepColor, _ShalowColor, diff);

                
                float2 uv_foam = _Foam_ST.xy * ((_Time.x * float2(0.1, 0.1)) + i.uv);
                float3 foam = tex2D(_Foam, uv_foam);
                float foam_diff = saturate(pow((abs(depth - i.srceen_pos.z) + _FoamDepth), _FoamFalloff) * foam.r);
                float4 lerpResult117 = lerp( lerpResult13 , float4(1,1,1,0) , foam_diff);

                float2 grab_uv = (i.srceen_pos.xy / i.srceen_pos.w);
                float4 grab = tex2D(_GrabTexture, (float3(grab_uv, 0) + blend_normal * _Distortion).xy);
                float4 lerpResult93 = lerp(lerpResult117, grab, diff);

                float3 albedo = lerpResult93.rgb;
                float3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo;
                float3 diffuse = _LightColor0.rgb * albedo * saturate(dot(world_normal, world_light_dir));

                float3 half_spec = normalize(world_view_dir + world_light_dir);
                float3 specular = _LightColor0.rgb * albedo * pow(saturate(dot(world_normal, half_spec)), _Specular)  * _WaterSmoothness ;
                return fixed4(ambient + diffuse + specular, 1);
                //return fixed4(grab, 1);
            }
            ENDCG
        }
    }

Summarize

The above is the content of this sharing, and other effects will be continuously updated in the future.

Guess you like

Origin blog.csdn.net/weixin_39289457/article/details/124237538