Commands/Shaders/Get-OBSRainWindowShader.ps1

function Get-OBSRainWindowShader {

[Alias('Set-OBSRainWindowShader','Add-OBSRainWindowShader')]
param(
# Set the size of OBSRainWindowShader
[ComponentModel.DefaultBindingProperty('size')]
[Single]
$Size,
# Set the blurSize of OBSRainWindowShader
[ComponentModel.DefaultBindingProperty('blurSize')]
[Single]
$BlurSize,
# Set the trail_strength of OBSRainWindowShader
[Alias('trail_strength')]
[ComponentModel.DefaultBindingProperty('trail_strength')]
[Single]
$TrailStrength,
# Set the trail_color of OBSRainWindowShader
[Alias('trail_color')]
[ComponentModel.DefaultBindingProperty('trail_color')]
[Single]
$TrailColor,
# Set the speed of OBSRainWindowShader
[ComponentModel.DefaultBindingProperty('speed')]
[Single]
$Speed,
# Set the debug of OBSRainWindowShader
[ComponentModel.DefaultBindingProperty('debug')]
[Management.Automation.SwitchParameter]
$DebugShader,
# The name of the source. This must be provided when adding an item for the first time
[Parameter(ValueFromPipelineByPropertyName)]
[Alias('SceneItemName')]
[String]
$SourceName,
# The name of the filter. If this is not provided, this will default to the shader name.
[Parameter(ValueFromPipelineByPropertyName)]
[String]
$FilterName,
# The inline value of the shader. This will normally be provided as a default parameter, based off of the name.
[Alias('ShaderContent')]
[String]
$ShaderText,
# If set, will force the recreation of a shader that already exists
[Management.Automation.SwitchParameter]
$Force,
# If set, will pass thru the commands that would be sent to OBS (these can be sent at any time with Send-OBS)
[Management.Automation.SwitchParameter]
$PassThru,
# If set, will not wait for a response from OBS (this will be faster, but will not return anything)
[Management.Automation.SwitchParameter]
$NoResponse,
# If set, use the shader elapsed time, instead of the OBS system elapsed time
[ComponentModel.DefaultBindingProperty('use_shader_elapsed_time')]
[Management.Automation.SwitchParameter]
$UseShaderTime
)


process {
$shaderName = 'rain-window'
$ShaderNoun = 'OBSRainWindowShader'
if (-not $psBoundParameters['ShaderText']) {    
    $psBoundParameters['ShaderText'] = $ShaderText = '
// https://www.shadertoy.com/view/slfSzS adopted for OBS by Exeldro
// shader derived from Heartfelt - by Martijn Steinrucken aka BigWings - 2017
// https://www.shadertoy.com/view/ltffzl
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

uniform float size<
    string label = "Rain Drop Size";
    string widget_type = "slider";
    float minimum = 0.001;
    float maximum = 0.5;
    float step = 0.01;
> = 0.2;
uniform float blurSize<
    string label = "Blur Radius";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 100.0;
    float step = 0.01;
> = 32.0; // BLUR SIZE (Radius)
uniform float trail_strength<
    string label = "Trail Strength";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 100.0;
    float step = 0.01;
> = 100.0;
uniform float trail_color<
    string label = "Trail Color";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 100.0;
    float step = 0.01;
> = 40.0;
uniform float speed<
    string label = "Speed";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 200.0;
    float step = 0.01;
> = 100.0;
uniform bool debug = false;


float fract(float v){
    return v - floor(v);
}

float2 fract2(float2 v){
    return float2(v.x - floor(v.x), v.y - floor(v.y));
}

float3 fract3(float3 v){
    return float3(v.x - floor(v.x), v.y - floor(v.y), v.z - floor(v.z));
}

float3 fract4(float4 v){
    return float4(v.x - floor(v.x), v.y - floor(v.y), v.z - floor(v.z), v.w - floor(v.w));
}


float3 N13(float p) {
   // from DAVE HOSKINS
   float3 p3 = fract3(float3(p, p, p) * float3(.1031,.11369,.13787));
   p3 += dot(p3, p3.yzx + 19.19);
   return fract3(float3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x));
}

float4 N14(float t) {
    return fract4(sin(t*float4(123., 1024., 1456., 264.))*float4(6547., 345., 8799., 1564.));
}
float N(float t) {
    return fract(sin(t*12345.564)*7658.76);
}

float Saw(float b, float t) {
    return smoothstep(0., b, t)*smoothstep(1., b, t);
}

float2 Drops(float2 uv, float t) {
    
    float2 UV = uv;
    
    // DEFINE GRID
    uv.y += t*0.8;
    float2 a = float2(6., 1.);
    float2 grid = a*2.;
    float2 id = floor(uv*grid);
    
    // RANDOM SHIFT Y
    float colShift = N(id.x);
    uv.y += colShift;
    
    // DEFINE SPACES
    id = floor(uv*grid);
    float3 n = N13(id.x*35.2+id.y*2376.1);
    float2 st = fract2(uv*grid)-float2(.5, 0);
    
    // POSITION DROPS
    //clamp(2*x,0,2)+clamp(1-x*.5, -1.5, .5)+1.5-2
    float x = n.x-.5;
    
    float y = UV.y*20.;
    
    float distort = sin(y+sin(y));
    x += distort*(.5-abs(x))*(n.z-.5);
    x *= .7;
    float ti = fract(t+n.z);
    y = (Saw(.85, ti)-.5)*.9+.5;
    float2 p = float2(x, y);
    
    // DROPS
    float d = length((st-p)*a.yx);
    
    float dSize = size;
    
    float Drop = smoothstep(dSize, .0, d);
    
    
    float r = sqrt(smoothstep(1., y, st.y));
    float cd = abs(st.x-x);
    
    // TRAILS
    float trail = smoothstep((dSize*.5+.03)*r, (dSize*.5-.05)*r, cd);
    float trailFront = smoothstep(-.02, .02, st.y-y);
    trail *= trailFront;
    
    
    // DROPLETS
    y = UV.y;
    y += N(id.x);
    float trail2 = smoothstep(dSize*r, .0, cd);
    float droplets = max(0., (sin(y*(1.-y)*120.)-st.y))*trail2*trailFront*n.z;
    y = fract(y*10.)+(st.y-.5);
    float dd = length(st-float2(x, y));
    droplets = smoothstep(dSize*N(id.x), 0., dd);
    float m = Drop+droplets*r*trailFront;
    if(debug){
        m += st.x>a.y*.45 || st.y>a.x*.165 ? 1.2 : 0.; //DEBUG SPACES
    }
    
    
    return float2(m, trail);
}

float StaticDrops(float2 uv, float t) {
    uv *= 30.;
    
    float2 id = floor(uv);
    uv = fract2(uv)-.5;
    float3 n = N13(id.x*107.45+id.y*3543.654);
    float2 p = (n.xy-.5)*0.5;
    float d = length(uv-p);
    
    float fade = Saw(.025, fract(t+n.z));
    float c = smoothstep(size, 0., d)*fract(n.z*10.)*fade;

    return c;
}

float2 Rain(float2 uv, float t) {
    //float s = StaticDrops(uv, t);
    float2 r1 = Drops(uv, t);
    float2 r2 = Drops(uv*1.8, t);
    float c;
    if(debug){
        c = r1.x;
    }else{
        c = r1.x+r2.x;//s+r1.x+r2.x;
    }
    
    c = smoothstep(.3, 1., c);
    
    if(debug){
        return float2(c, r1.y);
    }else{
        return float2(c, max(r1.y, r2.y));
    }
}

float4 mainImage(VertData v_in) : TARGET
{
    float2 uv = v_in.uv;//(fragCoord.xy-.5*iResolution.xy) / iResolution.y;
    uv.y = 1.0 - uv.y;
    uv = uv * uv_scale;
    float2 UV = v_in.uv;
    float T = elapsed_time * speed / 100.0;
       
    float t = T*.2;
    
    UV = (UV-.5)*(.9)+.5;

    float2 c = Rain(uv, t);

       float2 e = float2(.001, 0.); //pixel offset
       float cx = Rain(uv+e, t).x;
       float cy = Rain(uv+e.yx, t).x;
       float2 n = float2(cx-c.x, cy-c.x); //normals

    // BLUR derived from existical https://www.shadertoy.com/view/Xltfzj
    float Pi = 6.28318530718; // Pi*2

    // GAUSSIAN BLUR SETTINGS {{{
    float Directions = 32.0; // BLUR DIRECTIONS (Default 16.0 - More is better but slower)
    float Quality = 8.0; // BLUR QUALITY (Default 4.0 - More is better but slower)
    // GAUSSIAN BLUR SETTINGS }}}
    float2 Radius = blurSize/uv_size;
    float3 col = image.Sample(textureSampler, UV).rgb;

    if(blurSize > 0.0){
        // Blur calculations
        for(float d=0.0; d<Pi; d+=Pi/Directions)
        {
            for(float i=1.0/Quality; i<=1.0; i+=1.0/Quality)
            {
                float2 uv2;
                if(debug){
                    uv2 = UV+c+float2(cos(d),sin(d))*Radius*i;
                } else{
                    uv2 = UV+n+float2(cos(d),sin(d))*Radius*i;
                }
                float3 t = image.Sample(textureSampler, uv2).rgb;
                col = col + t;
            }
        }

        col /= Quality * Directions - 0.0;
    }

    float3 tex = image.Sample(textureSampler, UV+n).rgb;

    c.y = clamp(c.y, 0.0, 1.);
    c.y = c.y * trail_strength /100.0;
    col -= c.y;
    col += c.y*(tex + 1.0 - trail_color/100.0);

    return float4(col, 1.);
}
'

}
$MyVerb, $myNoun = $MyInvocation.InvocationName -split '-',2
if (-not $myNoun) {
    $myNoun = $myVerb
    $myVerb = 'Get'    
}
switch -regex ($myVerb) {
    Get {
        $FilterNamePattern = "(?>$(
            if ($FilterName) {
                [Regex]::Escape($FilterName)
            }
            else {
                [Regex]::Escape($ShaderNoun -replace '^OBS' -replace 'Shader$'),[Regex]::Escape($shaderName) -join '|'
            }
        ))"

        if ($SourceName) {
            Get-OBSInput | 
                Where-Object InputName -eq $SourceName |
                Get-OBSSourceFilterList |
                Where-Object FilterName -Match $FilterNamePattern
        } else {
            $obs.Inputs |
                Get-OBSSourceFilterList |
                Where-Object FilterName -Match $FilterNamePattern
        }        
    }
    'Remove' {
        if ($SourceName) {
            Get-OBSInput | 
                Where-Object InputName -eq $SourceName |
                Get-OBSSourceFilterList |
                Where-Object FilterName -Match $FilterNamePattern |
                Remove-OBSSourceFilter
        }
    }
    '(?>Add|Set)' {
        $ShaderSettings = [Ordered]@{}
        :nextParameter foreach ($parameterMetadata in $MyInvocation.MyCommand.Parameters[@($psBoundParameters.Keys)]) {
            foreach ($parameterAttribute in $parameterMetadata.Attributes) {
                if ($parameterAttribute -isnot [ComponentModel.DefaultBindingPropertyAttribute]) { continue }
                $ShaderSettings[$parameterAttribute.Name] = $PSBoundParameters[$parameterMetadata.Name]
                if ($ShaderSettings[$parameterAttribute.Name] -is [switch]) {
                    $ShaderSettings[$parameterAttribute.Name] = $ShaderSettings[$parameterAttribute.Name] -as [bool]
                }
                continue nextParameter
            }            
        }

        if (-not $PSBoundParameters['FilterName']) {
            $filterName = $PSBoundParameters['FilterName'] = $shaderName
        }

        $ShaderFilterSplat = [Ordered]@{
            ShaderSetting = $ShaderSettings
            FilterName = $FilterName
            SourceName = $SourceName
        }        

        foreach ($CarryOnParameter in "PassThru", "NoResponse","Force") {
            if ($PSBoundParameters.ContainsKey($CarryOnParameter)) {
                $ShaderFilterSplat[$CarryOnParameter] = $PSBoundParameters[$CarryOnParameter]
            }
        }

        if (-not $script:CachedShaderFilesFromCommand) {
            $script:CachedShaderFilesFromCommand = @{}
        }

        if ($Home -and -not $script:CachedShaderFilesFromCommand[$shaderName]) {
            $MyObsPowerShellPath = Join-Path $home ".obs-powershell"
            $ThisShaderPath = Join-Path $MyObsPowerShellPath "$shaderName.shader"
            $shaderText | Set-Content -LiteralPath $ThisShaderPath
            $script:CachedShaderFilesFromCommand[$shaderName] = Get-Item -LiteralPath $ThisShaderPath
        }
        if ($script:CachedShaderFilesFromCommand[$shaderName]) {
            $ShaderFilterSplat.ShaderFile = $script:CachedShaderFilesFromCommand[$shaderName].FullName
        } else {
            $ShaderFilterSplat.ShaderText = $shaderText
        }        

        if ($myVerb -eq 'Add') {                        
            Add-OBSShaderFilter @ShaderFilterSplat
        } else {
            Set-OBSShaderFilter @ShaderFilterSplat
        }
    }
}

}


}