From 5f1b86f316a3322840ae41fc8965e2c189a6d294 Mon Sep 17 00:00:00 2001 From: hunterk Date: Fri, 6 Jan 2017 12:55:29 -0600 Subject: [PATCH] add bayer-matrix, gendither and gdapt shaders --- dithering/bayer-matrix-dithering.slangp | 4 + dithering/gdapt.slangp | 11 ++ dithering/gendither.slangp | 4 + .../shaders/bayer-matrix-dithering.slang | 87 +++++++++++++++ dithering/shaders/gdapt/gdapt-pass0.slang | 78 ++++++++++++++ dithering/shaders/gdapt/gdapt-pass1.slang | 93 ++++++++++++++++ dithering/shaders/gendither.slang | 101 ++++++++++++++++++ 7 files changed, 378 insertions(+) create mode 100644 dithering/bayer-matrix-dithering.slangp create mode 100644 dithering/gdapt.slangp create mode 100644 dithering/gendither.slangp create mode 100644 dithering/shaders/bayer-matrix-dithering.slang create mode 100644 dithering/shaders/gdapt/gdapt-pass0.slang create mode 100644 dithering/shaders/gdapt/gdapt-pass1.slang create mode 100644 dithering/shaders/gendither.slang diff --git a/dithering/bayer-matrix-dithering.slangp b/dithering/bayer-matrix-dithering.slangp new file mode 100644 index 0000000..24b210f --- /dev/null +++ b/dithering/bayer-matrix-dithering.slangp @@ -0,0 +1,4 @@ +shaders = 1 + +shader0 = shaders/bayer-matrix-dithering.slang +filter_linear0 = false \ No newline at end of file diff --git a/dithering/gdapt.slangp b/dithering/gdapt.slangp new file mode 100644 index 0000000..8ec7fbd --- /dev/null +++ b/dithering/gdapt.slangp @@ -0,0 +1,11 @@ +shaders = 2 + +shader0 = shaders/gdapt/gdapt-pass0.slang +filter_linear0 = false +scale_type0 = source +scale0 = 1.0 + +shader1 = shaders/gdapt/gdapt-pass1.slang +filter_linear1 = false +scale_type1 = source +scale1 = 1.0 diff --git a/dithering/gendither.slangp b/dithering/gendither.slangp new file mode 100644 index 0000000..6ced28d --- /dev/null +++ b/dithering/gendither.slangp @@ -0,0 +1,4 @@ +shaders = 1 + +shader0 = shaders/gendither.slang +filter_linear0 = false \ No newline at end of file diff --git a/dithering/shaders/bayer-matrix-dithering.slang b/dithering/shaders/bayer-matrix-dithering.slang new file mode 100644 index 0000000..671bb6e --- /dev/null +++ b/dithering/shaders/bayer-matrix-dithering.slang @@ -0,0 +1,87 @@ +#version 450 + +// 8x8 Bayer matrix dithering +// by Martins Upitis +// license: "All the content here is and will be free to use for everyone, but a donation is always nice." +// url: http://devlog-martinsh.blogspot.com/2011/03/glsl-8x8-bayer-matrix-dithering.html +// adapted for RetroArch by hunterk + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; + float animate; + float dither_size; +} params; + +#pragma parameter animate "Dithering Animation" 0.0 0.0 1.0 1.0 +#pragma parameter dither_size "Dither Size" 0.0 0.0 0.95 0.05 + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; +} global; + +float find_closest(int x, int y, float c0) +{ + +int dither[8][8] = { +{ 0, 32, 8, 40, 2, 34, 10, 42}, /* 8x8 Bayer ordered dithering */ +{48, 16, 56, 24, 50, 18, 58, 26}, /* pattern. Each input pixel */ +{12, 44, 4, 36, 14, 46, 6, 38}, /* is scaled to the 0..63 range */ +{60, 28, 52, 20, 62, 30, 54, 22}, /* before looking in this table */ +{ 3, 35, 11, 43, 1, 33, 9, 41}, /* to determine the action. */ +{51, 19, 59, 27, 49, 17, 57, 25}, +{15, 47, 7, 39, 13, 45, 5, 37}, +{63, 31, 55, 23, 61, 29, 53, 21} }; + +float limit = 0.0; +if(x < 8) +{ +limit = (dither[x][y]+1)/64.0; +} + + +if(c0 < limit) +return 0.0; +return 1.0; +} + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +void main() +{ +float Scale = 3.0 + mod(2.0 * params.FrameCount, 32.0) * params.animate + params.dither_size; +vec4 lum = vec4(0.299, 0.587, 0.114, 0); +float grayscale = dot(texture(Source, vTexCoord), lum); +vec3 rgb = texture(Source, vTexCoord).rgb; + +vec2 xy = (vTexCoord * params.OutputSize.xy) * Scale; +int x = int(mod(xy.x, 8)); +int y = int(mod(xy.y, 8)); + +vec3 finalRGB; +finalRGB.r = find_closest(x, y, rgb.r); +finalRGB.g = find_closest(x, y, rgb.g); +finalRGB.b = find_closest(x, y, rgb.b); + +float final = find_closest(x, y, grayscale); + + FragColor = vec4(finalRGB, 1.0); +} \ No newline at end of file diff --git a/dithering/shaders/gdapt/gdapt-pass0.slang b/dithering/shaders/gdapt/gdapt-pass0.slang new file mode 100644 index 0000000..8e70145 --- /dev/null +++ b/dithering/shaders/gdapt/gdapt-pass0.slang @@ -0,0 +1,78 @@ +#version 450 + +/* + Genesis Dithering and Pseudo Transparency Shader v1.3 - Pass 0 + by Sp00kyFox, 2014 + + Neighbor anaylsis via dot product of the difference vectors. + +*/ + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; + float MODE; + float PWR; +} params; + +#pragma parameter MODE "GDAPT Monochrome Analysis" 0.0 0.0 1.0 1.0 +#pragma parameter PWR "GDAPT Color Metric Exp" 2.0 0.0 10.0 0.1 + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; +} global; + +#define dot(x,y) clamp(dot(x,y), 0.0, 1.0) // NVIDIA Fix +#define TEX(dx,dy) texture(Source, vTexCoord+vec2((dx),(dy))*t1).xyz + +// Reference: http://www.compuphase.com/cmetric.htm +float eq(vec3 A, vec3 B) +{ + vec3 diff = A-B; + float ravg = (A.x + B.x) * 0.5; + + diff *= diff * vec3(2.0 + ravg, 4.0, 3.0 - ravg); + + return pow( smoothstep(3.0, 0.0, sqrt(diff.x + diff.y + diff.z)), params.PWR ); +} + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; +layout(location = 1) out vec2 t1; + +void main() +{ + gl_Position = global.MVP * vec4(Position.xy, 0.0, 1.0); + vTexCoord = TexCoord; + t1 = params.SourceSize.zw; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 1) in vec2 t1; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +void main() +{ + vec3 C = TEX( 0, 0); + vec3 L = TEX(-1, 0); + vec3 R = TEX( 1, 0); + + float tag = 0.0; + + if(params.MODE > 0.5){ + tag = ((L == R) && (C != L)) ? 1.0 : 0.0; + } + else{ + tag = dot(normalize(C-L), normalize(C-R)) * eq(L,R); + } + + FragColor = vec4(C, tag); +} \ No newline at end of file diff --git a/dithering/shaders/gdapt/gdapt-pass1.slang b/dithering/shaders/gdapt/gdapt-pass1.slang new file mode 100644 index 0000000..54aa338 --- /dev/null +++ b/dithering/shaders/gdapt/gdapt-pass1.slang @@ -0,0 +1,93 @@ +#version 450 + +/* + Genesis Dithering and Pseudo Transparency Shader v1.3 - Pass 1 + by Sp00kyFox, 2014 + + Blends pixels based on detected dithering patterns. + +*/ + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; + float STEPS; + float DEBUG; +} params; + +#pragma parameter STEPS "GDAPT Error Prevention LVL" 1.0 0.0 5.0 1.0 +#pragma parameter DEBUG "GDAPT Adjust View" 0.0 0.0 1.0 1.0 + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; +} global; + +#define TEX(dx,dy) texture(Source, vTexCoord+vec2((dx),(dy))*t1) + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; +layout(location = 1) out vec2 t1; + +void main() +{ + gl_Position = global.MVP * vec4(Position.xy, 0.0, 1.0); + vTexCoord = TexCoord; + t1 = params.SourceSize.zw; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 1) in vec2 t1; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +void main() +{ + vec4 C = TEX( 0, 0); + vec4 L = TEX(-1, 0); + vec4 R = TEX( 1, 0); + + + float str = 0.0; + + if(params.STEPS == 0.0){ + str = C.w; + } + else if(params.STEPS == 1.0){ + str = min(max(L.w, R.w), C.w); + } + else if(params.STEPS == 2.0){ + str = min(max(min(max(TEX(-2,0).w, R.w), L.w), min(R.w, TEX(2,0).w)), C.w); + } + else if(params.STEPS == 3.0){ + float tmp = min(R.w, TEX(2,0).w); + str = min(max(min(max(min(max(TEX(-3,0).w, R.w), TEX(-2,0).w), tmp), L.w), min(tmp, TEX(3,0).w)), C.w); + } + else if(params.STEPS == 4.0){ + float tmp1 = min(R.w, TEX(2,0).w); + float tmp2 = min(tmp1, TEX(3,0).w); + str = min(max(min(max(min(max(min(max(TEX(-4,0).w, R.w), TEX(-3,0).w), tmp1), TEX(-2,0).w), tmp2), L.w), min(tmp2, TEX(4,0).w)), C.w); + } + else{ + float tmp1 = min(R.w, TEX(2,0).w); + float tmp2 = min(tmp1, TEX(3,0).w); + float tmp3 = min(tmp2, TEX(4,0).w); + str = min(max(min(max(min(max(min(max(min(max(TEX(-5,0).w, R.w), TEX(-4,0).w), tmp1), TEX(-3,0).w), tmp2), TEX(-2,0).w), tmp3), L.w), min(tmp3, TEX(5,0).w)), C.w); + } + + + if(params.DEBUG > 0.5) + FragColor = vec4(str); + + float sum = L.w + R.w; + float wght = max(L.w, R.w); + wght = (wght == 0.0) ? 1.0 : sum/wght; + + FragColor = vec4(mix(C.xyz, (wght*C.xyz + L.w*L.xyz + R.w*R.xyz)/(wght + sum), str), 1.0); +} \ No newline at end of file diff --git a/dithering/shaders/gendither.slang b/dithering/shaders/gendither.slang new file mode 100644 index 0000000..a611db4 --- /dev/null +++ b/dithering/shaders/gendither.slang @@ -0,0 +1,101 @@ +#version 450 + +// Gendither +// +// Copyright (C) 2013-2014 leilei +// adapted for slang format by hunterk +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. + +layout(push_constant) uniform Push +{ + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} params; + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; +} global; + +// This table is a lazy jailbar pattern +int erroredtable[16] = { + 0,1,0,1, + 16,15,16,15, + 0,1,0,1, + 16,15,16,15 +}; + +#pragma stage vertex +layout(location = 0) in vec4 Position; +layout(location = 1) in vec2 TexCoord; +layout(location = 0) out vec2 vTexCoord; + +void main() +{ + gl_Position = global.MVP * Position; + vTexCoord = TexCoord; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +void main() +{ + vec3 final = texture(Source, vTexCoord).rgb; + vec2 ditheu = vTexCoord.xy * params.SourceSize.xy; + + // Dither + int ditdex = int(mod(ditheu.x, 4.0)) * 4 + int(mod(ditheu.y, 4.0)); // 4x4! + ivec3 color; + ivec3 colord; + color.r = int(final.r) * 224; + color.g = int(final.g) * 224; + color.b = int(final.b) * 224; + int yeh = 0; + int ohyes = 0; + + + // looping through a lookup table matrix + for (yeh=ditdex; yeh<(ditdex+16); yeh++) ohyes = erroredtable[yeh-15]; + + colord.r = color.r + ohyes; + colord.g = color.g + ohyes; + colord.b = color.b + ohyes; + final.rgb += colord.rgb * 0.003921568627451; // divide by 255, i don't trust em + + // Reduce color depth + float why = 1.0; + vec3 reduceme = vec3(1.0); + float radooct = 4.4; // 32 is usually the proper value // 4.4 was eyeballed + + reduceme.r = pow(final.r, why); + reduceme.r *= radooct; + reduceme.r = int(floor(reduceme.r)); + reduceme.r /= radooct; + reduceme.r = pow(reduceme.r, why); + + reduceme.g = pow(final.g, why); + reduceme.g *= radooct; + reduceme.g = int(floor(reduceme.g)); + reduceme.g /= radooct; + reduceme.g = pow(reduceme.g, why); + + reduceme.b = pow(final.b, why); + reduceme.b *= radooct; + reduceme.b = int(floor(reduceme.b)); + reduceme.b /= radooct; + reduceme.b = pow(reduceme.b, why); + + // Brightness cap + reduceme.rgb = clamp(reduceme.rgb, vec3(0.0), vec3(0.875)); + + FragColor = vec4(reduceme.rgb, 1.0); +} \ No newline at end of file