Created
February 1, 2023 11:42
-
-
Save kato-megumi/36812b9330ac4185fd4528e33f8c2963 to your computer and use it in GitHub Desktop.
port mpv deband shader for magpie
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Deband | |
// Port from https://github.com/haasn/gentoo-conf/blob/xor/home/nand/.mpv/shaders/deband.glsl | |
//!MAGPIE EFFECT | |
//!VERSION 2 | |
//!PARAMETER | |
//!DEFAULT 64 | |
//!MIN 0 | |
// The threshold of difference below which a pixel is considered to be part of | |
// a gradient. Higher = more debanding, but setting it too high diminishes image | |
// details. | |
float THRESHOLD; | |
//!PARAMETER | |
//!DEFAULT 8 | |
//!MIN 0 | |
// The range (in source pixels) at which to sample for neighbours. Higher values | |
// will find more gradients, but lower values will deband more aggressively. | |
float RANGE; | |
//!PARAMETER | |
//!DEFAULT 4 | |
//!MIN 0 | |
// The number of debanding iterations to perform. Each iteration samples from | |
// random positions, so increasing the number of iterations is likely to | |
// increase the debanding quality. Conversely, it slows the shader down. | |
// (Each iteration will use a multiple of the configured RANGE, and a | |
// successively lower THRESHOLD - so setting it much higher has little effect) | |
float ITERATIONS; | |
//!PARAMETER | |
//!DEFAULT 48 | |
//!MIN 0 | |
// (Optional) Add some extra noise to the image. This significantly helps cover | |
// up remaining banding and blocking artifacts, at comparatively little visual | |
// quality. Higher = more grain. Setting it to 0 disables the effect. | |
float GRAIN; | |
//!TEXTURE | |
Texture2D INPUT; | |
//!SAMPLER | |
//!FILTER POINT | |
SamplerState sam; | |
//!PASS 1 | |
//!STYLE PS | |
//!IN INPUT | |
// Wide usage friendly PRNG, shamelessly stolen from a GLSL tricks forum post | |
float mod289(float x) { return x - floor(x / 289.0) * 289.0; } | |
float permute(float x) { return mod289((34.0*x + 1.0) * x); } | |
float rand(float x) { return frac(x / 41.0); } | |
// Helper: Calculate a stochastic approximation of the avg color around a pixel | |
float4 average(float2 pos, float range, inout float h) | |
{ | |
const float2 pt = GetInputPt(); | |
// Compute a random rangle and distance | |
float dist = rand(h) * range; h = permute(h); | |
float dir = rand(h) * 6.2831853; h = permute(h); | |
float2 o = float2(cos(dir) * dist * pt.x, sin(dir) * dist * pt.y); | |
// Sample at quarter-turn intervals around the source pixel | |
float4 ref[4]; | |
ref[0] = INPUT.SampleLevel(sam, pos + float2( o.x, o.y), 0); | |
ref[1] = INPUT.SampleLevel(sam, pos + float2(-o.y, o.x), 0); | |
ref[2] = INPUT.SampleLevel(sam, pos + float2(-o.x, -o.y), 0); | |
ref[3] = INPUT.SampleLevel(sam, pos + float2( o.y, -o.x), 0); | |
// Return the (normalized) average | |
return (ref[0] + ref[1] + ref[2] + ref[3])/4.0; | |
} | |
float4 Pass1(float2 pos) | |
{ | |
// Initialize the PRNG by hashing the position + a random uniform | |
float3 m = float3(pos, 4.6); | |
float h = permute(permute(permute(m.x)+m.y)+m.z); | |
// Sample the source pixel | |
float4 col = INPUT.SampleLevel(sam, pos, 0); | |
for (int i = 1; i <= ITERATIONS; i++) { | |
// Use the average instead if the difference is below the threshold | |
float4 avg = average(pos, i*RANGE, h); | |
float4 diff = abs(col - avg); | |
float4 threshold = THRESHOLD/(i*16384.0); | |
col = lerp(avg, col, step(threshold, diff)); | |
} | |
// Add some random noise to the output | |
float3 noise; | |
noise.x = rand(h); h = permute(h); | |
noise.y = rand(h); h = permute(h); | |
noise.z = rand(h); h = permute(h); | |
col.rgb += (GRAIN/8192.0) * (noise - 0.5); | |
return col; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment