Skip to content

Instantly share code, notes, and snippets.

@agrif
Forked from ion1/pixelate-rectangle.shader
Last active October 1, 2020 23:59
Show Gist options
  • Save agrif/c9ec6d161611cb2257be9d7c5ef14250 to your computer and use it in GitHub Desktop.
Save agrif/c9ec6d161611cb2257be9d7c5ef14250 to your computer and use it in GitHub Desktop.
Censor a part of the screen (such as a chat window) by pixelation in obs-shaderfilter
// Censor a part of the screen (such as a chat window) by pixelation in
// obs-shaderfilter.
// https://obsproject.com/forum/resources/obs-shaderfilter.775/
// https://creativecommons.org/publicdomain/zero/1.0/
// To the extent possible under law, ion has waived all copyright and related
// or neighboring rights to obs-pixelate-rectangle. This work is published
// from: Suomi.
// originally from
// https://gist.github.com/ion1/0e028ad096aa6f375bc9a97334639fa3
// modified to work with StreamFX
// https://github.com/Xaymar/obs-StreamFX/
// https://gist.github.com/agrif/c9ec6d161611cb2257be9d7c5ef14250
uniform float4x4 ViewProj<bool automatic = true;>;
uniform float4 ViewSize<bool automatic = true;>;
uniform texture2d InputA<bool automatic = true;>;
uniform int Square_Size<string name = "Square Size"; int minimum = 0;> = 8;
uniform float Left<float minimum = 0; float maximum = 100; string field_type = "slider";> = 0;
uniform float Right<float minimum = 0; float maximum = 100; string field_type = "slider";> = 0;
uniform float Top<float minimum = 0; float maximum = 100; string field_type = "slider";> = 0;
uniform float Bottom<float minimum = 0; float maximum = 100; string field_type = "slider";> = 0;
sampler_state textureSampler {
AddressU = Clamp;
AddressV = Clamp;
Filter = Linear;
};
struct VertData {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
// Very rough approximations.
float3 to_linear(float3 col) {
return col * col;
}
float3 from_linear(float3 col) {
return sqrt(col);
}
float3 sample(float2 square_top_left, uint sx, uint sy, float2 dx, float2 dy)
{
float2 pos = square_top_left + (float2(sx, sy) + 0.5) * Square_Size / 8.0;
// OBS doesn't seem to generate mipmaps, this will just sample the unscaled
// texture for now.
return to_linear(InputA.SampleGrad(textureSampler, pos * ViewSize.zw, dx, dy).rgb);
}
float3 square(VertData v_in)
{
uint2 pixel = floor(v_in.uv * ViewSize.xy);
uint2 square_top_left = pixel - (pixel % Square_Size);
// Sample 8 points from each square following this 8x MSAA pattern:
// https://docs.microsoft.com/windows/win32/api/d3d11/ne-d3d11-d3d11_standard_multisample_quality_levels
float2 dx = ddx(v_in.uv) * Square_Size / 8.0;
float2 dy = ddy(v_in.uv) * Square_Size / 8.0;
float3 col = 0;
col += sample(square_top_left, 7, 0, dx, dy);
col += sample(square_top_left, 2, 1, dx, dy);
col += sample(square_top_left, 4, 2, dx, dy);
col += sample(square_top_left, 0, 3, dx, dy);
col += sample(square_top_left, 6, 4, dx, dy);
col += sample(square_top_left, 3, 5, dx, dy);
col += sample(square_top_left, 1, 6, dx, dy);
col += sample(square_top_left, 5, 7, dx, dy);
col /= 8;
return col;
}
VertData VSDefault(VertData v_in) {
VertData vert_out;
vert_out.pos = mul(float4(v_in.pos.xyz, 1.0), ViewProj);
vert_out.uv = v_in.uv;
return vert_out;
}
float4 PSDefault(VertData v_in) : TARGET {
if (v_in.uv.x >= Left * 0.01 &&
v_in.uv.x < 1.0 - Right * 0.01 &&
v_in.uv.y >= Top * 0.01 &&
v_in.uv.y < 1.0 - Bottom * 0.01) {
return float4(from_linear(square(v_in)), 1.0);
} else {
return InputA.Sample(textureSampler, v_in.uv);
}
}
technique Draw
{
pass
{
vertex_shader = VSDefault(v_in);
pixel_shader = PSDefault(v_in);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment