From b73e2e8cf4c7c8fefc29c573473395d3579199f8 Mon Sep 17 00:00:00 2001 From: Exeldro Date: Tue, 14 Jan 2025 09:44:57 +0100 Subject: [PATCH] Add clock_digital_led.shader --- data/examples/clock_digital_led.shader | 176 +++++++++++++++++++++++++ obs-shaderfilter.c | 27 ++-- 2 files changed, 195 insertions(+), 8 deletions(-) create mode 100644 data/examples/clock_digital_led.shader diff --git a/data/examples/clock_digital_led.shader b/data/examples/clock_digital_led.shader new file mode 100644 index 00000000..6f3b9a70 --- /dev/null +++ b/data/examples/clock_digital_led.shader @@ -0,0 +1,176 @@ +// 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 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; + + float timeSecs = 0.0; + if(timeMode == 0){ + timeSecs = local_time; + }else 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 > 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); +} \ No newline at end of file diff --git a/obs-shaderfilter.c b/obs-shaderfilter.c index 44f212f5..49d6abfa 100644 --- a/obs-shaderfilter.c +++ b/obs-shaderfilter.c @@ -40,6 +40,7 @@ uniform float elapsed_time_show;\n\ uniform float elapsed_time_active;\n\ uniform float elapsed_time_enable;\n\ uniform int loops;\n\ +uniform float loop_second;\n\ uniform float local_time;\n\ \n\ sampler_state textureSampler{\n\ @@ -184,6 +185,7 @@ struct shader_filter_data { gs_eparam_t *param_elapsed_time_active; gs_eparam_t *param_elapsed_time_enable; gs_eparam_t *param_loops; + gs_eparam_t *param_loop_second; gs_eparam_t *param_local_time; gs_eparam_t *param_rand_f; gs_eparam_t *param_rand_instance_f; @@ -307,6 +309,7 @@ static void shader_filter_clear_params(struct shader_filter_data *filter) filter->param_rand_activation_f = NULL; filter->param_rand_instance_f = NULL; filter->param_loops = NULL; + filter->param_loop_second = NULL; filter->param_local_time = NULL; filter->param_image = NULL; filter->param_image_a = NULL; @@ -513,6 +516,8 @@ static void shader_filter_reload_effect(struct shader_filter_data *filter) filter->param_rand_instance_f = param; } else if (strcmp(info.name, "loops") == 0) { filter->param_loops = param; + } else if (strcmp(info.name, "loop_second") == 0) { + filter->param_loop_second = param; } else if (strcmp(info.name, "local_time") == 0) { filter->param_local_time = param; } else if (strcmp(info.name, "ViewProj") == 0) { @@ -2495,8 +2500,8 @@ static void shader_filter_tick(void *data, float seconds) } filter->elapsed_time += seconds; filter->elapsed_time_loop += seconds; - if (filter->elapsed_time_loop > 1.) { - filter->elapsed_time_loop -= 1.; + if (filter->elapsed_time_loop > 1.0f) { + filter->elapsed_time_loop -= 1.0f; // Loops filter->loops += 1; @@ -2509,6 +2514,16 @@ static void shader_filter_tick(void *data, float seconds) if (filter->enabled) filter->shader_enable_time = filter->elapsed_time; } + if (obs_source_enabled(filter->context) && obs_source_active(obs_filter_get_parent(filter->context))) { + filter->shader_active_time += seconds; + } else { + filter->shader_active_time = 0.0f; + } + if (obs_source_enabled(filter->context) && obs_source_showing(obs_filter_get_parent(filter->context))) { + filter->shader_show_time += seconds; + } else { + filter->shader_show_time = 0.0f; + } // undecided between this and "rand_float(1);" filter->rand_f = (float)((double)rand_interval(0, 10000) / (double)10000); @@ -2620,10 +2635,10 @@ void shader_filter_set_effect_params(struct shader_filter_data *filter) gs_effect_set_float(filter->param_elapsed_time_start, filter->elapsed_time - filter->shader_start_time); } if (filter->param_elapsed_time_show != NULL) { - gs_effect_set_float(filter->param_elapsed_time_show, filter->elapsed_time - filter->shader_show_time); + gs_effect_set_float(filter->param_elapsed_time_show, filter->shader_show_time); } if (filter->param_elapsed_time_active != NULL) { - gs_effect_set_float(filter->param_elapsed_time_active, filter->elapsed_time - filter->shader_active_time); + gs_effect_set_float(filter->param_elapsed_time_active, filter->shader_active_time); } if (filter->param_elapsed_time_enable != NULL) { gs_effect_set_float(filter->param_elapsed_time_enable, filter->elapsed_time - filter->shader_enable_time); @@ -2834,8 +2849,6 @@ void shader_filter_param_source_action(void *data, void (*action)(obs_source_t * void shader_filter_activate(void *data) { - struct shader_filter_data *filter = data; - filter->shader_active_time = filter->elapsed_time; shader_filter_param_source_action(data, obs_source_inc_active); } @@ -2846,8 +2859,6 @@ void shader_filter_deactivate(void *data) void shader_filter_show(void *data) { - struct shader_filter_data *filter = data; - filter->shader_show_time = filter->elapsed_time; shader_filter_param_source_action(data, obs_source_inc_showing); }