Skip to content

Commit

Permalink
Add smart denoise shader (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
euiko authored Feb 10, 2025
1 parent 35edcbb commit ad47a71
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) |
Expand Down
76 changes: 76 additions & 0 deletions data/examples/smart_denoise.shader
Original file line number Diff line number Diff line change
@@ -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);
}

0 comments on commit ad47a71

Please sign in to comment.