Commands/Shaders/Get-OBSSeascapeShader.ps1

function Get-OBSSeascapeShader {

[Alias('Set-OBSSeascapeShader','Add-OBSSeascapeShader')]
param(
# Set the AA of OBSSeascapeShader
[ComponentModel.DefaultBindingProperty('AA')]
[Management.Automation.SwitchParameter]
$AA,
# Set the SEA_HEIGHT of OBSSeascapeShader
[Alias('SEA_HEIGHT')]
[ComponentModel.DefaultBindingProperty('SEA_HEIGHT')]
[Single]
$SEAHEIGHT,
# Set the SEA_CHOPPY of OBSSeascapeShader
[Alias('SEA_CHOPPY')]
[ComponentModel.DefaultBindingProperty('SEA_CHOPPY')]
[Single]
$SEACHOPPY,
# Set the SEA_SPEED of OBSSeascapeShader
[Alias('SEA_SPEED')]
[ComponentModel.DefaultBindingProperty('SEA_SPEED')]
[Single]
$SEASPEED,
# Set the SEA_FREQ of OBSSeascapeShader
[Alias('SEA_FREQ')]
[ComponentModel.DefaultBindingProperty('SEA_FREQ')]
[Single]
$SEAFREQ,
# Set the SEA_BASE of OBSSeascapeShader
[Alias('SEA_BASE')]
[ComponentModel.DefaultBindingProperty('SEA_BASE')]
[String]
$SEABASE,
# Set the SEA_WATER_COLOR of OBSSeascapeShader
[Alias('SEA_WATER_COLOR')]
[ComponentModel.DefaultBindingProperty('SEA_WATER_COLOR')]
[String]
$SEAWATERCOLOR,
# Set the CAMERA_SPEED of OBSSeascapeShader
[Alias('CAMERA_SPEED')]
[ComponentModel.DefaultBindingProperty('CAMERA_SPEED')]
[Single]
$CAMERASPEED,
# Set the CAMERA_TURN_SPEED of OBSSeascapeShader
[Alias('CAMERA_TURN_SPEED')]
[ComponentModel.DefaultBindingProperty('CAMERA_TURN_SPEED')]
[Single]
$CAMERATURNSPEED,
# 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 = 'seascape'
$ShaderNoun = 'OBSSeascapeShader'
if (-not $psBoundParameters['ShaderText']) {    
    $psBoundParameters['ShaderText'] = $ShaderText = '
/*
 * "Seascape" by Alexander Alekseev aka TDM - 2014
 * License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 * Contact: tdmaav@gmail.com
 * https://www.shadertoy.com/view/Ms2SD1 adapted by Exeldro
 */

#define NUM_STEPS 8
#define PI 3.141592
#define EPSILON 0.001
uniform bool AA<
    string label = "Smooth (more resources)";
> = false;

#ifndef OPENGL
#define mat2 float2x2
#define mat3 float3x3
#define fract frac
#define mix lerp
#endif

// sea
#define ITER_GEOMETRY 3
#define ITER_FRAGMENT 5
uniform float SEA_HEIGHT<
    string label = "Sea Height";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 1.5;
    float step = 0.001;
> = 0.6;
uniform float SEA_CHOPPY<
    string label = "Sea Choppy";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 10.0;
    float step = 0.001;
> = 4.0;
uniform float SEA_SPEED<
    string label = "Sea Speed";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 10.0;
    float step = 0.001;
> = 0.8;
uniform float SEA_FREQ<
    string label = "Sea Frequency";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 0.5;
    float step = 0.001;
> = 0.16;
uniform float4 SEA_BASE<
    string label = "Sea Base";
> = {0.0,0.09,0.18,1.0};
uniform float4 SEA_WATER_COLOR<
    string label = "Sea Water";
> = {0.48,0.54,0.36,1.0};

uniform float CAMERA_SPEED<
    string label = "Camera Speed";
    string widget_type = "slider";
    float minimum = -10.0;
    float maximum = 10.0;
    float step = 0.001;
> = 1.0;

uniform float CAMERA_TURN_SPEED<
    string label = "Camera Turn Speed";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 10.0;
    float step = 0.001;
> = 1.0;


float SEA_TIME(){
    return 1.0 + elapsed_time * SEA_SPEED;
}

// math
mat3 fromEuler(float3 ang) {
    float2 a1 = float2(sin(ang.x),cos(ang.x));
    float2 a2 = float2(sin(ang.y),cos(ang.y));
    float2 a3 = float2(sin(ang.z),cos(ang.z));
    return mat3(float3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x),
    float3(-a2.y*a1.x,a1.y*a2.y,a2.x),
    float3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y));
}

float hash(float2 p) {
    float h = dot(p,float2(127.1,311.7));
    return fract(sin(h)*43758.5453123);
}

float noise(float2 p) {
    float2 i = floor( p );
    float2 f = fract( p );
    float2 u = f*f*(3.0-2.0*f);
    return -1.0+2.0*mix( mix( hash( i + float2(0.0,0.0) ),
                     hash( i + float2(1.0,0.0) ), u.x),
                mix( hash( i + float2(0.0,1.0) ),
                     hash( i + float2(1.0,1.0) ), u.x), u.y);
}

// lighting
float diffuse(float3 n,float3 l,float p) {
    return pow(dot(n,l) * 0.4 + 0.6,p);
}
float specular(float3 n,float3 l,float3 e,float s) {
    float nrm = (s + 8.0) / (PI * 8.0);
    return pow(max(dot(reflect(e,n),l),0.0),s) * nrm;
}

// sky
float3 getSkyColor(float3 e) {
    e.y = (max(e.y,0.0)*0.8+0.2)*0.8;
    return float3(pow(1.0-e.y,2.0), 1.0-e.y, 0.6+(1.0-e.y)*0.4) * 1.1;
}

// sea
float sea_octave(float2 uv, float choppy) {
    uv += noise(uv);
    float2 wv = 1.0-abs(sin(uv));
    float2 swv = abs(cos(uv));
    wv = mix(wv,swv,wv);
    return pow(1.0-pow(wv.x * wv.y,0.65),choppy);
}

float map(float3 p) {
    float freq = SEA_FREQ;
    float amp = SEA_HEIGHT;
    float choppy = SEA_CHOPPY;
    float2 uv = p.xz;
    uv.x *= 0.75;
    mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);

    float st = SEA_TIME();
    float d, h = 0.0;
    for(int i = 0; i < ITER_GEOMETRY; i++) {
        d = sea_octave((uv+float2(st,st))*freq,choppy);
        d += sea_octave((uv-float2(st,st))*freq,choppy);
        h += d * amp;
        uv = mul(uv, octave_m);
        freq *= 1.9;
        amp *= 0.22;
        choppy = mix(choppy,1.0,0.2);
    }
    return p.y - h;
}

