From ad47a7114d2789b51357b685dd7a7e08a83cf489 Mon Sep 17 00:00:00 2001 From: Kharista Date: Tue, 11 Feb 2025 01:06:13 +0700 Subject: [PATCH] Add smart denoise shader (#68) --- README.md | 1 + data/examples/smart_denoise.shader | 76 ++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 data/examples/smart_denoise.shader diff --git a/README.md b/README.md index 9f6ec8cf..afe21d2f 100644 --- a/README.md +++ b/README.md @@ -211,6 +211,7 @@ I recommend *.shader* as they do not require `Use Effect File (.effect)` as pixe | selective_color.shader | Create black and white effects with some colorization. (defaults: .4,.03,.25,.25, 5.0, true,true, true, true. cuttoff higher = less color, 0 = all 1 = none) | ![image](https://github.com/exeldro/obs-shaderfilter/assets/5457024/868780e9-aa88-4546-a1cb-d7fcc23a18ca) | | shake.effect | creates random screen glitch style shake. Keep the random_scale low for small (0.2-1) for small jerky movements and larger for less often big jumps. | | | shine.shader | Add shine / glow to any element, use the transition luma wipes (obs-studio\plugins\obs-transitions\data\luma_wipes *SOME NEW WIPES INCLUDED IN THIS RELEASE ZIP*) or create your own, also includes a glitch (using rand_f), hide/reveal, reverse and ease, start adjustment and stop adjustment | | +| smart_denoise.shader | A shader that denoise your noisy video input, based on the GLSL implementation in [BrutPitt/glslSmartDeNoise](https://github.com/BrutPitt/glslSmartDeNoise) | | | spotlight.shader | Creates a stationary or animated spotlight effect with color options, speed of animation and glitch | ![image](https://github.com/exeldro/obs-shaderfilter/assets/5457024/f9aebc02-4da5-4d30-b2f3-a9d9d7511f9f) | | Swirl.shader | | ![image](https://github.com/exeldro/obs-shaderfilter/assets/5457024/722bc6fc-7c75-455f-a3bd-94607e621e74) | | thermal.shader | | ![image](https://github.com/exeldro/obs-shaderfilter/assets/5457024/f12e1040-51a6-4401-a84b-160f19c8f907) | diff --git a/data/examples/smart_denoise.shader b/data/examples/smart_denoise.shader new file mode 100644 index 00000000..02997cd6 --- /dev/null +++ b/data/examples/smart_denoise.shader @@ -0,0 +1,76 @@ +// Smart DeNoise By Michele Morrone (https://github.com/BrutPitt/glslSmartDeNoise) +// Converted to OBS version of HLSL by Euiko on February 10, 2025 + +#define INV_SQRT_OF_2PI 0.39894228040143267793994605993439 // 1.0/SQRT_OF_2PI +#define INV_PI 0.31830988618379067153776752674503 + +uniform float uSigma< + string label = "Sigma"; + string widget_type = "slider"; + float minimum = 0.01; + float maximum = 3; // max based on the webgl sample, which is 3 + float step = 0.01; +> = 5.0; // default value based on shadertoy +uniform float uKSigma< + string label = "K-Sigma"; + string widget_type = "slider"; + float minimum = 0.01; + float maximum = 24; // max based on the webgl sample, which is 24 + float step = 0.01; +> = 7.0; // the default value is based on the webgl sample +uniform float uThreshold< + string label = "Edge Threshold"; + string widget_type = "slider"; + float minimum = 0.01; + float maximum = 2; // max based on the webgl sample, which is 2 + float step = 0.01; +> = 0.190; // the default value is based on the webgl sample + +// smartDeNoise - parameters +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// float2 uv - actual fragment coord +// float2 size - window size +// float sigma > 0 - sigma Standard Deviation +// float kSigma >= 0 - sigma coefficient +// kSigma * sigma --> radius of the circular kernel +// float threshold - edge sharpening threshold +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// NOTE: image's texture2d data will be supplied by the OBS shaderfilter by default +float4 smartDeNoise(float2 uv, float2 size, float sigma, float kSigma, float threshold) +{ + float radius = round(kSigma * sigma); + float radQ = radius * radius; + + float invSigmaQx2 = 0.5 / (sigma * sigma); // 1.0 / (sigma^2 * 2.0) + float invSigmaQx2PI = INV_PI * invSigmaQx2; // 1/(2 * PI * sigma^2) + + float invThresholdSqx2 = 0.5 / (threshold * threshold); // 1.0 / (sigma^2 * 2.0) + float invThresholdSqrt2PI = INV_SQRT_OF_2PI / threshold; // 1.0 / (sqrt(2*PI) * sigma^2) + + float4 centrPx = image.Sample(textureSampler, uv); + + float zBuff = 0.0; + float4 aBuff = float4(0.0, 0.0, 0.0, 0.0); + + float2 d; + for (d.x = -radius; d.x <= radius; d.x += 1.0) + { + float pt = sqrt(radQ - (d.x * d.x)); // pt = yRadius: have circular trend + d.y = -pt; + for (; d.y <= pt; d.y += 1.0) + { + float blurFactor = exp((-dot(d, d)) * invSigmaQx2) * invSigmaQx2PI; + float4 walkPx = image.Sample(textureSampler, uv + (d / size)); + float4 dC = walkPx - centrPx; + float deltaFactor = (exp((-dot(dC.xyz, dC.xyz)) * invThresholdSqx2) * invThresholdSqrt2PI) * blurFactor; + zBuff += deltaFactor; + aBuff += (walkPx * deltaFactor); + } + } + return aBuff / float4(zBuff, zBuff, zBuff, zBuff); +} + +float4 mainImage(VertData v_in) : TARGET +{ + return smartDeNoise(v_in.uv, uv_size, uSigma, uKSigma, uThreshold); +}