Added Viewsonic SuperClear A90f+ simulation Added numerous shadow masks

This commit is contained in:
MajorPainTheCactus 2022-02-10 21:45:22 +00:00
parent 70d1b26378
commit c511d122c1
7 changed files with 158 additions and 52 deletions

View file

@ -0,0 +1 @@
#reference "crt-viewsonic-superclear-4k-hdr.slangp"

View file

@ -0,0 +1,55 @@
/*
A shader that specifically tries to emulate Viewsonic SuperClear monitor's with an shadow mask screen but with full brightness.
The novel thing about this shader is that it transforms the image output by the 'console/arcade/computer' into HDR space first i.e brightens it first and then applies
an shadow mask afterwards which is kind of what a CRT would actually do - its kind of a kin to the electron beam (but nothing like it lol).
My DisplayHDR 600 monitor does seem to get reasonably close to the brightness of my PVM - its not quite there but its close. I think DisplayHDR 1000 and above will be able to match.
Currently defaults towards a Viewsonic A90f+.
To use:
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/great.
This shader doesn't do any geometry warping or bouncing of light around inside the screen - I think these effects just add unwanted noise, I know people disagree. Please feel free to make you own and add them
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)
*/
shaders = "1"
feedback_pass = "0"
shader0 = "shaders/crt-shadow-mask-hdr.slang"
filter_linear0 = "false"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "false"
srgb_framebuffer0 = "false"
PaperWhiteNits = "400.000000"
RedConvergence = "0.000000"
GreenConvergence = "0.000000"
BlueConvergence = "0.000000"
RedScanlineMin = "0.5000000"
RedScanlineMax = "1.000000"
RedScanlineAttack = "0.350000"
GreenScanlineMin = "0.550000"
GreenScanlineMax = "1.000000"
GreenScanlineAttack = "0.350000"
BlueScanlineMin = "0.550000"
BlueScanlineMax = "1.000000"
BlueScanlineAttack = "0.350000"
RedBeamSharpness = "1.200000"
RedBeamAttack = "0.5000000"
GreenBeamSharpness = "1.200000"
GreenBeamAttack = "0.500000"
BlueBeamSharpness = "1.200000"
BlueBeamAttack = "0.500000"

View file