float map_detailed(float3 p) {
    float freq = SEA_FREQ;
    float amp = SEA_HEIGHT;
    float choppy = SEA_CHOPPY;
    float2 uv = p.xz; uv.x *= 0.75;
    mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);
    float st = SEA_TIME();
    float d, h = 0.0;
    for(int i = 0; i < ITER_FRAGMENT; i++) {
        d = sea_octave((uv+float2(st,st))*freq,choppy);
        d += sea_octave((uv-float2(st,st))*freq,choppy);
        h += d * amp;
        uv = mul(uv, octave_m);
        freq *= 1.9;
        amp *= 0.22;
        choppy = mix(choppy,1.0,0.2);
    }
    return p.y - h;
}

float3 getSeaColor(float3 p, float3 n, float3 l, float3 eye, float3 dist) {
    float fresnel = clamp(1.0 - dot(n,-eye), 0.0, 1.0);
    fresnel = min(pow(fresnel,3.0), 0.5);
        
    float3 reflected = getSkyColor(reflect(eye,n));
    float3 refracted = SEA_BASE.rgb + diffuse(n,l,80.0) * SEA_WATER_COLOR.rgb * 0.12;
    
    float3 color = mix(refracted,reflected,fresnel);
    
    float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0);
    color += SEA_WATER_COLOR.rgb * (p.y - SEA_HEIGHT) * 0.18 * atten;
    
    float s = specular(n,l,eye,60.0);
    color += float3(s,s,s);
    
    return color;
}

// tracing
float3 getNormal(float3 p, float eps) {
    float3 n;
    n.y = map_detailed(p);
    n.x = map_detailed(float3(p.x+eps,p.y,p.z)) - n.y;
    n.z = map_detailed(float3(p.x,p.y,p.z+eps)) - n.y;
    n.y = eps;
    return normalize(n);
}

float heightMapTracing(float3 ori, float3 dir, out float3 p) {
    float tm = 0.0;
    float tx = 1000.0;
    float hx = map(ori + dir * tx);
    if(hx > 0.0) {
        p = ori + dir * tx;
        return tx;
    }
    float hm = map(ori + dir * tm);
    float tmid = 0.0;
    for(int i = 0; i < NUM_STEPS; i++) {
        tmid = mix(tm,tx, hm/(hm-hx));
        p = ori + dir * tmid;
        float hmid = map(p);
        if(hmid < 0.0) {
            tx = tmid;
            hx = hmid;
        } else {
            tm = tmid;
            hm = hmid;
        }
    }
    return tmid;
}

float3 getPixel(in float2 coord, float time) {
    float2 uv = coord / uv_size.xy;
    uv = uv * 2.0 - 1.0;
    uv.x *= uv_size.x / uv_size.y;
        
    // ray
    float3 ang = float3(sin(time*3.0*CAMERA_TURN_SPEED)*0.1,sin(time*CAMERA_TURN_SPEED)*0.2+0.3,time*CAMERA_TURN_SPEED);
    float3 ori = float3(0.0,3.5,time*5.0*CAMERA_SPEED);
    float3 dir = normalize(float3(uv.xy,-2.0));
    dir.z += length(uv) * 0.14;
    dir = mul(normalize(dir), fromEuler(ang));
    
    // tracing
    float3 p;
    heightMapTracing(ori,dir,p);
    float3 dist = p - ori;
    float3 n = getNormal(p, dot(dist,dist) * (0.1 / uv_size.x));
    float3 light = normalize(float3(0.0,1.0,0.8));
             
    // color
    return mix(
        getSkyColor(dir),
        getSeaColor(p,n,light,dir,dist),
        pow(smoothstep(0.0,-0.02,dir.y),0.2));
}

// main
float4 mainImage(VertData v_in) : TARGET
{
    float time = elapsed_time * 0.3;
    float2 fragCoord = float2(v_in.uv.x * uv_size.x, (1.0 - v_in.uv.y) * uv_size.y);
    
    float3 color = float3(0.0,0.0,0.0);;
    if (AA){
        for(int i = -1; i <= 1; i++) {
            for(int j = -1; j <= 1; j++) {
                float2 uv = fragCoord+float2(i,j)/3.0;
                color += getPixel(uv, time);
            }
        }
        color /= 9.0;
    }else{
        color = getPixel(fragCoord, time);
    }
    
    // post
    return float4(pow(color,float3(0.65,0.65,0.65)), 1.0);
}
'

}
$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
        }
    }
}

}


}