Commands/Shaders/Get-OBSClockDigitalLedShader.ps1

function Get-OBSClockDigitalLedShader {

[Alias('Set-OBSClockDigitalLedShader','Add-OBSClockDigitalLedShader')]
param(
# Set the current_time_sec of OBSClockDigitalLedShader
[Alias('current_time_sec')]
[ComponentModel.DefaultBindingProperty('current_time_sec')]
[Int32]
$CurrentTimeSec,
# Set the current_time_min of OBSClockDigitalLedShader
[Alias('current_time_min')]
[ComponentModel.DefaultBindingProperty('current_time_min')]
[Int32]
$CurrentTimeMin,
# Set the current_time_hour of OBSClockDigitalLedShader
[Alias('current_time_hour')]
[ComponentModel.DefaultBindingProperty('current_time_hour')]
[Int32]
$CurrentTimeHour,
# Set the timeMode of OBSClockDigitalLedShader
[ComponentModel.DefaultBindingProperty('timeMode')]
[Int32]
$TimeMode,
# Set the showMatrix of OBSClockDigitalLedShader
[ComponentModel.DefaultBindingProperty('showMatrix')]
[Management.Automation.SwitchParameter]
$ShowMatrix,
# Set the showOff of OBSClockDigitalLedShader
[ComponentModel.DefaultBindingProperty('showOff')]
[Management.Automation.SwitchParameter]
$ShowOff,
# Set the ampm of OBSClockDigitalLedShader
[ComponentModel.DefaultBindingProperty('ampm')]
[Management.Automation.SwitchParameter]
$Ampm,
# Set the ledColor of OBSClockDigitalLedShader
[ComponentModel.DefaultBindingProperty('ledColor')]
[String]
$LedColor,
# Set the offsetHours of OBSClockDigitalLedShader
[ComponentModel.DefaultBindingProperty('offsetHours')]
[Int32]
$OffsetHours,
# Set the offsetSeconds of OBSClockDigitalLedShader
[ComponentModel.DefaultBindingProperty('offsetSeconds')]
[Int32]
$OffsetSeconds,
# 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 = 'clock_digital_led'
$ShaderNoun = 'OBSClockDigitalLedShader'
if (-not $psBoundParameters['ShaderText']) {    
    $psBoundParameters['ShaderText'] = $ShaderText = '
// based on https://www.shadertoy.com/view/MdfGzf
// cmarangu has linked all 7 segments in his comments
// https://www.shadertoy.com/view/3dtSRj

#ifndef OPENGL
#define mod(x,y) (x - y * floor(x / y))
#endif

uniform int current_time_sec;
uniform int current_time_min;
uniform int current_time_hour;

uniform int timeMode<
  string label = "Time mode";
  string widget_type = "select";
  int option_0_value = 0;
  string option_0_label = "Time";
  int option_1_value = 1;
  string option_1_label = "Enable duration";
  int option_2_value = 2;
  string option_2_label = "Active duration";
  int option_3_value = 3;
  string option_3_label = "Show duration";
  int option_4_value = 4;
  string option_4_label = "Load duration";
> = 0;

uniform bool showMatrix = false;
uniform bool showOff = false;
uniform bool ampm = false;
uniform float4 ledColor = {1.0,0,0,1.0};
uniform int offsetHours = 0;
uniform int offsetSeconds = 0;

float segment(float2 uv, bool On)
{
    if (!On && !showOff)
        return 0.0;
    
    float seg = (1.0-smoothstep(0.08,0.09+float(On)*0.02,abs(uv.x)))*
                (1.0-smoothstep(0.46,0.47+float(On)*0.02,abs(uv.y)+abs(uv.x)));
    
    //Fiddle with lights and matrix
    //uv.x += sin(elapsed_time*60.0*6.26)/14.0;
    //uv.y += cos(elapsed_time*60.0*6.26)/14.0;
    
    //led like brightness
    if (On){
        seg *= (1.0-length(uv*float2(3.8,0.9)));//-sin(elapsed_time*25.0*6.26)*0.04;
    } else {
        seg *= -(0.05+length(uv*float2(0.2,0.1)));
    }
    return seg;
}

float sevenSegment(float2 uv,int num)
{
    float seg= 0.0;
    seg += segment(uv.yx+float2(-1.0, 0.0),num!=-1 && num!=1 && num!=4 );
    seg += segment(uv.xy+float2(-0.5,-0.5),num!=-1 && num!=1 && num!=2 && num!=3 && num!=7);
    seg += segment(uv.xy+float2( 0.5,-0.5),num!=-1 && num!=5 && num!=6 );
       seg += segment(uv.yx+float2( 0.0, 0.0),num!=-1 && num!=0 && num!=1 && num!=7 );
    seg += segment(uv.xy+float2(-0.5, 0.5),num==0 || num==2 || num==6 || num==8 );
    seg += segment(uv.xy+float2( 0.5, 0.5),num!=-1 && num!=2 );
    seg += segment(uv.yx+float2( 1.0, 0.0),num!=-1 && num!=1 && num!=4 && num!=7 );
    
    return seg;
}

float showNum(float2 uv,int nr, bool zeroTrim)
{
    //Speed optimization, leave if pixel is not in segment
    if (abs(uv.x)>1.5 || abs(uv.y)>1.2)
        return 0.0;
    
    float seg= 0.0;
    if (uv.x>0.0)
    {
        nr /= 10;
        if (nr==0 && zeroTrim)
            nr = -1;
        seg += sevenSegment(uv+float2(-0.75,0.0),nr);
    } else {
        seg += sevenSegment(uv+float2( 0.75,0.0),int(mod(float(nr),10.0)));
    }

    return seg;
}

float dots(float2 uv)
{
    float seg = 0.0;
    uv.y -= 0.5;
    seg += (1.0-smoothstep(0.11,0.13,length(uv))) * (1.0-length(uv)*2.0);
    uv.y += 1.0;
    seg += (1.0-smoothstep(0.11,0.13,length(uv))) * (1.0-length(uv)*2.0);
    return seg;
}

float4 mainImage(VertData v_in) : TARGET
{
    float2 uv = ((float2(v_in.uv.x, 1.0-v_in.uv.y) * uv_size).xy-0.5*uv_size) /
                min(uv_size.x,uv_size.y);
    
    if (uv_size.x>uv_size.y)
    {
        uv *= 6.0;
    }
    else
    {
        uv *= 12.0;
    }
    
    uv.x *= -1.0;
    uv.x += uv.y/12.0;
    //wobble
    //uv.x += sin(uv.y*3.0+elapsed_time*14.0)/25.0;
    //uv.y += cos(uv.x*3.0+elapsed_time*14.0)/25.0;
    uv.x += 3.5;
    float seg = 0.0;

    if(timeMode == 0){
        seg += showNum(uv,current_time_sec,false);
        uv.x -= 1.75;
        seg += dots(uv);
        uv.x -= 1.75;
        seg += showNum(uv,current_time_min,false);
        uv.x -= 1.75;
        seg += dots(uv);
        uv.x -= 1.75;
        if (ampm) {
            if(current_time_hour == 0){
                seg += showNum(uv,12,true);
            }else if(current_time_hour > 12){
                seg += showNum(uv,current_time_hour-12,true);
            }else{
                seg += showNum(uv,current_time_hour,true);
            }
        } else {
            seg += showNum(uv,current_time_hour,true);
        }
    }else{
        float timeSecs = 0.0;
        if(timeMode == 1){
            timeSecs = elapsed_time_enable;
        }else if(timeMode == 2){
            timeSecs = elapsed_time_active;
        }else if(timeMode == 3){
            timeSecs = elapsed_time_show;
        }else if(timeMode == 4){
            timeSecs = elapsed_time_start;
        }

        timeSecs += offsetSeconds + offsetHours*3600;
        if(timeSecs < 0)
            timeSecs = 0.9999-timeSecs;
        seg += showNum(uv,int(mod(timeSecs,60.0)),false);
        
        timeSecs = floor(timeSecs/60.0);
        
        uv.x -= 1.75;

        seg += dots(uv);
        
        uv.x -= 1.75;
        
        seg += showNum(uv,int(mod(timeSecs,60.0)),false);
        
        timeSecs = floor(timeSecs/60.0);
        if (ampm)
        {
            if(timeSecs == 0.0){
                timeSecs = 12.0;
            }else if (timeSecs > 12.0){
                timeSecs = mod(timeSecs,12.0);
            }
        }else if (timeSecs > 24.0) {
            timeSecs = mod(timeSecs,24.0);
        }
        
        uv.x -= 1.75;
        
        seg += dots(uv);
        
        uv.x -= 1.75;
        seg += showNum(uv,int(mod(timeSecs,60.0)),true);
    }

    
    if (seg==0.0){
        return image.Sample(textureSampler, v_in.uv);
    }
    // matrix over segment
    if (showMatrix)
    {
        seg *= 0.8+0.2*smoothstep(0.02,0.04,mod(uv.y+uv.x,0.06025));
        //seg *= 0.8+0.2*smoothstep(0.02,0.04,mod(uv.y-uv.x,0.06025));
    }
    if (seg<0.0)
    {
        seg = -seg;;
        return float4(seg,seg,seg,1.0);
    }
    return float4(ledColor.rgb * seg, ledColor.a);
}
'

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

}


}