@ -36,10 +36,18 @@ THIS SHADER DOES NOT SUPPORT WRGB OLED (Due to the sub pixel layout of WRGB - RG
layout(push_constant) uniform Push layout(push_constant) uniform Push
{ {
#include "include\user_properties.h" #include "include\user_properties.h"
float CRTResolution;
#include "include\developer_properties.h" #include "include\developer_properties.h"
} params; } params;
#include "include\user_parameters.h" #include "include\user_parameters.h"
#pragma parameter Space3 " " 0.0 0.0 0.0 0.0
#pragma parameter DeveloperSettings "DEVELOPER SETTINGS:" 0.0 0.0 0.0 0.0
#pragma parameter CRTResolution " CRT Resolution: 600TVL/800TVL/1000TVL" 0.0 0.0 2.0 1.0
#include "include\developer_parameters.h" #include "include\developer_parameters.h"
layout(std140, set = 0, binding = 0) uniform UBO layout(std140, set = 0, binding = 0) uniform UBO

View file

@ -36,10 +36,18 @@ THIS SHADER DOES NOT SUPPORT WRGB OLED (Due to the sub pixel layout of WRGB - RG
layout(push_constant) uniform Push layout(push_constant) uniform Push
{ {
#include "include\user_properties.h" #include "include\user_properties.h"
float ShadowMaskPattern;
#include "include\developer_properties.h" #include "include\developer_properties.h"
} params; } params;
#include "include\user_parameters.h" #include "include\user_parameters.h"
#pragma parameter Space3 " " 0.0 0.0 0.0 0.0
#pragma parameter DeveloperSettings "DEVELOPER SETTINGS:" 0.0 0.0 0.0 0.0
#pragma parameter ShadowMaskPattern " Shadow Mask: Fine/2x1/1x2/Diagonal/Coarse/8K Coarse" 0.0 0.0 5.0 1.0
#include "include\developer_parameters.h" #include "include\developer_parameters.h"
layout(std140, set = 0, binding = 0) uniform UBO layout(std140, set = 0, binding = 0) uniform UBO
@ -88,65 +96,96 @@ layout(set = 0, binding = 2) uniform sampler2D Source;
#define kWhite vec3(1.0, 1.0, 1.0) #define kWhite vec3(1.0, 1.0, 1.0)
#define kBGRAxis 2 #define kBGRAxis 2
#define kTVLAxis 3 #define kPatternAxis 6
#define kResolutionAxis 2 #define kResolutionAxis 2
#define kMaxMaskSize 8 #define kMaxMaskSize 12
#define kMaxShadowSize 2 #define kMaxShadowSize 8
#define kMaxGridSize 2
#define kXXXX { kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack } #define kXXXX { kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kMG { kMagenta, kGreen, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack } #define kMG { kMagenta, kGreen, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kGM { kGreen, kMagenta, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack } #define kGM { kGreen, kMagenta, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kBGR { kBlue, kGreen, kRed, kBlack, kBlack, kBlack, kBlack, kBlack } #define kMGCRYB { kMagenta, kGreen, kCyan, kRed, kYellow, kBlue, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kRGB { kRed, kGreen, kBlue, kBlack, kBlack, kBlack, kBlack, kBlack } #define kRYBMGC { kRed, kYellow, kBlue, kMagenta, kGreen, kCyan, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kRGBX { kRed, kGreen, kBlue, kBlack, kBlack, kBlack, kBlack, kBlack } #define kRYCB { kRed, kYellow, kCyan, kBlue, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kBGRX { kBlue, kGreen, kRed, kBlack, kBlack, kBlack, kBlack, kBlack } #define kCBRY { kCyan, kBlue, kRed, kYellow, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kXRGB { kBlack, kRed, kGreen, kBlue, kBlack, kBlack, kBlack, kBlack } #define kBGR { kBlue, kGreen, kRed, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kXBGR { kBlack, kBlue, kGreen, kRed, kBlack, kBlack, kBlack, kBlack } #define kRBG { kRed, kBlue, kGreen, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kGRB { kGreen, kRed, kBlue, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kRYCBX { kRed, kYellow, kCyan, kBlue, kBlack, kBlack, kBlack, kBlack } #define kYCM { kCyan, kYellow, kMagenta, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kBCYRX { kBlue, kCyan, kYellow, kRed, kBlack, kBlack, kBlack, kBlack } #define kMYC { kMagenta, kCyan, kYellow, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kCMY { kYellow, kMagenta, kCyan, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kXRYCB { kBlack, kRed, kYellow, kCyan, kBlue, kBlack, kBlack, kBlack } #define kGBRGBR { kGreen, kBlue, kRed, kGreen, kBlue, kRed, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kXBCYR { kBlack, kBlue, kCyan, kYellow, kRed, kBlack, kBlack, kBlack } // TODO: #define kGBRGBR { kGreen, kBlue, kRed, kGreen, kBlue, kRed, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kRRGGBBX { kRed, kRed, kGreen, kGreen, kBlue, kBlue, kBlack, kBlack } #define kGYRMBC { kGreen, kYellow, kRed, kMagenta, kBlue, kCyan, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kBBGGRRX { kBlue, kBlue, kGreen, kGreen, kRed, kRed, kBlack, kBlack } // TODO: #define kGYRMBC { kGreen, kYellow, kRed, kMagenta, kBlue, kCyan, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kXRRGGBB { kBlack, kRed, kRed, kGreen, kGreen, kBlue, kBlue, kBlack } #define kMBCGYR { kMagenta, kBlue, kCyan, kGreen, kYellow, kRed, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kXBBGGRR { kBlack, kBlue, kBlue, kGreen, kGreen, kRed, kRed, kBlack } // TODO: #define kMBCGYR { kMagenta, kBlue, kCyan, kGreen, kYellow, kRed, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kMG_GM { kMG, kGM } #define kGRRBBG { kGreen, kRed, kRed, kBlue, kBlue, kGreen, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kGM_MG { kGM, kMG } #define kBBGGRR { kBlue, kBlue, kGreen, kGreen, kRed, kRed, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kBGR_BGR { kBGR, kRGB } #define kGBBRRG { kGreen, kBlue, kBlue, kRed, kRed, kGreen, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kRGB_RGB { kRGB, kBGR } #define kRRGGBB { kRed, kRed, kGreen, kGreen, kBlue, kBlue, kBlack, kBlack, kBlack, kBlack, kBlack, kBlack }
#define kRGBX_BGRX { kRGBX, kXRGB } #define kGGRRRRBBBBGG { kGreen, kGreen, kRed, kRed, kRed, kRed, kBlue, kBlue, kBlue, kBlue, kGreen, kGreen }
#define kBGRX_RGBX { kBGRX, kXBGR } #define kBBBBGGGGRRRR { kBlue, kBlue, kBlue, kBlue, kGreen, kGreen, kGreen, kGreen, kRed, kRed, kRed, kRed }
#define kRYCBX_BCYRX { kRYCBX, kXRYCB } #define kGGBBBBRRRRGG { kGreen, kGreen, kBlue, kBlue, kBlue, kBlue, kRed, kRed, kRed, kRed, kGreen, kGreen }
#define kBCYRX_RYCBX { kBCYRX, kXBCYR } #define kRRRRGGGGBBBB { kRed, kRed, kRed, kRed, kGreen, kGreen, kGreen, kGreen, kBlue, kBlue, kBlue, kBlue }
#define kRRGGBBX_BBGGRRX { kRRGGBBX, kXRRGGBB } #define kMG_GM { kMG, kGM, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX }
#define kBBGGRRX_RRGGBBX { kBBGGRRX, kXBBGGRR } #define kGM_MG { kGM, kMG, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX }
const uint kPhosphorMaskSize[kResolutionAxis][kTVLAxis] = { { 4, 3, 2 }, { 7, 5, 4 } }; //4K: 600 TVL, 800 TVL, 1000 TVL 8K: 600 TVL, 800 TVL, 1000 TVL #define kBGR_RBG_GRB { kBGR, kRBG, kGRB, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX }
// TODO: #define kBGR_RBG { kBGR, kRBG, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX }
const vec3 kPhosphorMasks[kResolutionAxis][kTVLAxis][kBGRAxis][kMaxShadowSize][kMaxMaskSize] = { #define kYCM_MYC_CMY { kYCM, kMYC, kCMY, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX }
{ // 4K // TODO: #define kBGR_RBG { kYCM, kMYC, kCMY, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX }
{ kRGBX_BGRX, kBGRX_RGBX }, // 600 TVL
{ kBGR_BGR, kRGB_RGB }, // 800 TVL #define kMGMG_GMGM { kMG, kMG, kGM, kGM, kXXXX, kXXXX, kXXXX, kXXXX }
{ kMG_GM, kGM_MG } // 1000 TVL // TODO: #define kMG_GM { kMG, kGM, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX }
},
{ // 8K #define kGRRBBG_GRRBBG_BBGGRR_BBGGRR { kGRRBBG, kGRRBBG, kBBGGRR, kBBGGRR, kXXXX, kXXXX, kXXXX, kXXXX }
{ kRRGGBBX_BBGGRRX, kBBGGRRX_RRGGBBX }, // 600 TVL #define kGBBRRG_GBBRRG_RRGGBB_RRGGBB { kGBBRRG, kGBBRRG, kRRGGBB, kRRGGBB, kXXXX, kXXXX, kXXXX, kXXXX }
{ kRYCBX_BCYRX, kBCYRX_RYCBX }, // 800 TVL
{ kRGBX_BGRX, kBGRX_RGBX } // 1000 TVL #define kGGRRRRBBBBGG_GGRRRRBBBBGG_GGRRRRBBBBGG_GGRRRRBBBBGG_BBBBGGGGRRRR_BBBBGGGGRRRR_BBBBGGGGRRRR_BBBBGGGGRRRR { kGGRRRRBBBBGG, kGGRRRRBBBBGG, kGGRRRRBBBBGG, kGGRRRRBBBBGG, kBBBBGGGGRRRR, kBBBBGGGGRRRR, kBBBBGGGGRRRR, kBBBBGGGGRRRR }
} #define kGGBBBBRRRRGG_GGBBBBRRRRGG_GGBBBBRRRRGG_GGBBBBRRRRGG_RRRRGGGGBBBB_RRRRGGGGBBBB_RRRRGGGGBBBB_RRRRGGGGBBBB { kGGBBBBRRRRGG, kGGBBBBRRRRGG, kGGBBBBRRRRGG, kGGBBBBRRRRGG, kRRRRGGGGBBBB, kRRRRGGGGBBBB, kRRRRGGGGBBBB, kRRRRGGGGBBBB }
#define kRYCB_kCBRY { kRYCB, kCBRY, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX }
// TODO: #define kRYCB_kCBRY { kRYCB, kCBRY, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX }
//#define kMGCRYB_RYBMGC { kMGCRYB, kRYBMGC, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX }
// TODO: #define kMGCRYB_RYBMGC { kMGCRYB, kRYBMGC, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX, kXXXX }
//#define kMGCRYB_MGCRYB_RYBMGC_RYBMGC { kMGCRYB, kMGCRYB, kRYBMGC, kRYBMGC, kXXXX, kXXXX, kXXXX, kXXXX }
// TODO: #define kMGCRYB_MGCRYB_RYBMGC_RYBMGC { kMGCRYB, kMGCRYB, kRYBMGC, kRYBMGC, kXXXX, kXXXX, kXXXX, kXXXX }
#define kGBRGBR_GYRMBC_GBRGBR_MBCGYR { kGBRGBR, kGYRMBC, kGBRGBR, kMBCGYR, kXXXX, kXXXX, kXXXX, kXXXX }
// TODO: #define kGBRGBR_GYRMBC_GBRGBR_MBCGYR { kGBRGBR, kGYRMBC, kGBRGBR, kMBCGYR, kXXXX, kXXXX, kXXXX, kXXXX }
const uint kPhosphorMaskSize[kPatternAxis] = { 2, 2, 4, 3, 6, 12 }; // , 6, 6, 6
const uint kShadowMaskSize[kPatternAxis] = { 2, 4, 2, 3, 4, 8, }; // , 2, 4, 4
const vec3 kPhosphorMasks[kPatternAxis][kBGRAxis][kMaxShadowSize][kMaxMaskSize] = {
{ kMG_GM, kGM_MG }, // Fine
{ kMGMG_GMGM, kMGMG_GMGM },
{ kRYCB_kCBRY, kRYCB_kCBRY },
{ kBGR_RBG_GRB, kBGR_RBG_GRB }, // Coarse0
//{ kYCM_MYC_CMY, kYCM_MYC_CMY },
{ kGRRBBG_GRRBBG_BBGGRR_BBGGRR, kGBBRRG_GBBRRG_RRGGBB_RRGGBB }, // Coarse1
{ kGGRRRRBBBBGG_GGRRRRBBBBGG_GGRRRRBBBBGG_GGRRRRBBBBGG_BBBBGGGGRRRR_BBBBGGGGRRRR_BBBBGGGGRRRR_BBBBGGGGRRRR, kGGBBBBRRRRGG_GGBBBBRRRRGG_GGBBBBRRRRGG_GGBBBBRRRRGG_RRRRGGGGBBBB_RRRRGGGGBBBB_RRRRGGGGBBBB_RRRRGGGGBBBB }, // 8K
// { kMGCRYB_RYBMGC, kMGCRYB_RYBMGC }, // Tile0
// { kMGCRYB_MGCRYB_RYBMGC_RYBMGC, kMGCRYB_MGCRYB_RYBMGC_RYBMGC }, // Tile1
// { kGBRGBR_GYRMBC_GBRGBR_MBCGYR, kGBRGBR_GYRMBC_GBRGBR_MBCGYR } // Tile2
}; };
float ModInteger(float a, float b) float ModInteger(float a, float b)
@ -164,15 +203,14 @@ void main()
vec3 scanline_colour = GenerateScanline(current_position); vec3 scanline_colour = GenerateScanline(current_position);
{ {
uint lcd_subpixel_layout = uint(params.LCDSubpixel); uint lcd_subpixel_layout = uint(params.LCDSubpixel);
uint crt_resolution = uint(params.CRTResolution); uint shadow_mask = uint(params.ShadowMaskPattern);
uint lcd_resolution = uint(params.LCDResolution);
uint shadow_y = uint(ModInteger(floor(current_position.y), kMaxShadowSize)); uint shadow_y = uint(ModInteger(floor(current_position.y), kShadowMaskSize[shadow_mask]));
uint mask = uint(ModInteger(floor(current_position.x), kPhosphorMaskSize[lcd_resolution][crt_resolution])); uint mask = uint(ModInteger(floor(current_position.x), kPhosphorMaskSize[shadow_mask]));
scanline_colour *= kPhosphorMasks[lcd_resolution][crt_resolution][lcd_subpixel_layout][shadow_y][mask]; scanline_colour *= kPhosphorMasks[shadow_mask][lcd_subpixel_layout][shadow_y][mask];
} }
// HACK: To get maximum brightness we just set paper white luminance to max luminance // HACK: To get maximum brightness we just set paper white luminance to max luminance

View file

@ -36,10 +36,18 @@ THIS SHADER DOES NOT SUPPORT WRGB OLED (Due to the sub pixel layout of WRGB - RG
layout(push_constant) uniform Push layout(push_constant) uniform Push
{ {
#include "include\user_properties.h" #include "include\user_properties.h"
float CRTResolution;
#include "include\developer_properties.h" #include "include\developer_properties.h"
} params; } params;
#include "include\user_parameters.h" #include "include\user_parameters.h"
#pragma parameter Space3 " " 0.0 0.0 0.0 0.0
#pragma parameter DeveloperSettings "DEVELOPER SETTINGS:" 0.0 0.0 0.0 0.0
#pragma parameter CRTResolution " CRT Resolution: 600TVL/800TVL/1000TVL" 0.0 0.0 2.0 1.0
#include "include\developer_parameters.h" #include "include\developer_parameters.h"
layout(std140, set = 0, binding = 0) uniform UBO layout(std140, set = 0, binding = 0) uniform UBO

View file

@ -1,7 +1,4 @@
#pragma parameter Space3 " " 0.0 0.0 0.0 0.0
#pragma parameter DeveloperSettings "DEVELOPER SETTINGS:" 0.0 0.0 0.0 0.0
#pragma parameter CRTResolution " CRT Resolution: 600TVL/800TVL/1000TVL" 0.0 0.0 2.0 1.0
#pragma parameter DeveloperSettings0 " VERTICAL SETTINGS:" 0.0 0.0 0.0 0.0 #pragma parameter DeveloperSettings0 " VERTICAL SETTINGS:" 0.0 0.0 0.0 0.0
#pragma parameter RedScanlineMin " Red Scanline Min" 0.50 0.0 2.0 0.01 #pragma parameter RedScanlineMin " Red Scanline Min" 0.50 0.0 2.0 0.01
#pragma parameter RedScanlineMax " Red Scanline Max" 1.00 0.0 2.0 0.01 #pragma parameter RedScanlineMax " Red Scanline Max" 1.00 0.0 2.0 0.01

View file

@ -1,7 +1,6 @@
// Developer Settings // Developer Settings
float CRTResolution;
// Vertical Settings // Vertical Settings
float RedScanlineMin; float RedScanlineMin;