Unity uses Shader to make glass windows in the rain learning notes

Keywords: Unity Windows Fragment less

Unity uses Shader to make glass windows in the rain learning notes


https://www.youtube.com/watch?v=EBrAdahFtuo Watch the notes after the oil pipe god's tutorial.

Blur background, simulate fog

  1. In the textured Inspector panel, checking Generate Mip Maps results in eight MipMaps with different levels of detail.
  2. tex2Dlod(_MainTex,float4(x,y,z,w)); in this texture sampling function, in addition to uv, you can control the level of detail, offset, and W control details.
  3. The Filter Mode in the textured Inspector panel represents how textures are filtered when stretched by a three-dimensional transformation.There are three options: Point has no filter, Bilinear blurs when viewed at close range, and Trilinear blurs between different Mip Level s one more than Bilinear.It just has more blurred levels and feels like stepless speed.

Make glass transparent

  1. Add GrabPass{"_GrabTexture"} to SubShader, meaning screenshots and storage for use.There are two problems: 1, incorrect connection with the background behind 2, the game object behind cannot be displayed because unit defaults to the first rendering near the camera.
  2. Question 1: Add variable float4 grabUv in V2F structure: TEXCOORD1; add statement o.grabUv = UNITY_PROJ_COORD (ComputeGrabScreenPos (o.vertex) in vertex shader;
    Float4 UNITY_PROJ_COORD (float4) inputs a four-component vector and returns coordinates suitable for texture sampling.
    Float4 ComputeGrabScreenPos (float4) enters the coordinates of the clip space and returns the coordinates used for GrabPass.
    Question 2: Add Queue="Transparent" to SubShader's Tag to tell Unity that the object is transparent and needs to be rendered at the end.

Handwriting Fuzzy Algorithm

  1. Since textures obtained using GrabPass cannot use Mipmap, blurring is achieved by iterating the average value of each pixel and surrounding pixels, which is the simplest but costly blurring method.
				//The blur is blurred and there is no fog covering where the water droplets pass
				float blur = _Blur * 7 * (1-drops.z);
				float2 projUv = i.grabUv.xy/i.grabUv.w;
                projUv+=drops.xy*_Distortion;
                blur*=0.01;
                const float numSamples = 16;
                //A is the starting position and the value is a random value within one period of the trigonometric function
                float a = N21(i.uv)*6.2831;
                for(float i = 0;i<numSamples;i++){
                	//offs is the offset coordinate of the surrounding pixel to be sampled relative to the intermediate pixel
                    float2 offs = float2(sin(a),cos(a))*blur;
                    //d To get a random number between 0 and 1 so that the sampled area is not a circle
                    //Can reduce edges too sharp
                    float d = frac(sin((i+1)*546.)*5425.);
                    d = sqrt(d);
                    offs *= d;
                    col += tex2D(_GrabTexture,projUv+offs);
                    a++;
                }
                col/=numSamples;

`Shader "Unlit/Window"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Size("Size",float) = 1
_t("Time",float) = 1
_Distortion("Distortion",Range(-5,5))=1
_Blur("blur",range(0,1)) = 0
}
SubShader
{
Tags { "RenderType"="Opaque" "Queue"="Transparent"}
LOD 100
GrabPass{"_GrabTexture"}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#define S(a,b,c) smoothstep(a,b,c)//Using S instead of this method is more convenient
#include "UnityCG.cginc"

        struct appdata
        {
            float4 vertex : POSITION;
            float2 uv : TEXCOORD0;
        };

        struct v2f
        {
            float2 uv : TEXCOORD0;
            float4 grabUv : TEXCOORD1;
            UNITY_FOG_COORDS(1)
            float4 vertex : SV_POSITION;
        };

        sampler2D _MainTex,_GrabTexture;
        float4 _MainTex_ST;
        float _Size,_t,_Distortion,_Blur;

        v2f vert (appdata v)
        {
            v2f o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.uv = TRANSFORM_TEX(v.uv, _MainTex);
            o.grabUv = UNITY_PROJ_COORD(ComputeGrabScreenPos(o.vertex));
            UNITY_TRANSFER_FOG(o,o.vertex);
            return o;
        }
        //Generate a pseudo-random number using a two-dimensional vector
        float N21(float2 p){
            p=frac(p*float2(123.34,345.45));
            p+=dot(p,p+34.345);//Return two vector clicks
            return frac(p.x*p.y);
        }
        //The process of generating water droplets is encapsulated in a function Layer to increase the number of water droplets by multiple overlays.
        float3 Layer(float2 UV,float t){
            //Double the grid x direction
            float2 aspect = float2(2,1);
            //size is used to control how many grids there are
            float2 uv = UV*_Size*aspect;
            //Achieving an overall slide
            uv.y+=t*0.25;
            //frac is decimal, gv is the coordinate within each cell, from left to right, from bottom to top is -0.5 to 0.5
            float2 gv = frac(uv)-0.5;
            //Set id for each grid
            float2 id = floor(uv);
            //Each grid has a random number between 0 and 1
            float n = N21(id); 
            //Make the random x-distribution on a period of 0 and 2_to make the effect more random.
            t+=n*6.2831;
            //Setting height as a variable of the lateral offset function
            float w = UV.y*10;
            //Achieve lateral drip offset of water droplets between -0.4 and 0.4 to prevent the drip from drifting out of the grid
            float x=(n-0.5)*0.8;
            x += (0.4-abs(x)) * sin(3*w)*pow(sin(w),6)*0.45;
            //Offset function to realize the vertical movement of water droplets and the slow rise and fast fall of water droplets
            float y=-sin(t+sin(t+sin(t)*0.5))*0.45;
            //Change the shape of the water droplets to offset the change in x
            y-=(gv.x-x)*(gv.x-x);
            //The location of the droplet center, which controls the coordinate system within the square, (0, 0) the origin is the droplet Center
            float2 dropPos = (gv-float2(x,y))/aspect;
            //Display area of water droplets, 1 for display, 0 for no water droplets, edge for interpolation
            float drop = S(.05,.03,length(dropPos));
            
            //Trailing beads
            float2 trailPos = (gv-float2(x,t*0.25))/aspect;
            trailPos.y=(frac(trailPos.y*8)-0.5)/8;
            float trail = S(.03,.01,length(trailPos));
            //Set only water droplets with tails above them
            float fogtrail = S(-0.05,0.05,dropPos.y);
            //Dragging gradient of water droplets to the upper limit of the square
            fogtrail*=S(0.5,y,gv.y);
            trail*=fogtrail;
            //Fog effect of trailing
            fogtrail*=S(0.05,0.04,abs(dropPos.x));
            //Test Code
            //col+=fogtrail*0.5;
            //col+=drop;
            //col+=trail;
            /*
            if(_textNum<0){
                col*=0;col.rg+=dropPos;
            }
            */
            //Offset the sampling coordinates where there are water droplets to represent the refraction of light
            float2 offs = drop*dropPos+trail*trailPos;
            //col= tex2D(_MainTex,i.uv+offs*_Distortion);
            return float3(offs,fogtrail);
        }
        fixed4 frag (v2f i) : SV_Target
        {
            //t means time, reset every two hours in case the time number is too large to cause the pseudo-random number to show up
            float t = fmod(_Time.y+_t,7200);
            float4 col = 0;
            float3 drops = Layer(i.uv,t);
            drops+=Layer(i.uv*1.11+8.43,t);
            //fwidth is a partial derivative that represents the difference between the pixel on the screen and the surrounding pixel. The closer the pixel is, the greater the distance is
            //saturate returns 0 for controlling variables between 0 and 1, 0 for less than 0, 1 for greater than 1
            //The farther away from the object, the closer fade is to 0, the closer fade is to 1
            float fade = 1-saturate(fwidth(i.uv)*60);

            //Fuzzy hierarchy for water droplets with no fog
            float blur = _Blur * 7 * (1-drops.z*fade);

            //col = tex2Dlod(_MainTex,float4(i.uv+drops.xy*_Distortion,_textNum,blur));
            
            float2 projUv = i.grabUv.xy/i.grabUv.w;
            projUv+=drops.xy*_Distortion*fade;
            //Use the average value of each pixel and surrounding pixels to blur and simulate the fog effect
            blur*=0.01;
            //Number of iterations
            const float numSamples = 16;
            //Search for the start of nearby pixels, between 0 and 2_
            float a = N21(i.uv)*6.2831;
            for(float i = 0;i<numSamples;i++){
                float2 offs = float2(sin(a),cos(a))*blur;
                float d = frac(sin((i+1)*546.)*5425.);
                d = sqrt(d);
                offs *= d;
                col += tex2D(_GrabTexture,projUv+offs);
                a++;
            }
            col/=numSamples;
            return col*0.9;
        }
        ENDCG
    }
}

}
`

Published an original article. Praise 0. Visits 3
Private letter follow

Posted by crazy_carl on Mon, 03 Feb 2020 19:30:26 -0800