From 210034a507dd03514b5543676c97c38af1dba001 Mon Sep 17 00:00:00 2001 From: Nuno Pereira Date: Thu, 15 Dec 2022 22:58:21 +0000 Subject: [PATCH] Allow LCD-grid handheld-border shaders to scale by parameter --- .../console-border/gba-lcd-grid-v2.slangp | 10 +- handheld/console-border/gba.slangp | 12 +- .../console-border/gbc-lcd-grid-v2.slangp | 10 +- handheld/console-border/gbc.slangp | 12 +- handheld/console-border/gg.slangp | 15 +- handheld/console-border/ngpc.slangp | 12 +- handheld/console-border/psp.slangp | 12 +- .../shader-files/lcd-cgwg/lcd-grid-v2.slang | 140 ++++++++++++++++++ .../shader-files/lcd-cgwg/lcd-grid.slang | 97 ++++++++++++ 9 files changed, 275 insertions(+), 45 deletions(-) create mode 100644 handheld/console-border/shader-files/lcd-cgwg/lcd-grid-v2.slang create mode 100644 handheld/console-border/shader-files/lcd-cgwg/lcd-grid.slang diff --git a/handheld/console-border/gba-lcd-grid-v2.slangp b/handheld/console-border/gba-lcd-grid-v2.slangp index 16e9bae..95805c9 100644 --- a/handheld/console-border/gba-lcd-grid-v2.slangp +++ b/handheld/console-border/gba-lcd-grid-v2.slangp @@ -1,11 +1,10 @@ shaders = 4 shader0 = ../../motionblur/shaders/response-time.slang -shader1 = ../shaders/lcd-cgwg/lcd-grid-v2.slang +shader1 = shader-files/lcd-cgwg/lcd-grid-v2.slang shader2 = ../shaders/color/gba-color.slang -shader3 = shader-files/border-auto-scale.slang +shader3 = shader-files/gb-pass-5.slang -scale_type1 = source -scale1 = 4 +scale_type1 = viewport filter_linear0 = false filter_linear1 = false @@ -17,7 +16,8 @@ textures = BORDER BORDER = resources/gba-border-square-4x.png BORDER_linear = true -parameters = "RSUBPIX_R;RSUBPIX_G;RSUBPIX_B;GSUBPIX_R;GSUBPIX_G;GSUBPIX_B;BSUBPIX_R;BSUBPIX_G;BSUBPIX_B;gain;gamma;blacklevel;ambient;BGR" +parameters = "video_scale;RSUBPIX_R;RSUBPIX_G;RSUBPIX_B;GSUBPIX_R;GSUBPIX_G;GSUBPIX_B;BSUBPIX_R;BSUBPIX_G;BSUBPIX_B;gain;gamma;blacklevel;ambient;BGR" +video_scale = 4.0 RSUBPIX_R = "0.750000" RSUBPIX_G = "0.000000" RSUBPIX_B = "0.000000" diff --git a/handheld/console-border/gba.slangp b/handheld/console-border/gba.slangp index db16ce4..fd918bd 100644 --- a/handheld/console-border/gba.slangp +++ b/handheld/console-border/gba.slangp @@ -6,17 +6,15 @@ filter_linear0 = false shader1 = "../shaders/color/gba-color.slang" filter_linear1 = false -shader2 = "../shaders/lcd-cgwg/lcd-grid.slang" +shader2 = "shader-files/lcd-cgwg/lcd-grid.slang" filter_linear2 = "false" -wrap_mode2 = "clamp_to_border" -scale_type2 = "source" -scale2 = "4.0" +scale_type2 = "viewport" -shader3 = "shader-files/border-auto-scale.slang" +shader3 = "shader-files/gb-pass-5.slang" filter_linear3 = "true" -wrap_mode3 = "clamp_to_border" -parameters = "GRID_STRENGTH;mixfactor" +parameters = "video_scale;GRID_STRENGTH;mixfactor" +video_scale = 4.0 GRID_STRENGTH = "0.150000" mixfactor = "0.50" diff --git a/handheld/console-border/gbc-lcd-grid-v2.slangp b/handheld/console-border/gbc-lcd-grid-v2.slangp index 096b647..bc44463 100644 --- a/handheld/console-border/gbc-lcd-grid-v2.slangp +++ b/handheld/console-border/gbc-lcd-grid-v2.slangp @@ -1,11 +1,10 @@ shaders = 4 shader0 = ../../motionblur/shaders/response-time.slang -shader1 = ../shaders/lcd-cgwg/lcd-grid-v2.slang +shader1 = shader-files/lcd-cgwg/lcd-grid-v2.slang shader2 = ../shaders/color/gbc-color.slang -shader3 = shader-files/border-auto-scale.slang +shader3 = shader-files/gb-pass-5.slang -scale_type1 = source -scale1 = 4 +scale_type1 = viewport filter_linear0 = false filter_linear1 = false @@ -17,7 +16,8 @@ textures = BORDER BORDER = resources/color-border-square-4x.png BORDER_linear = true -parameters = "RSUBPIX_R;RSUBPIX_G;RSUBPIX_B;GSUBPIX_R;GSUBPIX_G;GSUBPIX_B;BSUBPIX_R;BSUBPIX_G;BSUBPIX_B;gain;gamma;blacklevel;ambient;BGR" +parameters = "video_scale;RSUBPIX_R;RSUBPIX_G;RSUBPIX_B;GSUBPIX_R;GSUBPIX_G;GSUBPIX_B;BSUBPIX_R;BSUBPIX_G;BSUBPIX_B;gain;gamma;blacklevel;ambient;BGR" +video_scale = 4.0 RSUBPIX_R = "0.750000" RSUBPIX_G = "0.000000" RSUBPIX_B = "0.000000" diff --git a/handheld/console-border/gbc.slangp b/handheld/console-border/gbc.slangp index 2ac488b..5a509ab 100644 --- a/handheld/console-border/gbc.slangp +++ b/handheld/console-border/gbc.slangp @@ -1,14 +1,14 @@ shaders = "2" -shader0 = "../shaders/lcd-cgwg/lcd-grid.slang" +shader0 = "shader-files/lcd-cgwg/lcd-grid.slang" filter_linear0 = "false" -wrap_mode0 = "clamp_to_border" -scale_type0 = "source" -scale0 = "4.0" +scale_type0 = "viewport" -shader1 = "shader-files/border-auto-scale.slang" +shader1 = "shader-files/gb-pass-5.slang" filter_linear1 = "true" -wrap_mode1 = "clamp_to_border" + +parameters = "video_scale" +video_scale = 4.0 textures = "BORDER" BORDER = "resources/color-border-square-4x.png" diff --git a/handheld/console-border/gg.slangp b/handheld/console-border/gg.slangp index 3709f14..3da1921 100644 --- a/handheld/console-border/gg.slangp +++ b/handheld/console-border/gg.slangp @@ -1,18 +1,15 @@ shaders = "2" -shader0 = "../shaders/lcd-cgwg/lcd-grid.slang" +shader0 = "shader-files/lcd-cgwg/lcd-grid.slang" filter_linear0 = "false" -wrap_mode0 = "clamp_to_border" -scale_type_x0 = "source" -scale_x0 = "4.800000" -scale_type_y0 = "source" -scale_y0 = "4.000000" +scale_type0 = viewport -shader1 = "shader-files/border-auto-scale.slang" +shader1 = "shader-files/gb-pass-5.slang" filter_linear1 = "true" -wrap_mode1 = "clamp_to_border" -parameters = "GRID_STRENGTH" +parameters = "video_scale;PAR;GRID_STRENGTH" +video_scale = 4.0 +PAR = 1.2 GRID_STRENGTH = "0.050000" textures = "BORDER" diff --git a/handheld/console-border/ngpc.slangp b/handheld/console-border/ngpc.slangp index 6261871..a83e7f8 100644 --- a/handheld/console-border/ngpc.slangp +++ b/handheld/console-border/ngpc.slangp @@ -1,14 +1,14 @@ shaders = "2" -shader0 = "../shaders/lcd-cgwg/lcd-grid.slang" +shader0 = "shader-files/lcd-cgwg/lcd-grid.slang" filter_linear0 = "false" -wrap_mode0 = "clamp_to_border" -scale_type0 = "source" -scale0 = "4.0" +scale_type0 = "viewport" -shader1 = "shader-files/border-auto-scale.slang" +shader1 = "shader-files/gb-pass-5.slang" filter_linear1 = "true" -wrap_mode1 = "clamp_to_border" + +parameters = "video_scale" +video_scale = 4.0 textures = "BORDER" BORDER = "resources/ngpc-border-square-4x.png" diff --git a/handheld/console-border/psp.slangp b/handheld/console-border/psp.slangp index ee69754..23153e3 100644 --- a/handheld/console-border/psp.slangp +++ b/handheld/console-border/psp.slangp @@ -1,16 +1,14 @@ shaders = "2" -shader0 = "../shaders/lcd-cgwg/lcd-grid.slang" +shader0 = "shader-files/lcd-cgwg/lcd-grid.slang" filter_linear0 = "false" -wrap_mode0 = "clamp_to_border" -scale_type0 = "source" -scale0 = "4.0" +scale_type0 = "viewport" -shader1 = "shader-files/border-auto-scale.slang" +shader1 = "shader-files/gb-pass-5.slang" filter_linear1 = "true" -wrap_mode1 = "clamp_to_border" -parameters = "border_texture_scale;GRID_STRENGTH" +parameters = "video_scale;border_texture_scale;GRID_STRENGTH" +video_scale = 4.0 border_texture_scale = 2.4 GRID_STRENGTH = 0.15 diff --git a/handheld/console-border/shader-files/lcd-cgwg/lcd-grid-v2.slang b/handheld/console-border/shader-files/lcd-cgwg/lcd-grid-v2.slang new file mode 100644 index 0000000..e7b3315 --- /dev/null +++ b/handheld/console-border/shader-files/lcd-cgwg/lcd-grid-v2.slang @@ -0,0 +1,140 @@ +#version 450 + +layout(push_constant) uniform Push +{ + float RSUBPIX_R; + float RSUBPIX_G; + float RSUBPIX_B; + float GSUBPIX_R; + float GSUBPIX_G; + float GSUBPIX_B; + float BSUBPIX_R; + float BSUBPIX_G; + float BSUBPIX_B; + float gain; + float gamma; + float blacklevel; + float ambient; + float BGR; + float video_scale, PAR; +} params; + +#pragma parameter video_scale "Video Scale" 3.0 2.0 20.0 1.0 +#pragma parameter PAR "Pixel Aspect Ratio" 1.0 0.0 20.0 0.01 +#pragma parameter RSUBPIX_R "Colour of R subpixel: R" 1.0 0.0 1.0 0.01 +#pragma parameter RSUBPIX_G "Colour of R subpixel: G" 0.0 0.0 1.0 0.01 +#pragma parameter RSUBPIX_B "Colour of R subpixel: B" 0.0 0.0 1.0 0.01 +#pragma parameter GSUBPIX_R "Colour of G subpixel: R" 0.0 0.0 1.0 0.01 +#pragma parameter GSUBPIX_G "Colour of G subpixel: G" 1.0 0.0 1.0 0.01 +#pragma parameter GSUBPIX_B "Colour of G subpixel: B" 0.0 0.0 1.0 0.01 +#pragma parameter BSUBPIX_R "Colour of B subpixel: R" 0.0 0.0 1.0 0.01 +#pragma parameter BSUBPIX_G "Colour of B subpixel: G" 0.0 0.0 1.0 0.01 +#pragma parameter BSUBPIX_B "Colour of B subpixel: B" 1.0 0.0 1.0 0.01 +#pragma parameter gain "Gain" 1.0 0.5 2.0 0.05 +#pragma parameter gamma "LCD Gamma" 3.0 0.5 5.0 0.1 +#pragma parameter blacklevel "Black level" 0.05 0.0 0.5 0.01 +#pragma parameter ambient "Ambient" 0.0 0.0 0.5 0.01 +#pragma parameter BGR "BGR" 0 0 1 1 + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; + vec4 OutputSize; + vec4 OriginalSize; + vec4 SourceSize; +} global; + +#define outgamma 2.2 + +#define fetch_offset(coord, offset) (pow(vec3(params.gain) * texelFetchOffset(Source, (coord), 0, (offset)).rgb + vec3(params.blacklevel), vec3(params.gamma)) + vec3(params.ambient)) + +vec2 middle = vec2(0.5, 0.5); +vec2 screen_scale = params.video_scale * vec2(params.PAR, 1.0); +vec2 screen_ratio = global.OutputSize.xy * global.SourceSize.zw / screen_scale; + +#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; + vec2 diff = TexCoord.xy - middle; + vTexCoord = middle + diff * screen_ratio; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +// integral of (1 - x^2 - x^4 + x^6)^2 +float coeffs_x[7] = float[](1.0, -2.0/3.0, -1.0/5.0, 4.0/7.0, -1.0/9.0, -2.0/11.0, 1.0/13.0); +// integral of (1 - 2x^4 + x^6)^2 +float coeffs_y[7] = float[](1.0, 0.0, -4.0/5.0, 2.0/7.0, 4.0/9.0, -4.0/11.0, 1.0/13.0); + +float intsmear_func(float z, float coeffs[7]) +{ + float z2 = z*z; + float zn = z; + float ret = 0.0; + for (int i = 0; i < 7; i++) { + ret += zn*coeffs[i]; + zn *= z2; + } + return ret; +} + +float intsmear(float x, float dx, float d, float coeffs[7]) +{ + float zl = clamp((x-dx*0.5)/d,-1.0,1.0); + float zh = clamp((x+dx*0.5)/d,-1.0,1.0); + return d * ( intsmear_func(zh,coeffs) - intsmear_func(zl,coeffs) )/dx; +} + +void main() +{ + vec2 texelSize = global.SourceSize.zw; + /* float2 range = IN.video_size / (IN.output_size * IN.texture_size); */ + vec2 range = global.SourceSize.zw / screen_scale; + + vec3 cred = pow(vec3(params.RSUBPIX_R, params.RSUBPIX_G, params.RSUBPIX_B), vec3(outgamma)); + vec3 cgreen = pow(vec3(params.GSUBPIX_R, params.GSUBPIX_G, params.GSUBPIX_B), vec3(outgamma)); + vec3 cblue = pow(vec3(params.BSUBPIX_R, params.BSUBPIX_G, params.BSUBPIX_B), vec3(outgamma)); + + ivec2 tli = ivec2(floor(vTexCoord/texelSize-vec2(0.4999))); + + vec3 lcol, rcol; + float subpix = (vTexCoord.x/texelSize.x - 0.4999 - float(tli.x))*3.0; + float rsubpix = range.x/texelSize.x * 3.0; + + lcol = vec3(intsmear(subpix+1.0, rsubpix, 1.5, coeffs_x), + intsmear(subpix , rsubpix, 1.5, coeffs_x), + intsmear(subpix-1.0, rsubpix, 1.5, coeffs_x)); + rcol = vec3(intsmear(subpix-2.0, rsubpix, 1.5, coeffs_x), + intsmear(subpix-3.0, rsubpix, 1.5, coeffs_x), + intsmear(subpix-4.0, rsubpix, 1.5, coeffs_x)); + + if (params.BGR > 0.5) { + lcol.rgb = lcol.bgr; + rcol.rgb = rcol.bgr; + } + + float tcol, bcol; + subpix = vTexCoord.y/texelSize.y - 0.4999 - float(tli.y); + rsubpix = range.y/texelSize.y; + tcol = intsmear(subpix ,rsubpix, 0.63, coeffs_y); + bcol = intsmear(subpix-1.0,rsubpix, 0.63, coeffs_y); + + vec3 topLeftColor = fetch_offset(tli, ivec2(0,0)) * lcol * vec3(tcol); + vec3 bottomRightColor = fetch_offset(tli, ivec2(1,1)) * rcol * vec3(bcol); + vec3 bottomLeftColor = fetch_offset(tli, ivec2(0,1)) * lcol * vec3(bcol); + vec3 topRightColor = fetch_offset(tli, ivec2(1,0)) * rcol * vec3(tcol); + + vec3 averageColor = topLeftColor + bottomRightColor + bottomLeftColor + topRightColor; + + averageColor = mat3(cred, cgreen, cblue) * averageColor; + + FragColor = vec4(pow(averageColor, vec3(1.0/outgamma)),0.0); +} diff --git a/handheld/console-border/shader-files/lcd-cgwg/lcd-grid.slang b/handheld/console-border/shader-files/lcd-cgwg/lcd-grid.slang new file mode 100644 index 0000000..b7f9dd8 --- /dev/null +++ b/handheld/console-border/shader-files/lcd-cgwg/lcd-grid.slang @@ -0,0 +1,97 @@ +#version 450 + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; + vec4 OutputSize; + vec4 OriginalSize; + vec4 SourceSize; + float video_scale, PAR, GRID_STRENGTH, gamma; +} global; + +#pragma parameter video_scale "Video Scale" 3.0 2.0 20.0 1.0 +#pragma parameter PAR "Pixel Aspect Ratio" 1.0 0.0 20.0 0.01 +#pragma parameter GRID_STRENGTH "LCD Grid Strength" 0.05 0.0 1.0 0.01 +#pragma parameter gamma "LCD Input Gamma" 2.2 1.0 5.0 0.1 + +#define round(x) floor( (x) + 0.5 ) +#define TEX2D(c) pow(texture(Source, (c)), vec4(global.gamma)) + +vec2 middle = vec2(0.5, 0.5); +vec2 screen_scale = global.video_scale * vec2(global.PAR, 1.0); +vec2 screen_ratio = global.OutputSize.xy * global.SourceSize.zw / screen_scale; + +#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; + vec2 diff = TexCoord.xy - middle; + vTexCoord = (middle + diff * screen_ratio) * 1.0001; +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +float intsmear_func(float z) +{ + float z2 = z*z; + float z4 = z2*z2; + float z8 = z4*z4; + return z - 2.0/3.0*z*z2 - 1.0/5.0*z*z4 + 4.0/7.0*z*z2*z4 - 1.0/9.0*z*z8 + - 2.0/11.0*z*z2*z8 + 1.0/13.0*z*z4*z8; +} + +float intsmear(float x, float dx) +{ + const float d = 1.5; + float zl = clamp((x-dx)/d,-1.0,1.0); + float zh = clamp((x+dx)/d,-1.0,1.0); + return d * ( intsmear_func(zh) - intsmear_func(zl) )/(2.0*dx); +} + +void main() +{ + vec2 texelSize = global.SourceSize.zw; + vec2 subtexelSize = texelSize / vec2(3.0,1.0); + vec2 range; + range = global.SourceSize.zw / screen_scale; + + float left = vTexCoord.x - texelSize.x*0.5; + float top = vTexCoord.y + range.y; + float right = vTexCoord.x + texelSize.x*0.5; + float bottom = vTexCoord.y - range.y; + + vec4 lcol, rcol; + float subpix = mod(vTexCoord.x/subtexelSize.x+1.5,3.0); + float rsubpix = range.x/subtexelSize.x; + lcol = vec4(intsmear(subpix+1.0,rsubpix),intsmear(subpix ,rsubpix), + intsmear(subpix-1.0,rsubpix),0.0); + rcol = vec4(intsmear(subpix-2.0,rsubpix),intsmear(subpix-3.0,rsubpix), + intsmear(subpix-4.0,rsubpix),0.0); + + vec4 topLeftColor = TEX2D((floor(vec2(left, top) / texelSize) + 0.5) * texelSize) * lcol; + vec4 bottomRightColor = TEX2D((floor(vec2(right, bottom) / texelSize) + 0.5) * texelSize) * rcol; + vec4 bottomLeftColor = TEX2D((floor(vec2(left, bottom) / texelSize) + 0.5) * texelSize) * lcol; + vec4 topRightColor = TEX2D((floor(vec2(right, top) / texelSize) + 0.5) * texelSize) * rcol; + + vec2 border = round(vTexCoord.st/subtexelSize); + vec2 bordert = clamp((border+vec2(0.0,+global.GRID_STRENGTH)) * subtexelSize, + vec2(left, bottom), vec2(right, top)); + vec2 borderb = clamp((border+vec2(0.0,-global.GRID_STRENGTH)) * subtexelSize, + vec2(left, bottom), vec2(right, top)); + float totalArea = 2.0 * range.y; + + vec4 averageColor; + averageColor = ((top - bordert.y) / totalArea) * topLeftColor; + averageColor += ((borderb.y - bottom) / totalArea) * bottomRightColor; + averageColor += ((borderb.y - bottom) / totalArea) * bottomLeftColor; + averageColor += ((top - bordert.y) / totalArea) * topRightColor; + + FragColor = pow(averageColor,vec4(1.0/global.gamma)); +}