From 2237891c656d2634732e1069fedbf7bf901408a5 Mon Sep 17 00:00:00 2001 From: MajorPainTheCactus Date: Mon, 14 Mar 2022 23:22:02 +0000 Subject: [PATCH] Optimised sony megatron shader by adding a three stage process and colour grading at lower source resolution Fixed include path slashes --- hdr/crt-sony-megatron-arcade.slangp | 26 ++- hdr/crt-sony-megatron-bang-olufsen.slangp | 26 ++- hdr/crt-sony-megatron-jvc-professional.slangp | 26 ++- hdr/crt-sony-megatron-sony-pvm.slangp | 26 ++- ...t-sony-megatron-toshiba-microfilter.slangp | 26 ++- ...-sony-megatron-viewsonic-superclear.slangp | 26 ++- hdr/shaders/crt-sony-megatron-hdr-pass.slang | 90 ++++++++ .../crt-sony-megatron-source-pass.slang | 86 ++++++++ hdr/shaders/crt-sony-megatron.slang | 205 ++++++++---------- hdr/shaders/include/colour_grade.h | 56 ++++- hdr/shaders/include/inverse_tonemap.h | 27 +-- hdr/shaders/include/parameters.h | 59 +++++ hdr/shaders/include/scanline_generation.h | 181 ++++++++-------- 13 files changed, 603 insertions(+), 257 deletions(-) create mode 100644 hdr/shaders/crt-sony-megatron-hdr-pass.slang create mode 100644 hdr/shaders/crt-sony-megatron-source-pass.slang create mode 100644 hdr/shaders/include/parameters.h diff --git a/hdr/crt-sony-megatron-arcade.slangp b/hdr/crt-sony-megatron-arcade.slangp index 6726447..1578474 100644 --- a/hdr/crt-sony-megatron-arcade.slangp +++ b/hdr/crt-sony-megatron-arcade.slangp @@ -28,16 +28,32 @@ Works only with the D3D11/D3D12/Vulkan drivers currently THIS SHADER DOES NOT SUPPORT WRGB OLED (Due to the sub pixel layout of WRGB - QD-OLED or LCD (and variants thereof screens are fine) - It will work just wont look right */ -shaders = "1" +shaders = "3" feedback_pass = "0" -shader0 = "shaders/crt-sony-megatron.slang" +shader0 = "shaders/crt-sony-megatron-source-pass.slang" filter_linear0 = "false" +scale_type0 = "source" +scale0 = "1.0" wrap_mode0 = "clamp_to_border" mipmap_input0 = "false" -alias0 = "" -float_framebuffer0 = "false" -srgb_framebuffer0 = "false" +alias0 = "SourceSDR" + +shader1 = "shaders/crt-sony-megatron-hdr-pass.slang" +filter_linear1 = "false" +scale_type1 = "source" +scale1 = "1.0" +wrap_mode1 = "clamp_to_border" +mipmap_input1 = "false" +alias1 = "SourceHDR" + +shader2 = "shaders/crt-sony-megatron.slang" +filter_linear2 = "false" +wrap_mode2 = "clamp_to_border" +mipmap_input2 = "false" +alias2 = "" +float_framebuffer2 = "false" +srgb_framebuffer2 = "false" hcrt_crt_screen_type = "2.000000" hcrt_paper_white_nits = "600.000000" diff --git a/hdr/crt-sony-megatron-bang-olufsen.slangp b/hdr/crt-sony-megatron-bang-olufsen.slangp index 4dd9bad..d5fd522 100644 --- a/hdr/crt-sony-megatron-bang-olufsen.slangp +++ b/hdr/crt-sony-megatron-bang-olufsen.slangp @@ -28,16 +28,32 @@ Works only with the D3D11/D3D12/Vulkan drivers currently THIS SHADER DOES NOT SUPPORT WRGB OLED (Due to the sub pixel layout of WRGB - QD-OLED or LCD (and variants thereof screens are fine) - It will work just wont look right */ -shaders = "1" +shaders = "3" feedback_pass = "0" -shader0 = "shaders/crt-sony-megatron.slang" +shader0 = "shaders/crt-sony-megatron-source-pass.slang" filter_linear0 = "false" +scale_type0 = "source" +scale0 = "1.0" wrap_mode0 = "clamp_to_border" mipmap_input0 = "false" -alias0 = "" -float_framebuffer0 = "false" -srgb_framebuffer0 = "false" +alias0 = "SourceSDR" + +shader1 = "shaders/crt-sony-megatron-hdr-pass.slang" +filter_linear1 = "false" +scale_type1 = "source" +scale1 = "1.0" +wrap_mode1 = "clamp_to_border" +mipmap_input1 = "false" +alias1 = "SourceHDR" + +shader2 = "shaders/crt-sony-megatron.slang" +filter_linear2 = "false" +wrap_mode2 = "clamp_to_border" +mipmap_input2 = "false" +alias2 = "" +float_framebuffer2 = "false" +srgb_framebuffer2 = "false" hcrt_crt_screen_type = "2.000000" hcrt_red_scanline_min = "0.650000" diff --git a/hdr/crt-sony-megatron-jvc-professional.slangp b/hdr/crt-sony-megatron-jvc-professional.slangp index 236f3f4..b51beda 100644 --- a/hdr/crt-sony-megatron-jvc-professional.slangp +++ b/hdr/crt-sony-megatron-jvc-professional.slangp @@ -28,16 +28,32 @@ Works only with the D3D11/D3D12/Vulkan drivers currently THIS SHADER DOES NOT SUPPORT WRGB OLED (Due to the sub pixel layout of WRGB - QD-OLED or LCD (and variants thereof screens are fine) - It will work just wont look right */ -shaders = "1" +shaders = "3" feedback_pass = "0" -shader0 = "shaders/crt-sony-megatron.slang" +shader0 = "shaders/crt-sony-megatron-source-pass.slang" filter_linear0 = "false" +scale_type0 = "source" +scale0 = "1.0" wrap_mode0 = "clamp_to_border" mipmap_input0 = "false" -alias0 = "" -float_framebuffer0 = "false" -srgb_framebuffer0 = "false" +alias0 = "SourceSDR" + +shader1 = "shaders/crt-sony-megatron-hdr-pass.slang" +filter_linear1 = "false" +scale_type1 = "source" +scale1 = "1.0" +wrap_mode1 = "clamp_to_border" +mipmap_input1 = "false" +alias1 = "SourceHDR" + +shader2 = "shaders/crt-sony-megatron.slang" +filter_linear2 = "false" +wrap_mode2 = "clamp_to_border" +mipmap_input2 = "false" +alias2 = "" +float_framebuffer2 = "false" +srgb_framebuffer2 = "false" hcrt_crt_screen_type = "1.000000" hcrt_crt_resolution = "2.000000" diff --git a/hdr/crt-sony-megatron-sony-pvm.slangp b/hdr/crt-sony-megatron-sony-pvm.slangp index 70d19b8..6a5caec 100644 --- a/hdr/crt-sony-megatron-sony-pvm.slangp +++ b/hdr/crt-sony-megatron-sony-pvm.slangp @@ -28,16 +28,32 @@ Works only with the D3D11/D3D12/Vulkan drivers currently THIS SHADER DOES NOT SUPPORT WRGB OLED (Due to the sub pixel layout of WRGB - QD-OLED or LCD (and variants thereof screens are fine) - It will work just wont look right */ -shaders = "1" +shaders = "3" feedback_pass = "0" -shader0 = "shaders/crt-sony-megatron.slang" +shader0 = "shaders/crt-sony-megatron-source-pass.slang" filter_linear0 = "false" +scale_type0 = "source" +scale0 = "1.0" wrap_mode0 = "clamp_to_border" mipmap_input0 = "false" -alias0 = "" -float_framebuffer0 = "false" -srgb_framebuffer0 = "false" +alias0 = "SourceSDR" + +shader1 = "shaders/crt-sony-megatron-hdr-pass.slang" +filter_linear1 = "false" +scale_type1 = "source" +scale1 = "1.0" +wrap_mode1 = "clamp_to_border" +mipmap_input1 = "false" +alias1 = "SourceHDR" + +shader2 = "shaders/crt-sony-megatron.slang" +filter_linear2 = "false" +wrap_mode2 = "clamp_to_border" +mipmap_input2 = "false" +alias2 = "" +float_framebuffer2 = "false" +srgb_framebuffer2 = "false" hcrt_brightness = "0.150000" hcrt_colour_system = "0.000000" diff --git a/hdr/crt-sony-megatron-toshiba-microfilter.slangp b/hdr/crt-sony-megatron-toshiba-microfilter.slangp index 44ba70a..a25ebd1 100644 --- a/hdr/crt-sony-megatron-toshiba-microfilter.slangp +++ b/hdr/crt-sony-megatron-toshiba-microfilter.slangp @@ -28,15 +28,31 @@ Works only with the D3D11/D3D12/Vulkan drivers currently THIS SHADER DOES NOT SUPPORT WRGB OLED (Due to the sub pixel layout of WRGB - QD-OLED or LCD (and variants thereof screens are fine) - It will work just wont look right */ -shaders = "1" +shaders = "3" feedback_pass = "0" -shader0 = "shaders/crt-sony-megatron.slang" +shader0 = "shaders/crt-sony-megatron-source-pass.slang" filter_linear0 = "false" +scale_type0 = "source" +scale0 = "1.0" wrap_mode0 = "clamp_to_border" mipmap_input0 = "false" -alias0 = "" -float_framebuffer0 = "false" -srgb_framebuffer0 = "false" +alias0 = "SourceSDR" + +shader1 = "shaders/crt-sony-megatron-hdr-pass.slang" +filter_linear1 = "false" +scale_type1 = "source" +scale1 = "1.0" +wrap_mode1 = "clamp_to_border" +mipmap_input1 = "false" +alias1 = "SourceHDR" + +shader2 = "shaders/crt-sony-megatron.slang" +filter_linear2 = "false" +wrap_mode2 = "clamp_to_border" +mipmap_input2 = "false" +alias2 = "" +float_framebuffer2 = "false" +srgb_framebuffer2 = "false" hcrt_crt_screen_type = "1.000000" diff --git a/hdr/crt-sony-megatron-viewsonic-superclear.slangp b/hdr/crt-sony-megatron-viewsonic-superclear.slangp index 821bf50..53bb08a 100644 --- a/hdr/crt-sony-megatron-viewsonic-superclear.slangp +++ b/hdr/crt-sony-megatron-viewsonic-superclear.slangp @@ -28,16 +28,32 @@ Works only with the D3D11/D3D12/Vulkan drivers currently THIS SHADER DOES NOT SUPPORT WRGB OLED (Due to the sub pixel layout of WRGB - QD-OLED or LCD (and variants thereof screens are fine) - It will work just wont look right */ -shaders = "1" +shaders = "3" feedback_pass = "0" -shader0 = "shaders/crt-sony-megatron.slang" +shader0 = "shaders/crt-sony-megatron-source-pass.slang" filter_linear0 = "false" +scale_type0 = "source" +scale0 = "1.0" wrap_mode0 = "clamp_to_border" mipmap_input0 = "false" -alias0 = "" -float_framebuffer0 = "false" -srgb_framebuffer0 = "false" +alias0 = "SourceSDR" + +shader1 = "shaders/crt-sony-megatron-hdr-pass.slang" +filter_linear1 = "false" +scale_type1 = "source" +scale1 = "1.0" +wrap_mode1 = "clamp_to_border" +mipmap_input1 = "false" +alias1 = "SourceHDR" + +shader2 = "shaders/crt-sony-megatron.slang" +filter_linear2 = "false" +wrap_mode2 = "clamp_to_border" +mipmap_input2 = "false" +alias2 = "" +float_framebuffer2 = "false" +srgb_framebuffer2 = "false" hcrt_crt_screen_type = "1.000000" hcrt_crt_resolution = "2.000000" diff --git a/hdr/shaders/crt-sony-megatron-hdr-pass.slang b/hdr/shaders/crt-sony-megatron-hdr-pass.slang new file mode 100644 index 0000000..69d5ef9 --- /dev/null +++ b/hdr/shaders/crt-sony-megatron-hdr-pass.slang @@ -0,0 +1,90 @@ +#version 450 + +/* +A shader that tries to emulate a sony PVM type aperture grille screen but with full brightness. + +The novel thing about this shader is that it relies on the HDR shaders to brighten up the image so that when +we apply this shader which emulates the apperture grille the resulting screen isn't left too dark. + +I think you need at least a DisplayHDR 600 monitor but to get close to CRT levels of brightness I think DisplayHDR 1000. + +Please Enable HDR in RetroArch 1.10+ + +NOTE: when this shader is envoked the Contrast, Peak Luminance and Paper White Luminance in the HDR menu do nothing instead set those values through the shader parameters + +For this shader set Paper White Luminance to above 700 and Peak Luminance to the peak luminance of your monitor. + +Also try to use a integer scaling - its just better - overscaling is fine. + +This shader doesn't do any geometry warping or bouncing of light around inside the screen etc - I think these effects just add unwanted noise, I know people disagree. Please feel free to make you own and add them + +Dont use this shader directly - use the hdr\crt-make-model-hdr.slangp where make and model are the make and model of the CRT you want. + +THIS SHADER DOES NOT SUPPORT WRGB OLED (Due to the sub pixel layout of WRGB - RGB QD-OLED or LCD (and variants thereof screens are fine) +*/ + +#pragma format A2B10G10R10_UNORM_PACK32 + +layout(push_constant) uniform Push +{ + // User Settings + float hcrt_hdr; + float hcrt_max_nits; + float hcrt_paper_white_nits; +} params; + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} global; + +#include "include/parameters.h" + +#define HCRT_HDR params.hcrt_hdr +#define HCRT_MAX_NITS params.hcrt_max_nits +#define HCRT_PAPER_WHITE_NITS params.hcrt_paper_white_nits + +#define COMPAT_TEXTURE(c, d) texture(c, d) + +#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 * vec2(1.00001); // To resolve rounding issues when sampling +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +#include "include/inverse_tonemap.h" + +vec3 InverseTonemapConditional(const vec3 linear) +{ + if(HCRT_HDR > 0.0f) + { + return linear; + } + else + { + return InverseTonemap(linear, HCRT_MAX_NITS, HCRT_PAPER_WHITE_NITS); + } +} + +void main() +{ + vec3 source = COMPAT_TEXTURE(Source, vTexCoord).rgb; + + const vec3 hdr_colour = InverseTonemapConditional(source); + + FragColor = vec4(hdr_colour, 1.0); +} diff --git a/hdr/shaders/crt-sony-megatron-source-pass.slang b/hdr/shaders/crt-sony-megatron-source-pass.slang new file mode 100644 index 0000000..403b507 --- /dev/null +++ b/hdr/shaders/crt-sony-megatron-source-pass.slang @@ -0,0 +1,86 @@ +#version 450 + +/* +A shader that tries to emulate a sony PVM type aperture grille screen but with full brightness. + +The novel thing about this shader is that it relies on the HDR shaders to brighten up the image so that when +we apply this shader which emulates the apperture grille the resulting screen isn't left too dark. + +I think you need at least a DisplayHDR 600 monitor but to get close to CRT levels of brightness I think DisplayHDR 1000. + +Please Enable HDR in RetroArch 1.10+ + +NOTE: when this shader is envoked the Contrast, Peak Luminance and Paper White Luminance in the HDR menu do nothing instead set those values through the shader parameters + +For this shader set Paper White Luminance to above 700 and Peak Luminance to the peak luminance of your monitor. + +Also try to use a integer scaling - its just better - overscaling is fine. + +This shader doesn't do any geometry warping or bouncing of light around inside the screen etc - I think these effects just add unwanted noise, I know people disagree. Please feel free to make you own and add them + +Dont use this shader directly - use the hdr\crt-make-model-hdr.slangp where make and model are the make and model of the CRT you want. + +THIS SHADER DOES NOT SUPPORT WRGB OLED (Due to the sub pixel layout of WRGB - RGB QD-OLED or LCD (and variants thereof screens are fine) +*/ + +layout(push_constant) uniform Push +{ + float hcrt_max_nits; + float hcrt_paper_white_nits; + float hcrt_lcd_resolution; + float hcrt_lcd_subpixel; + float hcrt_colour_system; + float hcrt_expand_gamut; + float hcrt_white_temperature; + float hcrt_brightness; + float hcrt_contrast; + float hcrt_saturation; + float hcrt_gamma; +} params; + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; + vec4 SourceSize; + vec4 OriginalSize; + vec4 OutputSize; + uint FrameCount; +} global; + +#include "include/parameters.h" + +#define HCRT_CRT_COLOUR_SYSTEM params.hcrt_colour_system +#define HCRT_WHITE_TEMPERATURE params.hcrt_white_temperature +#define HCRT_BRIGHTNESS params.hcrt_brightness +#define HCRT_CONTRAST params.hcrt_contrast +#define HCRT_SATURATION params.hcrt_saturation +#define HCRT_GAMMA params.hcrt_gamma + +#define COMPAT_TEXTURE(c, d) texture(c, d) + +#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 * vec2(1.00001); // To resolve rounding issues when sampling +} + +#pragma stage fragment +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform sampler2D Source; + +#include "include/colour_grade.h" + +void main() +{ + vec3 source = COMPAT_TEXTURE(Source, vTexCoord).rgb; + + const vec3 colour = ColourGrade(source); + + FragColor = vec4(colour, 1.0); +} diff --git a/hdr/shaders/crt-sony-megatron.slang b/hdr/shaders/crt-sony-megatron.slang index 86d9bab..7c9b19e 100644 --- a/hdr/shaders/crt-sony-megatron.slang +++ b/hdr/shaders/crt-sony-megatron.slang @@ -29,13 +29,15 @@ layout(push_constant) uniform Push { // User Settings float hcrt_hdr; + float hcrt_colour_space; float hcrt_max_nits; float hcrt_paper_white_nits; + float hcrt_expand_gamut; + float hcrt_gamma; + float hcrt_lcd_resolution; float hcrt_lcd_subpixel; - float hcrt_colour_system; - float hcrt_colour_space; - float hcrt_expand_gamut; + float hcrt_red_vertical_convergence; float hcrt_green_vertical_convergence; float hcrt_blue_vertical_convergence; @@ -75,78 +77,19 @@ layout(std140, set = 0, binding = 0) uniform UBO vec4 OriginalSize; vec4 OutputSize; uint FrameCount; - - float hcrt_white_temperature; - float hcrt_brightness; - float hcrt_contrast; - float hcrt_saturation; - float hcrt_gamma; } global; - -#pragma parameter hcrt_title "SONY PVM/BVM HDR SHADER" 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_space0 " " 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_support0 "SUPPORTED: RGB/BGR LCD, QD-OLED Displays" 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_support1 "NOT SUPPORTED: WRGB OLED Displays" 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_support2 "MIN SPEC: DisplayHDR 600, 4K, RetroArch v1.10" 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_support3 "REC SPEC: DisplayHDR 1000, 4K+, RetroArch v1.10" 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_space1 " " 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_instructions0 "HDR: Enable HDR: On" 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_instructions1 "SCALING: Integer Scale: ON" 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_instructions2 "SCALING: Integer Overscale: ON" 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_instructions3 "SCALING: Apect Ratio: Core Provided" 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_space2 " " 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_user_settings "USER SETTINGS:" 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_hdr " HDR | SDR" 0.0 0.0 1.0 1.0 -#pragma parameter hcrt_max_nits " HDR: Display's Peak Luminance" 700.0 0.0 10000.0 10.0 -#pragma parameter hcrt_paper_white_nits " HDR: Display's Paper White Luminance" 700.0 0.0 10000.0 10.0 -#pragma parameter hcrt_colour_space " SDR: Display's Colour Space: sRGB | DCI-P3" 0.0 0.0 1.0 1.0 -#pragma parameter hcrt_lcd_resolution " Display's Resolution: 4K | 8K" 0.0 0.0 1.0 1.0 -#pragma parameter hcrt_lcd_subpixel " Display's Subpixel Layout: RGB | BGR" 0.0 0.0 1.0 1.0 -#pragma parameter hcrt_red_vertical_convergence " Red Vertical Convergence" 0.00 -10.0 10.0 0.01 -#pragma parameter hcrt_green_vertical_convergence " Green Vertical Convergence" 0.00 -10.0 10.0 0.01 -#pragma parameter hcrt_blue_vertical_convergence " Blue Vertical Convergence" 0.00 -10.0 10.0 0.01 -#pragma parameter hcrt_red_horizontal_convergence " Red Horizontal Convergence" 0.00 -10.0 10.0 0.01 -#pragma parameter hcrt_green_horizontal_convergence " Green Horizontal Convergence" 0.00 -10.0 10.0 0.01 -#pragma parameter hcrt_blue_horizontal_convergence " Blue Horizontal Convergence" 0.00 -10.0 10.0 0.01 - -#pragma parameter hcrt_space3 " " 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_developer_settings "DEVELOPER SETTINGS:" 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_crt_screen_type " CRT Type: APERTURE GRILLE | SHADOW MASK | SLOT MASK" 0.0 0.0 2.0 1.0 -#pragma parameter hcrt_crt_resolution " CRT Resolution: 600TVL | 800TVL | 1000TVL" 0.0 0.0 2.0 1.0 -#pragma parameter hcrt_colour_system " CRT Colour System: PAL | NTSC-U | NTSC-J" 1.0 0.0 2.0 1.0 -#pragma parameter hcrt_white_temperature " White Point: (PAL:D65, NTSC-U:D65, NTSC-J:D93)" 0.0 -5000.0 12000.0 100.0 -#pragma parameter hcrt_expand_gamut " HDR: Original/Vivid" 0.0 0.0 1.0 1.0 -#pragma parameter hcrt_brightness " Brightness" 0.0 -1.0 1.0 0.01 -#pragma parameter hcrt_contrast " Contrast" 0.0 -1.0 1.0 0.01 -#pragma parameter hcrt_saturation " Saturation" 0.0 -1.0 1.0 0.01 -#pragma parameter hcrt_gamma " Gamma" 0.0 -1.0 1.0 0.01 - -#pragma parameter hcrt_developer_settings0 " VERTICAL SETTINGS:" 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_red_scanline_min " Red Scanline Min" 0.50 0.0 2.0 0.01 -#pragma parameter hcrt_red_scanline_max " Red Scanline Max" 1.00 0.0 2.0 0.01 -#pragma parameter hcrt_red_scanline_attack " Red Scanline Attack" 0.20 0.0 1.0 0.01 -#pragma parameter hcrt_green_scanline_min " Green Scanline Min" 0.50 0.0 2.0 0.01 -#pragma parameter hcrt_green_scanline_max " Green Scanline Max" 1.00 0.0 2.0 0.01 -#pragma parameter hcrt_green_scanline_attack " Green Scanline Attack" 0.20 0.0 1.0 0.01 -#pragma parameter hcrt_blue_scanline_min " Blue Scanline Min" 0.50 0.0 2.0 0.01 -#pragma parameter hcrt_blue_scanline_max " Blue Scanline Max" 1.00 0.0 2.0 0.01 -#pragma parameter hcrt_blue_scanline_attack " Blue Scanline Attack" 0.20 0.0 1.0 0.01 -#pragma parameter hcrt_developer_settings1 " HORIZONTAL SETTINGS:" 0.0 0.0 0.0001 0.0 -#pragma parameter hcrt_red_beam_sharpness " Red Beam Sharpness" 1.75 0.0 5.0 0.05 -#pragma parameter hcrt_red_beam_attack " Red Beam Attack" 0.50 0.0 2.0 0.01 -#pragma parameter hcrt_green_beam_sharpness " Green Beam Sharpness" 1.75 0.0 5.0 0.05 -#pragma parameter hcrt_green_beam_attack " Green Beam Attack" 0.50 0.0 2.0 0.01 -#pragma parameter hcrt_blue_beam_sharpness " Blue Beam Sharpness" 1.75 0.0 5.0 0.05 -#pragma parameter hcrt_blue_beam_attack " Blue Beam Attack" 0.50 0.0 2.0 0.01 - +#include "include/parameters.h" #define HCRT_HDR params.hcrt_hdr +#define HCRT_OUTPUT_COLOUR_SPACE params.hcrt_colour_space #define HCRT_MAX_NITS params.hcrt_max_nits #define HCRT_PAPER_WHITE_NITS params.hcrt_paper_white_nits +#define HCRT_EXPAND_GAMUT params.hcrt_expand_gamut +#define HCRT_GAMMA params.hcrt_gamma + #define HCRT_LCD_RESOLUTION params.hcrt_lcd_resolution #define HCRT_LCD_SUBPIXEL params.hcrt_lcd_subpixel -#define HCRT_EXPAND_GAMUT params.hcrt_expand_gamut #define HCRT_RED_VERTICAL_CONVERGENCE params.hcrt_red_vertical_convergence #define HCRT_GREEN_VERTICAL_CONVERGENCE params.hcrt_green_vertical_convergence #define HCRT_BLUE_VERTICAL_CONVERGENCE params.hcrt_blue_vertical_convergence @@ -156,13 +99,6 @@ layout(std140, set = 0, binding = 0) uniform UBO #define HCRT_CRT_SCREEN_TYPE params.hcrt_crt_screen_type #define HCRT_CRT_RESOLUTION params.hcrt_crt_resolution -#define HCRT_CRT_COLOUR_SYSTEM params.hcrt_colour_system -#define HCRT_OUTPUT_COLOUR_SPACE params.hcrt_colour_space -#define HCRT_WHITE_TEMPERATURE global.hcrt_white_temperature -#define HCRT_BRIGHTNESS global.hcrt_brightness -#define HCRT_CONTRAST global.hcrt_contrast -#define HCRT_SATURATION global.hcrt_saturation -#define HCRT_GAMMA global.hcrt_gamma #define HCRT_RED_SCANLINE_MIN params.hcrt_red_scanline_min #define HCRT_RED_SCANLINE_MAX params.hcrt_red_scanline_max @@ -197,16 +133,31 @@ void main() #pragma stage fragment layout(location = 0) in vec2 vTexCoord; layout(location = 0) out vec4 FragColor; -layout(set = 0, binding = 2) uniform sampler2D Source; +layout(set = 0, binding = 2) uniform sampler2D SourceSDR; +layout(set = 0, binding = 3) uniform sampler2D SourceHDR; -#define kRed vec3(1.0, 0.0, 0.0) -#define kGreen vec3(0.0, 1.0, 0.0) -#define kBlue vec3(0.0, 0.0, 1.0) -#define kMagenta vec3(1.0, 0.0, 1.0) -#define kYellow vec3(1.0, 1.0, 0.0) -#define kCyan vec3(0.0, 1.0, 1.0) -#define kBlack vec3(0.0, 0.0, 0.0) -#define kWhite vec3(1.0, 1.0, 1.0) + +#define kChannelMask 3 +#define kFirstChannelShift 2 +#define kSecondChannelShift 4 + +#define kRedId 0 +#define kGreenId 1 +#define kBlueId 2 + +#define kRed (1 | (kRedId << kFirstChannelShift)) +#define kGreen (1 | (kGreenId << kFirstChannelShift)) +#define kBlue (1 | (kBlueId << kFirstChannelShift)) +#define kMagenta (2 | (kRedId << kFirstChannelShift) | (kBlueId << kSecondChannelShift)) +#define kYellow (2 | (kRedId << kFirstChannelShift) | (kGreenId << kSecondChannelShift)) +#define kCyan (2 | (kGreenId << kFirstChannelShift) | (kBlueId << kSecondChannelShift)) +#define kBlack 0 + +#define kRedChannel vec3(1.0, 0.0, 0.0) +#define kGreenChannel vec3(0.0, 1.0, 0.0) +#define kBlueChannel vec3(0.0, 0.0, 1.0) + +const vec3 kColourMask[3] = { kRedChannel, kGreenChannel, kBlueChannel }; #define kApertureGrille 0 #define kShadowMask 1 @@ -237,7 +188,7 @@ layout(set = 0, binding = 2) uniform sampler2D Source; const uint kApertureGrilleMaskSize[kResolutionAxis][kTVLAxis] = { { 4, 3, 2 }, { 7, 5, 4 } }; //4K: 600 TVL, 800 TVL, 1000 TVL 8K: 600 TVL, 800 TVL, 1000 TVL -const vec3 kApertureGrilleMasks[kResolutionAxis][kTVLAxis][kBGRAxis][kMaxApertureGrilleSize] = { +const uint kApertureGrilleMasks[kResolutionAxis][kTVLAxis][kBGRAxis][kMaxApertureGrilleSize] = { { // 4K { kRGBX, kBGRX }, // 600 TVL { kBGR, kRGB }, // 800 TVL @@ -296,7 +247,7 @@ const vec3 kApertureGrilleMasks[kResolutionAxis][kTVLAxis][kBGRAxis][kMaxApertur const uint kShadowMaskSizeX[kResolutionAxis][kTVLAxis] = { { 6, 2, 2 }, { 12, 6, 6 } }; const uint kShadowMaskSizeY[kResolutionAxis][kTVLAxis] = { { 4, 2, 2 }, { 8, 4, 4 } }; -const vec3 kShadowMasks[kResolutionAxis][kTVLAxis][kBGRAxis][kMaxShadowMaskSizeY][kMaxShadowMaskSizeX] = { +const uint kShadowMasks[kResolutionAxis][kTVLAxis][kBGRAxis][kMaxShadowMaskSizeY][kMaxShadowMaskSizeX] = { { // 4K { kGRRBBG_GRRBBG_BBGGRR_BBGGRR, kGBBRRG_GBBRRG_RRGGBB_RRGGBB }, // 600 TVL { kMG_GM, kGM_MG }, // 800 TVL @@ -362,7 +313,7 @@ const vec3 kShadowMasks[kResolutionAxis][kTVLAxis][kBGRAxis][kMaxShadowMaskSizeY const uint kSlotMaskSize[kResolutionAxis][kTVLAxis] = { { 4, 3, 2 }, { 7, 5, 4 } }; //4K: 600 TVL, 800 TVL, 1000 TVL 8K: 600 TVL, 800 TVL, 1000 TVL -const vec3 kSlotMasks[kResolutionAxis][kTVLAxis][kBGRAxis][kMaxSlotSizeY][kMaxSlotSizeX][kMaxSlotMaskSize] = { +const uint kSlotMasks[kResolutionAxis][kTVLAxis][kBGRAxis][kMaxSlotSizeY][kMaxSlotSizeX][kMaxSlotMaskSize] = { { // 4K { kRGBXRGBX_RGBXXXXX_RGBXRGBX_XXXXRGBX, kBGRXBGRX_BGRXXXXX_BGRXBGRX_XXXXBGRX }, // 600 TVL { kBGRBGR_BGRXXX_BGRBGR_XXXBGR, kRGBRGB_RGBXXX_RGBRGB_XXXRGB }, // 800 TVL @@ -393,16 +344,8 @@ float ModInteger(float a, float b) return floor(m + 0.5); } -const mat4 kCubicBezier = mat4( 1.0f, 0.0f, 0.0f, 0.0f, - -3.0f, 3.0f, 0.0f, 0.0f, - 3.0f, -6.0f, 3.0f, 0.0f, - -1.0f, 3.0f, -3.0f, 1.0f ); - -float Bezier(const float t0, const vec4 control_points) -{ - vec4 t = vec4(1.0, t0, t0*t0, t0*t0*t0); - return dot(t, control_points * kCubicBezier); -} +#include "include/scanline_generation.h" +#include "include/hdr10.h" // SDR Colour output spaces float sRGBToLinear_1(const float channel) @@ -430,11 +373,6 @@ vec3 LinearToDCIP3(const vec3 colour) return pow(colour, vec3(1.0f / 2.6f)); } -#include "include\hdr10.h" -#include "include\inverse_tonemap.h" -#include "include\colour_grade.h" -#include "include\scanline_generation.h" - vec3 GammaCorrect(const vec3 scanline_colour) { if(HCRT_HDR > 0.0f) @@ -446,12 +384,9 @@ vec3 GammaCorrect(const vec3 scanline_colour) return Hdr10(scanline_colour, HCRT_PAPER_WHITE_NITS, HCRT_EXPAND_GAMUT); } } - + void main() { - const float scanline_size = global.OutputSize.y / global.SourceSize.y; - vec3 scanline_colour = GenerateScanline(global.SourceSize.xy, scanline_size); - const uint screen_type = uint(HCRT_CRT_SCREEN_TYPE); const uint crt_resolution = uint(HCRT_CRT_RESOLUTION); const uint lcd_resolution = uint(HCRT_LCD_RESOLUTION); @@ -459,13 +394,15 @@ void main() const vec2 current_position = vTexCoord * global.OutputSize.xy; + uint colour_mask; + switch(screen_type) { case kApertureGrille: { uint mask = uint(ModInteger(floor(current_position.x), kApertureGrilleMaskSize[lcd_resolution][crt_resolution])); - scanline_colour *= kApertureGrilleMasks[lcd_resolution][crt_resolution][lcd_subpixel_layout][mask]; + colour_mask = kApertureGrilleMasks[lcd_resolution][crt_resolution][lcd_subpixel_layout][mask]; break; } @@ -475,7 +412,7 @@ void main() uint mask = uint(ModInteger(floor(current_position.x), kShadowMaskSizeX[lcd_resolution][crt_resolution])); - scanline_colour *= kShadowMasks[lcd_resolution][crt_resolution][lcd_subpixel_layout][shadow_y][mask]; + colour_mask = kShadowMasks[lcd_resolution][crt_resolution][lcd_subpixel_layout][shadow_y][mask]; break; } @@ -486,7 +423,7 @@ void main() uint mask = uint(ModInteger(floor(current_position.x), kSlotMaskSize[lcd_resolution][crt_resolution])); - scanline_colour *= kSlotMasks[lcd_resolution][crt_resolution][lcd_subpixel_layout][slot_x][slot_y][mask]; + colour_mask = kSlotMasks[lcd_resolution][crt_resolution][lcd_subpixel_layout][slot_x][slot_y][mask]; break; } @@ -496,7 +433,57 @@ void main() } } + const float scanline_size = global.OutputSize.y / global.SourceSize.y; + + const vec3 horizontal_convergence = vec3(HCRT_RED_HORIZONTAL_CONVERGENCE, HCRT_GREEN_HORIZONTAL_CONVERGENCE, HCRT_BLUE_HORIZONTAL_CONVERGENCE); + const vec3 vertical_convergence = vec3(HCRT_RED_VERTICAL_CONVERGENCE, HCRT_GREEN_VERTICAL_CONVERGENCE, HCRT_BLUE_VERTICAL_CONVERGENCE); + const vec3 beam_sharpness = vec3(HCRT_RED_BEAM_SHARPNESS, HCRT_GREEN_BEAM_SHARPNESS, HCRT_BLUE_BEAM_SHARPNESS); + const vec3 beam_attack = vec3(HCRT_RED_BEAM_ATTACK, HCRT_GREEN_BEAM_ATTACK, HCRT_BLUE_BEAM_ATTACK); + const vec3 scanline_min = vec3(HCRT_RED_SCANLINE_MIN, HCRT_GREEN_SCANLINE_MIN, HCRT_BLUE_SCANLINE_MIN); + const vec3 scanline_max = vec3(HCRT_RED_SCANLINE_MAX, HCRT_GREEN_SCANLINE_MAX, HCRT_BLUE_SCANLINE_MAX); + const vec3 scanline_attack = vec3(HCRT_RED_SCANLINE_ATTACK, HCRT_GREEN_SCANLINE_ATTACK, HCRT_BLUE_SCANLINE_ATTACK); + + const uint channel_count = colour_mask & 3; + + vec3 scanline_colour = vec3(0.0f); + + if(channel_count > 0) + { + const uint channel_0 = (colour_mask >> 2) & 3; + + const float scanline_channel_0 = GenerateScanline(channel_0, + global.SourceSize.xy, + scanline_size, + horizontal_convergence[channel_0], + vertical_convergence[channel_0], + beam_sharpness[channel_0], + beam_attack[channel_0], + scanline_min[channel_0], + scanline_max[channel_0], + scanline_attack[channel_0]); + + scanline_colour = scanline_channel_0 * kColourMask[channel_0]; + } + + if(channel_count > 1) + { + const uint channel_1 = (colour_mask >> 4) & 3; + + const float scanline_channel_1 = GenerateScanline(channel_1, + global.SourceSize.xy, + scanline_size, + horizontal_convergence[channel_1], + vertical_convergence[channel_1], + beam_sharpness[channel_1], + beam_attack[channel_1], + scanline_min[channel_1], + scanline_max[channel_1], + scanline_attack[channel_1]); + + scanline_colour += scanline_channel_1 * kColourMask[channel_1]; + } + const vec3 hdr10 = GammaCorrect(scanline_colour); - FragColor = vec4(hdr10, 1.0); + FragColor = vec4(hdr10, 1.0f); } diff --git a/hdr/shaders/include/colour_grade.h b/hdr/shaders/include/colour_grade.h index c0a8b4f..acdc9fa 100644 --- a/hdr/shaders/include/colour_grade.h +++ b/hdr/shaders/include/colour_grade.h @@ -62,6 +62,17 @@ const mat3 kCoolTemperature = mat3( vec3(-2666.3474220535695, -2173.1012343082230, 2575.2827530017594), vec3( 0.55995389139931482, 0.70381203140554553, 1.8993753891711275)); +const mat4 kCubicBezier = mat4( 1.0f, 0.0f, 0.0f, 0.0f, + -3.0f, 3.0f, 0.0f, 0.0f, + 3.0f, -6.0f, 3.0f, 0.0f, + -1.0f, 3.0f, -3.0f, 1.0f ); + +float Bezier(const float t0, const vec4 control_points) +{ + vec4 t = vec4(1.0, t0, t0*t0, t0*t0*t0); + return dot(t, control_points * kCubicBezier); +} + vec3 WhiteBalance(float temperature, vec3 colour) { const mat3 m = (temperature < kD65) ? kWarmTemperature : kCoolTemperature; @@ -95,6 +106,32 @@ vec3 LinearTor601r709(const vec3 colour) return vec3(LinearTor601r709_1(colour.r), LinearTor601r709_1(colour.g), LinearTor601r709_1(colour.b)); } +// SDR Colour output spaces +float sRGBToLinear_1(const float channel) +{ + return (channel > 0.04045f) ? pow((channel + 0.055f) * (1.0f / 1.055f), 2.4f + HCRT_GAMMA) : channel * (1.0f / 12.92f); +} + +vec3 sRGBToLinear(const vec3 colour) +{ + return vec3(sRGBToLinear_1(colour.r), sRGBToLinear_1(colour.g), sRGBToLinear_1(colour.b)); +} + +float LinearTosRGB_1(const float channel) +{ + return (channel > 0.0031308f) ? (1.055f * pow(channel, 1.0f / 2.4f)) - 0.055f : channel * 12.92f; +} + +vec3 LinearTosRGB(const vec3 colour) +{ + return vec3(LinearTosRGB_1(colour.r), LinearTosRGB_1(colour.g), LinearTosRGB_1(colour.b)); +} + +vec3 LinearToDCIP3(const vec3 colour) +{ + return pow(colour, vec3(1.0f / 2.6f)); +} + // XYZ Yxy transforms found in Dogway's Grade.slang shader vec3 XYZtoYxy(const vec3 XYZ) @@ -153,12 +190,8 @@ vec3 Saturation(const vec3 colour) return clamp(mix(vec3(luma), colour, vec3(saturation) * 2.0f), 0.0f, 1.0f); } -vec3 ColourGrade(const vec3 colour) +vec3 BrightnessContrastSaturation(const vec3 linear) { - const uint colour_system = uint(HCRT_CRT_COLOUR_SYSTEM); - - const vec3 linear = r601r709ToLinear(colour); - const vec3 xyz = sRGB_to_XYZ * linear; const vec3 Yxy = XYZtoYxy(xyz); const float Y_gamma = clamp(LinearTosRGB_1(Yxy.x), 0.0f, 1.0f); @@ -173,7 +206,18 @@ vec3 ColourGrade(const vec3 colour) const vec3 saturation = Saturation(contrast); - const vec3 gamut = kPhosphorGamut[colour_system] * saturation; + return saturation; +} + +vec3 ColourGrade(const vec3 colour) +{ + const uint colour_system = uint(HCRT_CRT_COLOUR_SYSTEM); + + const vec3 linear = r601r709ToLinear(colour); + + const vec3 graded = BrightnessContrastSaturation(linear); + + const vec3 gamut = kPhosphorGamut[colour_system] * graded; const vec3 white_point = WhiteBalance(kTemperatures[colour_system] + HCRT_WHITE_TEMPERATURE, gamut); diff --git a/hdr/shaders/include/inverse_tonemap.h b/hdr/shaders/include/inverse_tonemap.h index 3f7fe6b..1e64c70 100644 --- a/hdr/shaders/include/inverse_tonemap.h +++ b/hdr/shaders/include/inverse_tonemap.h @@ -2,29 +2,20 @@ #define kMaxNitsFor2084 10000.0f #define kEpsilon 0.0001f -vec3 InverseTonemap(vec3 sdr_linear, float max_nits, float paper_white_nits, float luma_ratio) +vec3 InverseTonemap(const vec3 sdr_linear, const float max_nits, const float paper_white_nits) { - float luma = dot(sdr_linear, vec3(0.2126, 0.7152, 0.0722)); /* Rec BT.709 luma coefficients - https://en.wikipedia.org/wiki/Luma_(video) */ + const float luma = dot(sdr_linear, vec3(0.2126, 0.7152, 0.0722)); /* Rec BT.709 luma coefficients - https://en.wikipedia.org/wiki/Luma_(video) */ /* Inverse reinhard tonemap */ - float max_value = (max_nits / paper_white_nits) + kEpsilon; - float elbow = max_value / (max_value - 1.0f); - float offset = 1.0f - ((0.5f * elbow) / (elbow - 0.5f)); + const float max_value = (max_nits / paper_white_nits) + kEpsilon; + const float elbow = max_value / (max_value - 1.0f); + const float offset = 1.0f - ((0.5f * elbow) / (elbow - 0.5f)); - float hdr_luma_inv_tonemap = offset + ((luma * elbow) / (elbow - luma)); - float sdr_luma_inv_tonemap = luma / ((1.0f + kEpsilon) - luma); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */ + const float hdr_luma_inv_tonemap = offset + ((luma * elbow) / (elbow - luma)); + const float sdr_luma_inv_tonemap = luma / ((1.0f + kEpsilon) - luma); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */ - float luma_inv_tonemap = (luma > 0.5f) ? hdr_luma_inv_tonemap : sdr_luma_inv_tonemap; - vec3 per_luma = sdr_linear / (luma + kEpsilon) * luma_inv_tonemap; - - vec3 hdr_inv_tonemap = offset + ((sdr_linear * elbow) / (elbow - sdr_linear)); - vec3 sdr_inv_tonemap = sdr_linear / ((1.0f + kEpsilon) - sdr_linear); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */ - - vec3 per_channel = vec3(sdr_linear.x > 0.5f ? hdr_inv_tonemap.x : sdr_inv_tonemap.x, - sdr_linear.y > 0.5f ? hdr_inv_tonemap.y : sdr_inv_tonemap.y, - sdr_linear.z > 0.5f ? hdr_inv_tonemap.z : sdr_inv_tonemap.z); - - vec3 hdr = mix(per_luma, per_channel, vec3(luma_ratio)); + const float luma_inv_tonemap = (luma > 0.5f) ? hdr_luma_inv_tonemap : sdr_luma_inv_tonemap; + const vec3 hdr = sdr_linear / (luma + kEpsilon) * luma_inv_tonemap; return hdr; } diff --git a/hdr/shaders/include/parameters.h b/hdr/shaders/include/parameters.h new file mode 100644 index 0000000..3059e2c --- /dev/null +++ b/hdr/shaders/include/parameters.h @@ -0,0 +1,59 @@ + + +#pragma parameter hcrt_title "SONY PVM/BVM HDR SHADER" 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_space0 " " 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_support0 "SUPPORTED: RGB/BGR LCD, QD-OLED Displays" 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_support1 "NOT SUPPORTED: WRGB OLED Displays" 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_support2 "MIN SPEC: DisplayHDR 600, 4K, RetroArch v1.10" 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_support3 "REC SPEC: DisplayHDR 1000, 4K+, RetroArch v1.10" 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_space1 " " 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_instructions0 "HDR: Enable HDR: On" 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_instructions1 "SCALING: Integer Scale: ON" 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_instructions2 "SCALING: Integer Overscale: ON" 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_instructions3 "SCALING: Apect Ratio: Core Provided" 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_space2 " " 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_user_settings "USER SETTINGS:" 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_hdr " HDR | SDR" 0.0 0.0 1.0 1.0 +#pragma parameter hcrt_max_nits " HDR: Display's Peak Luminance" 700.0 0.0 10000.0 10.0 +#pragma parameter hcrt_paper_white_nits " HDR: Display's Paper White Luminance" 700.0 0.0 10000.0 10.0 +#pragma parameter hcrt_colour_space " SDR: Display's Colour Space: sRGB | DCI-P3" 0.0 0.0 1.0 1.0 +#pragma parameter hcrt_lcd_resolution " Display's Resolution: 4K | 8K" 0.0 0.0 1.0 1.0 +#pragma parameter hcrt_lcd_subpixel " Display's Subpixel Layout: RGB | BGR" 0.0 0.0 1.0 1.0 +#pragma parameter hcrt_red_vertical_convergence " Red Vertical Convergence" 0.00 -10.0 10.0 0.01 +#pragma parameter hcrt_green_vertical_convergence " Green Vertical Convergence" 0.00 -10.0 10.0 0.01 +#pragma parameter hcrt_blue_vertical_convergence " Blue Vertical Convergence" 0.00 -10.0 10.0 0.01 +#pragma parameter hcrt_red_horizontal_convergence " Red Horizontal Convergence" 0.00 -10.0 10.0 0.01 +#pragma parameter hcrt_green_horizontal_convergence " Green Horizontal Convergence" 0.00 -10.0 10.0 0.01 +#pragma parameter hcrt_blue_horizontal_convergence " Blue Horizontal Convergence" 0.00 -10.0 10.0 0.01 + +#pragma parameter hcrt_space3 " " 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_developer_settings "DEVELOPER SETTINGS:" 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_crt_screen_type " CRT Type: APERTURE GRILLE | SHADOW MASK | SLOT MASK" 0.0 0.0 2.0 1.0 +#pragma parameter hcrt_crt_resolution " CRT Resolution: 600TVL | 800TVL | 1000TVL" 0.0 0.0 2.0 1.0 +#pragma parameter hcrt_colour_system " CRT Colour System: PAL | NTSC-U | NTSC-J" 1.0 0.0 2.0 1.0 +#pragma parameter hcrt_white_temperature " White Point: (PAL:D65, NTSC-U:D65, NTSC-J:D93)" 0.0 -5000.0 12000.0 100.0 +#pragma parameter hcrt_expand_gamut " HDR: Original/Vivid" 0.0 0.0 1.0 1.0 +#pragma parameter hcrt_brightness " Brightness" 0.0 -1.0 1.0 0.01 +#pragma parameter hcrt_contrast " Contrast" 0.0 -1.0 1.0 0.01 +#pragma parameter hcrt_saturation " Saturation" 0.0 -1.0 1.0 0.01 +#pragma parameter hcrt_gamma " Gamma" 0.0 -1.0 1.0 0.01 + +#pragma parameter hcrt_developer_settings0 " VERTICAL SETTINGS:" 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_red_scanline_min " Red Scanline Min" 0.50 0.0 2.0 0.01 +#pragma parameter hcrt_red_scanline_max " Red Scanline Max" 1.00 0.0 2.0 0.01 +#pragma parameter hcrt_red_scanline_attack " Red Scanline Attack" 0.20 0.0 1.0 0.01 +#pragma parameter hcrt_green_scanline_min " Green Scanline Min" 0.50 0.0 2.0 0.01 +#pragma parameter hcrt_green_scanline_max " Green Scanline Max" 1.00 0.0 2.0 0.01 +#pragma parameter hcrt_green_scanline_attack " Green Scanline Attack" 0.20 0.0 1.0 0.01 +#pragma parameter hcrt_blue_scanline_min " Blue Scanline Min" 0.50 0.0 2.0 0.01 +#pragma parameter hcrt_blue_scanline_max " Blue Scanline Max" 1.00 0.0 2.0 0.01 +#pragma parameter hcrt_blue_scanline_attack " Blue Scanline Attack" 0.20 0.0 1.0 0.01 +#pragma parameter hcrt_developer_settings1 " HORIZONTAL SETTINGS:" 0.0 0.0 0.0001 0.0 +#pragma parameter hcrt_red_beam_sharpness " Red Beam Sharpness" 1.75 0.0 5.0 0.05 +#pragma parameter hcrt_red_beam_attack " Red Beam Attack" 0.50 0.0 2.0 0.01 +#pragma parameter hcrt_green_beam_sharpness " Green Beam Sharpness" 1.75 0.0 5.0 0.05 +#pragma parameter hcrt_green_beam_attack " Green Beam Attack" 0.50 0.0 2.0 0.01 +#pragma parameter hcrt_blue_beam_sharpness " Blue Beam Sharpness" 1.75 0.0 5.0 0.05 +#pragma parameter hcrt_blue_beam_attack " Blue Beam Attack" 0.50 0.0 2.0 0.01 + + diff --git a/hdr/shaders/include/scanline_generation.h b/hdr/shaders/include/scanline_generation.h index 9b8b7ab..4e1b1cc 100644 --- a/hdr/shaders/include/scanline_generation.h +++ b/hdr/shaders/include/scanline_generation.h @@ -4,136 +4,129 @@ #define kMax 1.0f #define kBeamWidth 0.5f -#define kLumaRatio 0.5f const vec4 kFallOffControlPoints = vec4(0.0f, 0.0f, 0.0f, 1.0f); const vec4 kAttackControlPoints = vec4(0.0f, 1.0f, 1.0f, 1.0f); //const vec4 kScanlineControlPoints = vec4(1.0f, 1.0f, 0.0f, 0.0f); -vec4 RedBeamControlPoints(const bool falloff) +const mat4 kCubicBezier = mat4( 1.0f, 0.0f, 0.0f, 0.0f, + -3.0f, 3.0f, 0.0f, 0.0f, + 3.0f, -6.0f, 3.0f, 0.0f, + -1.0f, 3.0f, -3.0f, 1.0f ); + +float Bezier(const float t0, const vec4 control_points) { - float inner_attack = clamp(HCRT_RED_BEAM_ATTACK, 0.0f, 1.0); - float outer_attack = clamp(HCRT_RED_BEAM_ATTACK - 1.0f, 0.0f, 1.0); + vec4 t = vec4(1.0, t0, t0*t0, t0*t0*t0); + return dot(t, control_points * kCubicBezier); +} + +vec4 BeamControlPoints(const float beam_attack, const bool falloff) +{ + const float inner_attack = clamp(beam_attack, 0.0f, 1.0); + const float outer_attack = clamp(beam_attack - 1.0f, 0.0f, 1.0); return falloff ? kFallOffControlPoints + vec4(0.0f, outer_attack, inner_attack, 0.0f) : kAttackControlPoints - vec4(0.0f, inner_attack, outer_attack, 0.0f); } -vec4 GreenBeamControlPoints(const bool falloff) +float ScanlineColour(const uint channel, + const vec2 source_size, + const float scanline_size, + const float source_tex_coord_x, + const float narrowed_source_pixel_offset, + const float vertical_convergence, + const float beam_attack, + const float scanline_min, + const float scanline_max, + const float scanline_attack, + inout float next_prev) { - float inner_attack = clamp(HCRT_GREEN_BEAM_ATTACK, 0.0f, 1.0); - float outer_attack = clamp(HCRT_GREEN_BEAM_ATTACK - 1.0f, 0.0f, 1.0); - - return falloff ? kFallOffControlPoints + vec4(0.0f, outer_attack, inner_attack, 0.0f) : kAttackControlPoints - vec4(0.0f, inner_attack, outer_attack, 0.0f); -} - -vec4 BlueBeamControlPoints(const bool falloff) -{ - float inner_attack = clamp(HCRT_BLUE_BEAM_ATTACK, 0.0f, 1.0); - float outer_attack = clamp(HCRT_BLUE_BEAM_ATTACK - 1.0f, 0.0f, 1.0); - - return falloff ? kFallOffControlPoints + vec4(0.0f, outer_attack, inner_attack, 0.0f) : kAttackControlPoints - vec4(0.0f, inner_attack, outer_attack, 0.0f); -} - -vec3 InverseTonemapConditional(const vec3 linear) -{ - if(HCRT_HDR > 0.0f) - { - return linear; - } - else - { - return InverseTonemap(linear, HCRT_MAX_NITS, HCRT_PAPER_WHITE_NITS, kLumaRatio); - } -} - -vec3 ScanlineColour(const vec2 source_size, const float scanline_size, const vec3 source_tex_coord_x, const vec3 narrowed_source_pixel_offset, inout vec3 next_prev) -{ - const vec3 current_source_position_y = (vec3(vTexCoord.y * source_size.y) - vec3(HCRT_RED_VERTICAL_CONVERGENCE, HCRT_GREEN_VERTICAL_CONVERGENCE, HCRT_BLUE_VERTICAL_CONVERGENCE)) + next_prev; - const vec3 current_source_center_y = floor(current_source_position_y) + 0.5f; + const float current_source_position_y = ((vTexCoord.y * source_size.y) - vertical_convergence) + next_prev; + const float current_source_center_y = floor(current_source_position_y) + 0.5f; - const vec3 source_tex_coord_y = current_source_center_y / source_size.y; + const float source_tex_coord_y = current_source_center_y / source_size.y; - const vec3 scanline_delta = fract(current_source_position_y) - 0.5f; + const float scanline_delta = fract(current_source_position_y) - 0.5f; // Slightly increase the beam width to get maximum brightness - vec3 beam_distance = abs(scanline_delta - next_prev) - (kBeamWidth / scanline_size); - beam_distance = vec3(beam_distance.x < 0.0f ? 0.0f : beam_distance.x, - beam_distance.y < 0.0f ? 0.0f : beam_distance.y, - beam_distance.z < 0.0f ? 0.0f : beam_distance.z); - const vec3 scanline_distance = beam_distance * 2.0f; + float beam_distance = abs(scanline_delta - next_prev) - (kBeamWidth / scanline_size); + beam_distance = beam_distance < 0.0f ? 0.0f : beam_distance; + const float scanline_distance = beam_distance * 2.0f; - next_prev.x = scanline_delta.x > 0.0f ? 1.0f : -1.0f; - next_prev.y = scanline_delta.y > 0.0f ? 1.0f : -1.0f; - next_prev.z = scanline_delta.z > 0.0f ? 1.0f : -1.0f; + next_prev = scanline_delta > 0.0f ? 1.0f : -1.0f; - const vec2 red_tex_coord_0 = vec2(source_tex_coord_x.x, source_tex_coord_y.x); - const vec2 red_tex_coord_1 = vec2(source_tex_coord_x.x + (1.0f / source_size.x), source_tex_coord_y.x); + const vec2 tex_coord_0 = vec2(source_tex_coord_x, source_tex_coord_y); + const vec2 tex_coord_1 = vec2(source_tex_coord_x + (1.0f / source_size.x), source_tex_coord_y); - const vec2 green_tex_coord_0 = vec2(source_tex_coord_x.y, source_tex_coord_y.y); - const vec2 green_tex_coord_1 = vec2(source_tex_coord_x.y + (1.0f / source_size.x), source_tex_coord_y.y); + const float sdr_channel_0 = COMPAT_TEXTURE(SourceSDR, tex_coord_0)[channel]; + const float sdr_channel_1 = COMPAT_TEXTURE(SourceSDR, tex_coord_1)[channel]; - const vec2 blue_tex_coord_0 = vec2(source_tex_coord_x.z, source_tex_coord_y.z); - const vec2 blue_tex_coord_1 = vec2(source_tex_coord_x.z + (1.0f / source_size.x), source_tex_coord_y.z); - - const float red_0 = COMPAT_TEXTURE(Source, red_tex_coord_0).x; - const float red_1 = COMPAT_TEXTURE(Source, red_tex_coord_1).x; - - const float green_0 = COMPAT_TEXTURE(Source, green_tex_coord_0).y; - const float green_1 = COMPAT_TEXTURE(Source, green_tex_coord_1).y; - - const float blue_0 = COMPAT_TEXTURE(Source, blue_tex_coord_0).z; - const float blue_1 = COMPAT_TEXTURE(Source, blue_tex_coord_1).z; - - const vec3 sdr_colour_0 = ColourGrade(vec3(red_0, green_0, blue_0)); - const vec3 sdr_colour_1 = ColourGrade(vec3(red_1, green_1, blue_1)); - - const vec3 hdr_colour_0 = InverseTonemapConditional(sdr_colour_0); - const vec3 hdr_colour_1 = InverseTonemapConditional(sdr_colour_1); + const float hdr_channel_0 = COMPAT_TEXTURE(SourceHDR, tex_coord_0)[channel]; + const float hdr_channel_1 = COMPAT_TEXTURE(SourceHDR, tex_coord_1)[channel]; /* Horizontal interpolation between pixels */ - const vec3 horiz_interp = vec3(Bezier(narrowed_source_pixel_offset.x, RedBeamControlPoints(sdr_colour_0.x > sdr_colour_1.x)), - Bezier(narrowed_source_pixel_offset.y, GreenBeamControlPoints(sdr_colour_0.y > sdr_colour_1.y)), - Bezier(narrowed_source_pixel_offset.z, BlueBeamControlPoints(sdr_colour_0.z > sdr_colour_1.z))); + const float horiz_interp = Bezier(narrowed_source_pixel_offset, BeamControlPoints(beam_attack, sdr_channel_0 > sdr_channel_1)); - const vec3 hdr_colour = mix(hdr_colour_0, hdr_colour_1, horiz_interp); - const vec3 sdr_colour = mix(sdr_colour_0, sdr_colour_1, horiz_interp); + const float hdr_channel = mix(hdr_channel_0, hdr_channel_1, horiz_interp); + const float sdr_channel = mix(sdr_channel_0, sdr_channel_1, horiz_interp); - const float red_scanline_distance = clamp(scanline_distance.x / ((sdr_colour.r * (HCRT_RED_SCANLINE_MAX - HCRT_RED_SCANLINE_MIN)) + HCRT_RED_SCANLINE_MIN), 0.0f, 1.0f); - const float green_scanline_distance = clamp(scanline_distance.y / ((sdr_colour.g * (HCRT_GREEN_SCANLINE_MAX - HCRT_GREEN_SCANLINE_MIN)) + HCRT_GREEN_SCANLINE_MIN), 0.0f, 1.0f); - const float blue_scanline_distance = clamp(scanline_distance.z / ((sdr_colour.b * (HCRT_BLUE_SCANLINE_MAX - HCRT_BLUE_SCANLINE_MIN)) + HCRT_BLUE_SCANLINE_MIN), 0.0f, 1.0f); + const float channel_scanline_distance = clamp(scanline_distance / ((sdr_channel * (scanline_max - scanline_min)) + scanline_min), 0.0f, 1.0f); - const vec4 red_control_points = vec4(1.0f, 1.0f, sdr_colour.r * HCRT_RED_SCANLINE_ATTACK, 0.0f); - const vec4 green_control_points = vec4(1.0f, 1.0f, sdr_colour.g * HCRT_GREEN_SCANLINE_ATTACK, 0.0f); - const vec4 blue_control_points = vec4(1.0f, 1.0f, sdr_colour.b * HCRT_BLUE_SCANLINE_ATTACK, 0.0f); + const vec4 channel_control_points = vec4(1.0f, 1.0f, sdr_channel * scanline_attack, 0.0f); - const vec3 luminance = vec3(Bezier(red_scanline_distance, red_control_points), - Bezier(green_scanline_distance, green_control_points), - Bezier(blue_scanline_distance, blue_control_points)); + const float luminance = Bezier(channel_scanline_distance, channel_control_points); - return luminance * hdr_colour; + return luminance * hdr_channel; } - -vec3 GenerateScanline(const vec2 source_size, const float scanline_size) + +float GenerateScanline( const uint channel, + const vec2 source_size, + const float scanline_size, + const float horizontal_convergence, + const float vertical_convergence, + const float beam_sharpness, + const float beam_attack, + const float scanline_min, + const float scanline_max, + const float scanline_attack) { - const vec3 current_source_position_x = vec3(vTexCoord.x * source_size.x) - vec3(HCRT_RED_HORIZONTAL_CONVERGENCE, HCRT_GREEN_HORIZONTAL_CONVERGENCE, HCRT_BLUE_HORIZONTAL_CONVERGENCE); - const vec3 current_source_center_x = floor(current_source_position_x) + 0.5f; + const float current_source_position_x = (vTexCoord.x * source_size.x) - horizontal_convergence; + const float current_source_center_x = floor(current_source_position_x) + 0.5f; - const vec3 source_tex_coord_x = current_source_center_x / source_size.x; + const float source_tex_coord_x = current_source_center_x / source_size.x; - const vec3 source_pixel_offset = fract(current_source_position_x); + const float source_pixel_offset = fract(current_source_position_x); - const vec3 beam_sharpness = vec3(HCRT_RED_BEAM_SHARPNESS, HCRT_GREEN_BEAM_SHARPNESS, HCRT_BLUE_BEAM_SHARPNESS); - const vec3 narrowed_source_pixel_offset = clamp(((source_pixel_offset - vec3(0.5f)) * beam_sharpness) + vec3(0.5f), vec3(0.0f), vec3(1.0f)); + const float narrowed_source_pixel_offset = clamp(((source_pixel_offset - 0.5f) * beam_sharpness) + 0.5f, 0.0f, 1.0f); - vec3 next_prev = vec3(0.0f); + float next_prev = 0.0f; - const vec3 scanline_colour0 = ScanlineColour(source_size, scanline_size, source_tex_coord_x, narrowed_source_pixel_offset, next_prev); + const float scanline_colour0 = ScanlineColour( channel, + source_size, + scanline_size, + source_tex_coord_x, + narrowed_source_pixel_offset, + vertical_convergence, + beam_attack, + scanline_min, + scanline_max, + scanline_attack, + next_prev); // Optionally sample the neighbouring scanline - vec3 scanline_colour1 = vec3(0.0f); - if(HCRT_RED_SCANLINE_MAX > 1.0f || HCRT_GREEN_SCANLINE_MAX > 1.0f || HCRT_BLUE_SCANLINE_MAX > 1.0f) + float scanline_colour1 = 0.0f; + if(scanline_max > 1.0f) { - scanline_colour1 = ScanlineColour(source_size, scanline_size, source_tex_coord_x, narrowed_source_pixel_offset, next_prev); + scanline_colour1 = ScanlineColour( channel, + source_size, + scanline_size, + source_tex_coord_x, + narrowed_source_pixel_offset, + vertical_convergence, + beam_attack, + scanline_min, + scanline_max, + scanline_attack, + next_prev); } return scanline_colour0 + scanline_colour1;