Commands/Shaders/Get-OBSNightSkyShader.ps1

function Get-OBSNightSkyShader {

[Alias('Set-OBSNightSkyShader','Add-OBSNightSkyShader')]
param(
# Set the speed of OBSNightSkyShader
[ComponentModel.DefaultBindingProperty('speed')]
[Single]
$Speed,
# Set the Include_Clouds of OBSNightSkyShader
[Alias('Include_Clouds')]
[ComponentModel.DefaultBindingProperty('Include_Clouds')]
[Management.Automation.SwitchParameter]
$IncludeClouds,
# Set the Include_Moon of OBSNightSkyShader
[Alias('Include_Moon')]
[ComponentModel.DefaultBindingProperty('Include_Moon')]
[Management.Automation.SwitchParameter]
$IncludeMoon,
# Set the center_width_percentage of OBSNightSkyShader
[Alias('center_width_percentage')]
[ComponentModel.DefaultBindingProperty('center_width_percentage')]
[Int32]
$CenterWidthPercentage,
# Set the center_height_percentage of OBSNightSkyShader
[Alias('center_height_percentage')]
[ComponentModel.DefaultBindingProperty('center_height_percentage')]
[Int32]
$CenterHeightPercentage,
# Set the Alpha_Percentage of OBSNightSkyShader
[Alias('Alpha_Percentage')]
[ComponentModel.DefaultBindingProperty('Alpha_Percentage')]
[Single]
$AlphaPercentage,
# Set the Apply_To_Image of OBSNightSkyShader
[Alias('Apply_To_Image')]
[ComponentModel.DefaultBindingProperty('Apply_To_Image')]
[Management.Automation.SwitchParameter]
$ApplyToImage,
# Set the Replace_Image_Color of OBSNightSkyShader
[Alias('Replace_Image_Color')]
[ComponentModel.DefaultBindingProperty('Replace_Image_Color')]
[Management.Automation.SwitchParameter]
$ReplaceImageColor,
# Set the number_stars of OBSNightSkyShader
[Alias('number_stars')]
[ComponentModel.DefaultBindingProperty('number_stars')]
[Int32]
$NumberStars,
# Set the SKY_COLOR of OBSNightSkyShader
[Alias('SKY_COLOR')]
[ComponentModel.DefaultBindingProperty('SKY_COLOR')]
[String]
$SKYCOLOR,
# Set the STAR_COLOR of OBSNightSkyShader
[Alias('STAR_COLOR')]
[ComponentModel.DefaultBindingProperty('STAR_COLOR')]
[String]
$STARCOLOR,
# Set the LIGHT_SKY of OBSNightSkyShader
[Alias('LIGHT_SKY')]
[ComponentModel.DefaultBindingProperty('LIGHT_SKY')]
[String]
$LIGHTSKY,
# Set the SKY_LIGHTNESS of OBSNightSkyShader
[Alias('SKY_LIGHTNESS')]
[ComponentModel.DefaultBindingProperty('SKY_LIGHTNESS')]
[Single]
$SKYLIGHTNESS,
# Set the MOON_COLOR of OBSNightSkyShader
[Alias('MOON_COLOR')]
[ComponentModel.DefaultBindingProperty('MOON_COLOR')]
[String]
$MOONCOLOR,
# Set the moon_size of OBSNightSkyShader
[Alias('moon_size')]
[ComponentModel.DefaultBindingProperty('moon_size')]
[Single]
$MoonSize,
# Set the moon_bump_size of OBSNightSkyShader
[Alias('moon_bump_size')]
[ComponentModel.DefaultBindingProperty('moon_bump_size')]
[Single]
$MoonBumpSize,
# Set the Moon_Position_x of OBSNightSkyShader
[Alias('Moon_Position_x')]
[ComponentModel.DefaultBindingProperty('Moon_Position_x')]
[Single]
$MoonPositionX,
# Set the Moon_Position_y of OBSNightSkyShader
[Alias('Moon_Position_y')]
[ComponentModel.DefaultBindingProperty('Moon_Position_y')]
[Single]
$MoonPositionY,
# 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 = 'night_sky'
$ShaderNoun = 'OBSNightSkyShader'
if (-not $psBoundParameters['ShaderText']) {    
    $psBoundParameters['ShaderText'] = $ShaderText = '
// Night Sky shader by Charles Fettinger for obs-shaderfilter plugin 6/2020 v.65
// https://github.com/Oncorporation/obs-shaderfilter
//https://www.shadertoy.com/view/3tfXRM Simple Night Sky - converted from and updated
//Converted to OpenGL by Q-mii & Exeldro February 22, 2022
uniform float speed<
    string label = "Speed";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 100.0;
    float step = 0.01;
> = 20.0;
uniform bool Include_Clouds = true;
uniform bool Include_Moon = true;
uniform int center_width_percentage<
    string label = "Center width percentage";
    string widget_type = "slider";
    int minimum = 0;
    int maximum = 100;
    int step = 1;
> = 50;
uniform int center_height_percentage<
    string label = "Center width percentage";
    string widget_type = "slider";
    int minimum = 0;
    int maximum = 100;
    int step = 1;
> = 50;
uniform float Alpha_Percentage<
    string label = "Alpha Percentage";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 100.0;
    float step = 0.01;
> = 95.0; //<Range(0.0,100.0)>
uniform bool Apply_To_Image = false;
uniform bool Replace_Image_Color = false;
uniform int number_stars<
    string label = "Number stars";
    string widget_type = "slider";
    int minimum = 0;
    int maximum = 100;
    int step = 1;
> = 20; //<Range(0,100)>

uniform float4 SKY_COLOR = { 0.027, 0.151, 0.354, 1.0 };
uniform float4 STAR_COLOR = { 0.92, 0.92, 0.14, 1.0 };
uniform float4 LIGHT_SKY = { 0.45, 0.61, 0.98, 1.0 };
uniform float SKY_LIGHTNESS<
    string label = "SKY LIGHTNESS";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 1.0;
    float step = 0.001;
> = .3;

 // Moon
uniform float4 MOON_COLOR = { .4, .25, 0.25, 1.0 };
uniform float moon_size<
    string label = "Moon size";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 1.0;
    float step = 0.001;
> = 0.18;
uniform float moon_bump_size<
    string label = "Moon bump size";
    string widget_type = "slider";
    float minimum = 0.0;
    float maximum = 1.0;
    float step = 0.001;
> = 0.14;
uniform float Moon_Position_x<
    string label = "Moon Position x";
    string widget_type = "slider";
    float minimum = -1.0;
    float maximum = 1.0;
    float step = 0.001;
> = -0.6;
uniform float Moon_Position_y<
    string label = "Moon Position y";
    string widget_type = "slider";
    float minimum = -1.0;
    float maximum = 1.0;
    float step = 0.001;
> = -0.3;

#define PI 3.1416

//Noise functions from https://www.youtube.com/watch?v=zXsWftRdsvU
float noise11(float p) {
    return frac(sin(p*633.1847) * 9827.95);
}
    
float noise21(float2 p) {
    return frac(sin(p.x*827.221 + p.y*3228.8275) * 878.121);
}

float2 noise22(float2 p) {
    return frac(float2(sin(p.x*9378.35), sin(p.y*75.589)) * 556.89);
}

//From https://codepen.io/Tobsta/post/procedural-generation-part-1-1d-perlin-noise
float cosineInterpolation(float a, float b, float x) {
    float ft = x * PI;
    float f = (1. - cos(ft)) * .5;
    return a * (1. - f) + b * f;
}

float smoothNoise11(float p, float dist) {
    float prev = noise11(p-dist);
    float next = noise11(p+dist);
       
    return cosineInterpolation(prev, next, .5);
}

float smoothNoise21(float2 uv, float cells) {
    float2 lv = frac(uv*cells);
    float2 id = floor(uv*cells);
    
    //smoothstep function: maybe change it later!
    lv = lv*lv*(3.-2.*lv);
    
    float bl = noise21(id);
    float br = noise21(id+float2(1.,0.));
    float b = lerp(bl, br, lv.x);
    
    float tl = noise21(id+float2(0.,1.));
    float tr = noise21(id+float2(1.,1.));
    float t = lerp(tl, tr, lv.x);
    
    return lerp(b, t, lv.y);
}

float2 smoothNoise22(float2 uv, float cells) {
    float2 lv = frac(uv*cells);
    float2 id = floor(uv*cells);
    
    lv = lv*lv*(3.-2.*lv);
    
    float2 bl = noise22(id);
    float2 br = noise22(id+float2(1.,0.));
    float2 b = lerp(bl, br, lv.x);
    
    float2 tl = noise22(id+float2(0.,1.));
    float2 tr = noise22(id+float2(1.,1.));
    float2 t = lerp(tl, tr, lv.x);
    
    return lerp(b, t, lv.y);
}

float valueNoise11(float p) {
    float c = smoothNoise11(p, 0.5);
    c += smoothNoise11(p, 0.25)*.5;
    c += smoothNoise11(p, 0.125)*.25;
    c += smoothNoise11(p, 0.0625)*.125;
    
    return c /= .875;
}

float valueNoise21(float2 uv) {
    float c = smoothNoise21(uv, 4.);
    c += smoothNoise21(uv, 8.)*.5;
    c += smoothNoise21(uv, 16.)*.25;
    c += smoothNoise21(uv, 32.)*.125;
    c += smoothNoise21(uv, 64.)*.0625;
    
    return c /= .9375;
}

float2 valueNoise22(float2 uv) {
    float2 c = smoothNoise22(uv, 4.);
    c += smoothNoise22(uv, 8.)*.5;
    c += smoothNoise22(uv, 16.)*.25;
    c += smoothNoise22(uv, 32.)*.125;
    c += smoothNoise22(uv, 64.)*.0625;
    
    return c /= .9375;
}

float3 points(float2 p, float2 uv, float3 color, float size, float blur) {
    float dist = distance(p, uv);
    return color*smoothstep(size, size*(0.999-blur), dist);
}

float mapInterval(float x, float a, float b, float c, float d) {
    return (x-a)/(b-a) * (d-c) + c;
}

float blink(float time, float timeInterval) {
    float halfInterval = timeInterval / 2.0;
    //Get relative position in the bucket
    float p = fmod(time, timeInterval);
    
    
    if (p <= timeInterval / 2.) {
        return smoothstep(0., 1., p/halfInterval);
    } else {
        return smoothstep(1., 0., (p-halfInterval)/halfInterval);
    }
}

float3 sampleBumps(float2 p, float2 uv, float radius, float spin) {
    float dist = distance(p, uv);
    float3 BumpSamples = float3(0.,0.,0.);
    
    if (dist < radius) {
        float bumps = (1.-valueNoise21(uv*spin))*.1;
        BumpSamples = float3(bumps, bumps, bumps);
    }
    return BumpSamples;
}

float4 mainImage(VertData v_in) : TARGET
{
    float4 rgba;// = image.Sample(textureSampler, v_in.uv);
    float alpha = clamp(Alpha_Percentage *.01 ,0,1.0);
    float2 center_pixel_coordinates = float2((center_width_percentage * 0.01), (center_height_percentage * 0.01));
    float2 st = v_in.uv* uv_scale;
    float2 toCenter = center_pixel_coordinates - st;

    // Normalized pixel coordinates (from 0 to 1)
    float2 uv = v_in.uv;
    float2 ouv = uv;
    uv -= .5;
    uv.x *= uv_size.x/uv_size.y;
    
    float2 seed = toCenter / uv_size.xy;
    
    float time = elapsed_time + seed.x*speed;
        
    //float3 col = float3(0.0);
    //float m = valueNoise21(uv);
    float3 col = lerp(SKY_COLOR.rgb, LIGHT_SKY.rgb, ouv.y-SKY_LIGHTNESS);
    
    col *= SKY_LIGHTNESS - (1.-ouv.y);
    
    //Add clouds
    if (Include_Clouds)
    {
        float2 timeUv = uv;
        timeUv.x += time*.1;
        timeUv.y += valueNoise11(timeUv.x+.352)*.01;
        float cloud = valueNoise21(timeUv);
        col += cloud*.1;
    }

    //Add stars in the top part of the scene
    float timeInterval = speed *.5; //5.0
    float timeBucket = floor(time / timeInterval);

    float2 moonPosition = float2(-1000, -1000);
    if (Include_Moon)
    {
        moonPosition = float2(Moon_Position_x, Moon_Position_y);
        col += points(moonPosition, uv, MOON_COLOR.rgb,moon_size, 0.3);
        // Moon bumps
        col += sampleBumps(moonPosition, uv, moon_bump_size, 9. + fmod(time*.1,9));
    }

    for (float i = 0.; i < clamp(number_stars,0,100); i++) {
        float2 starPosition = float2(i/10., i/10.);
        
        starPosition.x = mapInterval(valueNoise11(timeBucket + i*827.913)-.4, 0., 1., 0.825, -0.825);
        starPosition.y = mapInterval(valueNoise11(starPosition.x)-.3, 0., 1., 0.445, -0.445);
        
        float starIntensity = blink(time+ (rand_f * i), timeInterval );
        //Hide stars that are behind the moon
        if (distance(starPosition, moonPosition) > moon_size) {
            col += points(starPosition, uv, STAR_COLOR.rgb, 0.001, 0.0)*clamp(starIntensity-.1, 0.0, 1.0)*10.0;
            col += points(starPosition, uv, STAR_COLOR.rgb, 0.009, 3.5)*starIntensity*3.0;
        }
    }
    //col = float3(blink(time, timeInterval));
    rgba = float4(col,alpha);

    // Output to screen
    if (Apply_To_Image)
    {
        float4 color = image.Sample(textureSampler, v_in.uv);
        float4 original_color = color;
        float luma = color.r * 0.299 + color.g * 0.587 + color.b * 0.114;
        if (Replace_Image_Color)
            color = float4(luma, luma, luma, luma);
        rgba = lerp(original_color, rgba * color,alpha);
        
    }
    return rgba;
}

'

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

}


}