Optimised sony megatron shader by adding a three stage process and colour grading at lower source resolution

Fixed include path slashes
This commit is contained in:
MajorPainTheCactus 2022-03-14 23:22:02 +00:00
parent 8121e935bd
commit 2237891c65
13 changed files with 603 additions and 257 deletions

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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;