Shader “Custom/RainyWindow”
{
Properties
{
_MainTex (“Texture”, 2D) = “white” {} // Texture property, default is white.
_Size (“Size”, float) = 1 // Controls the size of the effect.
_T(“Time”, float) = 1 // Time property for animating effects.
_Distortion(“Distortion”, range(-5,5)) = 1 // Distortion intensity for the effect.
_Blur(“Blur”, range (0, 1)) = 1 // Blur intensity of the effect.
}
SubShader
{
Tags { “RenderType”=“Opaque” “Queue” =“Transparent”} // Render as opaque but in the transparent queue for layering effects.
LOD 100 // Level of detail, determining complexity of the shader.
Grabpass {"_GrabTexture"} // Captures the current frame buffer content into _GrabTexture for further use.
Pass
{
CGPROGRAM
#pragma vertex vert // Specifies the vertex shader function.
#pragma fragment frag // Specifies the fragment shader function.
#pragma multi_compile_fog // Allows shader to handle fog states.
#define S(a, b, t) smoothstep(a, b, t) // Macro for the smoothstep function.
#include "UnityCG.cginc" // Includes Unity's common shader library.
struct appdata
{
float4 vertex : POSITION; // Input vertex position.
float2 uv : TEXCOORD0; // Input texture coordinates.
};
struct v2f
{
float2 uv : TEXCOORD0; // Interpolated texture coordinates.
float4 grabUv : TEXCOORD1; // Screen coordinates for the GrabPass texture.
UNITY_FOG_COORDS(1) // Macro to handle fog coordinates.
float4 vertex : SV_POSITION; // Output position in clip space.
};
sampler2D _MainTex, _GrabTexture; // Samplers for the main and grabbed textures.
float4 _MainTex_ST; // Scale and offset for main texture coordinates.
float _Size, _T, _Distortion, _Blur; // Shader properties for effect parameters.
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex); // Converts object space position to clip space.
o.uv = TRANSFORM_TEX(v.uv, _MainTex); // Transforms UVs based on texture properties.
o.grabUv = UNITY_PROJ_COORD(ComputeGrabScreenPos(o.vertex)); // Computes screen space UV for GrabPass.
UNITY_TRANSFER_FOG(o,o.vertex); // Passes fog data to the fragment shader.
return o; // Outputs the processed vertex data.
}
float N21(float2 p)
{
p = frac(p * float2(123.34, 345.45)); // Applies a fractal pattern to generate pseudo-random numbers.
p += dot(p, p + 34.345); // Modulates the pattern further for randomness.
return frac(p.x * p.y); // Returns a fractional value that appears random.
}
float3 layer(float2 UV, float t)
{
float2 aspect = float2(2, 1); // Defines the aspect ratio to stretch the effect horizontally.
float2 uv = UV * _Size * aspect; // Scales UV coordinates by size and aspect ratio.
uv.y += t * .25; // Animates the Y axis over time to simulate motion.
float2 gv = frac(uv) - .5; // Calculates the grid position within each cell.
float2 id = floor(uv); // Integer grid ID to identify cells.
float n = N21(id); // Generates a noise value based on cell ID.
t += n * 6.2831; // Modifies time with noise to create a varied animation.
float w = UV.y * 10; // Multiplies Y-coordinate for wave simulation.
float x = (n - .5) * .8; // Calculates X offset for drops.
x += (.4 - abs(x)) * sin(3 * w) * pow(sin(w), 6) * .45; // Adds wave modulation for drop movement.
float y = -sin(t + sin(t + sin(t) * .5)) * .45; // Complex sine wave for Y position.
y -= (gv.x - x) * (gv.x - x); // Adjusts Y based on X to simulate drop position.
float2 dropPos = (gv - float2(x, y)) / aspect; // Position of the drop in aspect ratio.
float drop = S(.05, .03, length(dropPos)); // Smooth edge for drops using smoothstep.
float2 trailPos = (gv - float2(x, t * .25)) / aspect; // Position of trail effect.
trailPos.y = (frac(trailPos.y * 8) - .5) / 8; // Vertical trail smoothing.
float trail = S(.03, .01, length(trailPos)); // Smooth edge for trails.
float fogtrail = S(-.05, .05, dropPos.y); // Fog effect for trail's Y position.
fogtrail *= S(.5, y, gv.y); // Modulates fog with Y and grid Y.
trail *= fogtrail; // Combines trail with fog effect.
fogtrail *= S(.05, .04, abs(dropPos.x)); // Additional fog modulation based on X.
float2 offs = drop * dropPos + trail * trailPos; // Final offset for the effect.
return float3(offs, fogtrail); // Returns offset and fog intensity.
}
fixed4 frag (v2f i) : SV_Target
{
float t = fmod(_Time.y + _T, 7200); // Calculates the time modulo to loop the animation over a large period.
float4 col = 0; // Initializes the color to zero.
float3 drops = layer(i.uv, t); // Computes the effect layer for raindrops.
drops += layer(i.uv * 1.23 + 7.54, t); // Adds an additional raindrop layer for complexity.
drops += layer(i.uv * 1.35 + 1.54, t); // Adds another raindrop layer for more complexity.
drops += layer(i.uv * 1.57 - 7.54, t); // Further adds another raindrop layer.
float fade = 1 - saturate(fwidth(i.uv) * 60); // Computes a fade effect based on the width of the texture.
float blur = _Blur * 7 * (1 - drops.z * fade); // Calculates the blur amount based on drop intensity and fade effect.
float2 projUv = i.grabUv.xy / i.grabUv.w; // Converts grab UV coordinates into projected space for texture sampling.
projUv += drops.xy * _Distortion * fade; // Applies distortion to the projected UV based on raindrops.
blur *= .01; // Scales down the blur factor.
const float numSamples = 32; // Sets the number of samples used for the blur effect.
float a = N21(i.uv) * 6.2381; // Generates a random initial angle for blur sampling.
for (float i = 0; i < numSamples; i++) { // Loops through samples to apply a blur effect.
float2 offs = float2(sin(a), cos(a)) * blur; // Computes blur offset using trigonometric functions.
float d = frac(sin((i + 1) * 546.) * 5424.); // Generates pseudo-random distance.
d = sqrt(d); // Adjusts distance with square root for natural distribution.
offs *= d; // Scales offset by the random distance.
col += tex2D(_GrabTexture, projUv + offs); // Samples the blurred texture from the grab texture.
a++; // Increments the angle for the next blur sample.
}
col /= numSamples; // Averages the color samples to finalize the blur effect.
return col * .9; // Returns the final color, toned down slightly for visual effect.
}
ENDCG
}
}
}