The most accurate CRT experience possible - call to all shader pros

I agree and don’t wanted to start a debate.

2 Likes

I also like the way consumer CRTs look, but I don’t have a strong preference. PVM, BVM, consumer, they all look great in their own way. Scanline shape is mostly determined by the need to prevent clipping and under-saturation with higher post-CRT brightness levels, they just kind of happen to wind up looking PVM/BVM-like when you increase the post-CRT brightness by this much. That’s kind of appropriate though given that the TVL of the mask winds up being 540 on a 1080p screen.

2 Likes

In your photo I can see some individual RGB phosphor bleed over the black lines and that the black lines are a bit more solid over brights (compared to the shader shot you posted). The individual phosphor bleed gives the scanlines a texture that mask 7 can’t replicate even with deconvergence added, it just can’t do the sawtooth thing. But anyway, here’s another screenshot.

differences from first post:

#reference "test1.slangp"
HSM_GAMMA_IN_LINEARIZE = "2.499999"
HSM_GAMMA_OUT_CRT = "1.500001"
beam_min = "1.700000"
beam_max = "1.700000"

While this looks fine for bright content, it struggles with dark content, even with bright boost dark pixels cranked up. So I may have already pushed gamma too far, have to do some more testing.

2 Likes

Alright, I think you just have to leave gamma alone. Lowering output gamma helps prevent the screen from washing out during bright scenes when using very high post-CRT brightness levels, but it also makes the screen too dark during dark scenes. Raising gammas has the odd side effect of adding glow halos to everything.

This is what I have now, I’m not sure how to improve it without some kind of dynamic gamma or something (or a much brighter display).

shaders = "40"
shader0 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm/hsm-prep-add-params-standard.slang"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "false"
srgb_framebuffer0 = "false"
shader1 = "shaders_slang/stock.slang"
filter_linear1 = "false"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = "DerezedPass"
float_framebuffer1 = "false"
srgb_framebuffer1 = "true"
scale_type_x1 = "source"
scale_x1 = "1.000000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm/hsm-prep-info-cache-standard.slang"
filter_linear2 = "true"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
alias2 = "InfoCachePass"
float_framebuffer2 = "true"
srgb_framebuffer2 = "false"
scale_type_x2 = "source"
scale_x2 = "1.000000"
scale_type_y2 = "source"
scale_y2 = "1.000000"
shader3 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm/hsm-prep-intro-standard.slang"
filter_linear3 = "false"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "false"
alias3 = "IntroPass"
float_framebuffer3 = "true"
srgb_framebuffer3 = "false"
scale_type_x3 = "source"
scale_x3 = "1.000000"
scale_type_y3 = "source"
scale_y3 = "1.000000"
shader4 = "shaders_slang/stock.slang"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "false"
alias4 = "PreDeDitheringPass"
float_framebuffer4 = "false"
srgb_framebuffer4 = "false"
shader5 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-mdapt/hsm-mdapt-pass0.slang"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "false"
alias5 = ""
float_framebuffer5 = "false"
srgb_framebuffer5 = "false"
shader6 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-mdapt/hsm-mdapt-pass1.slang"
wrap_mode6 = "clamp_to_border"
mipmap_input6 = "false"
alias6 = ""
float_framebuffer6 = "false"
srgb_framebuffer6 = "false"
shader7 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-mdapt/hsm-mdapt-pass2.slang"
wrap_mode7 = "clamp_to_border"
mipmap_input7 = "false"
alias7 = ""
float_framebuffer7 = "false"
srgb_framebuffer7 = "false"
shader8 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-mdapt/hsm-mdapt-pass3.slang"
wrap_mode8 = "clamp_to_border"
mipmap_input8 = "false"
alias8 = ""
float_framebuffer8 = "false"
srgb_framebuffer8 = "false"
shader9 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-mdapt/hsm-mdapt-pass4.slang"
wrap_mode9 = "clamp_to_border"
mipmap_input9 = "false"
alias9 = ""
float_framebuffer9 = "false"
srgb_framebuffer9 = "false"
shader10 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-sgenpt-mix/hsm-sgenpt-mix.slang"
wrap_mode10 = "clamp_to_border"
mipmap_input10 = "false"
alias10 = ""
float_framebuffer10 = "false"
srgb_framebuffer10 = "false"
shader11 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-ps1dither/hsm-PS1-Undither-BoxBlur.slang"
wrap_mode11 = "clamp_to_border"
mipmap_input11 = "false"
alias11 = ""
float_framebuffer11 = "false"
srgb_framebuffer11 = "false"
shader12 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/hsm-custom-fast-sharpen.slang"
filter_linear12 = "false"
wrap_mode12 = "clamp_to_border"
mipmap_input12 = "false"
alias12 = ""
float_framebuffer12 = "true"
srgb_framebuffer12 = "true"
shader13 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-dogway/hsm-grade.slang"
wrap_mode13 = "clamp_to_border"
mipmap_input13 = "false"
alias13 = ""
float_framebuffer13 = "false"
srgb_framebuffer13 = "false"
shader14 = "shaders_slang/stock.slang"
wrap_mode14 = "clamp_to_border"
mipmap_input14 = "false"
alias14 = "refpass"
float_framebuffer14 = "false"
srgb_framebuffer14 = "false"
shader15 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-scalefx/hsm-scalefx-pass0.slang"
filter_linear15 = "false"
wrap_mode15 = "clamp_to_border"
mipmap_input15 = "false"
alias15 = "scalefx_pass0"
float_framebuffer15 = "true"
srgb_framebuffer15 = "false"
scale_type_x15 = "source"
scale_x15 = "1.000000"
scale_type_y15 = "source"
scale_y15 = "1.000000"
shader16 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-scalefx/hsm-scalefx-pass1.slang"
filter_linear16 = "false"
wrap_mode16 = "clamp_to_border"
mipmap_input16 = "false"
alias16 = ""
float_framebuffer16 = "false"
srgb_framebuffer16 = "false"
scale_type_x16 = "source"
scale_x16 = "1.000000"
scale_type_y16 = "source"
scale_y16 = "1.000000"
shader17 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-scalefx/hsm-scalefx-pass2.slang"
filter_linear17 = "false"
wrap_mode17 = "clamp_to_border"
mipmap_input17 = "false"
alias17 = ""
float_framebuffer17 = "false"
srgb_framebuffer17 = "false"
scale_type_x17 = "source"
scale_x17 = "1.000000"
scale_type_y17 = "source"
scale_y17 = "1.000000"
shader18 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-scalefx/hsm-scalefx-pass3.slang"
filter_linear18 = "false"
wrap_mode18 = "clamp_to_border"
mipmap_input18 = "false"
alias18 = ""
float_framebuffer18 = "false"
srgb_framebuffer18 = "false"
scale_type_x18 = "source"
scale_x18 = "1.000000"
scale_type_y18 = "source"
scale_y18 = "1.000000"
shader19 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-scalefx/hsm-scalefx-pass4.slang"
filter_linear19 = "false"
wrap_mode19 = "clamp_to_border"
mipmap_input19 = "false"
alias19 = ""
float_framebuffer19 = "false"
srgb_framebuffer19 = "false"
scale_type_x19 = "source"
scale_x19 = "3.000000"
scale_type_y19 = "source"
scale_y19 = "3.000000"
shader20 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-gtu/hsm-gtu-pass1.slang"
wrap_mode20 = "clamp_to_border"
mipmap_input20 = "false"
alias20 = ""
float_framebuffer20 = "true"
srgb_framebuffer20 = "false"
scale_type_x20 = "source"
scale_x20 = "1.000000"
scale_type_y20 = "source"
scale_y20 = "1.000000"
shader21 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-gtu/hsm-gtu-pass2.slang"
filter_linear21 = "false"
wrap_mode21 = "clamp_to_border"
mipmap_input21 = "false"
alias21 = ""
float_framebuffer21 = "true"
srgb_framebuffer21 = "false"
scale_type_x21 = "source"
scale_x21 = "1.000000"
scale_type_y21 = "source"
scale_y21 = "1.000000"
shader22 = "shaders_slang/stock.slang"
wrap_mode22 = "clamp_to_border"
mipmap_input22 = "false"
alias22 = "PreCRTPass"
float_framebuffer22 = "false"
srgb_framebuffer22 = "false"
shader23 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/hsm-afterglow0.slang"
filter_linear23 = "false"
wrap_mode23 = "clamp_to_border"
mipmap_input23 = "false"
alias23 = "AfterglowPass"
float_framebuffer23 = "false"
srgb_framebuffer23 = "false"
scale_type_x23 = "source"
scale_x23 = "1.000000"
scale_type_y23 = "source"
scale_y23 = "1.000000"
shader24 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/hsm-pre-shaders-afterglow.slang"
filter_linear24 = "false"
wrap_mode24 = "clamp_to_border"
mipmap_input24 = "true"
alias24 = "PrePass"
float_framebuffer24 = "false"
srgb_framebuffer24 = "false"
scale_type_x24 = "source"
scale_x24 = "1.000000"
scale_type_y24 = "source"
scale_y24 = "1.000000"
shader25 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/hsm-avg-lum.slang"
filter_linear25 = "true"
wrap_mode25 = "clamp_to_border"
mipmap_input25 = "true"
alias25 = "AvgLumPass"
float_framebuffer25 = "false"
srgb_framebuffer25 = "false"
scale_type_x25 = "source"
scale_x25 = "1.000000"
scale_type_y25 = "source"
scale_y25 = "1.000000"
shader26 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/hsm-interlace-and-linearize.slang"
filter_linear26 = "true"
wrap_mode26 = "clamp_to_border"
mipmap_input26 = "false"
alias26 = "LinearizePass"
float_framebuffer26 = "true"
srgb_framebuffer26 = "false"
scale_type_x26 = "source"
scale_x26 = "1.000000"
scale_type_y26 = "source"
scale_y26 = "1.000000"
shader27 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/hsm-gaussian_horizontal.slang"
filter_linear27 = "true"
wrap_mode27 = "clamp_to_border"
mipmap_input27 = "false"
alias27 = ""
float_framebuffer27 = "true"
srgb_framebuffer27 = "false"
scale_type_x27 = "absolute"
scale_x27 = "800"
scale_type_y27 = "source"
scale_y27 = "1.000000"
shader28 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/hsm-gaussian_vertical.slang"
filter_linear28 = "true"
wrap_mode28 = "clamp_to_border"
mipmap_input28 = "false"
alias28 = "GlowPass"
float_framebuffer28 = "true"
srgb_framebuffer28 = "false"
scale_type_x28 = "absolute"
scale_x28 = "800"
scale_type_y28 = "absolute"
scale_y28 = "600"
shader29 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/hsm-bloom_horizontal.slang"
filter_linear29 = "true"
wrap_mode29 = "clamp_to_border"
mipmap_input29 = "false"
alias29 = ""
float_framebuffer29 = "true"
srgb_framebuffer29 = "false"
scale_type_x29 = "absolute"
scale_x29 = "800"
scale_type_y29 = "absolute"
scale_y29 = "600"
shader30 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/hsm-bloom_vertical.slang"
filter_linear30 = "true"
wrap_mode30 = "clamp_to_border"
mipmap_input30 = "false"
alias30 = "BloomPass"
float_framebuffer30 = "true"
srgb_framebuffer30 = "false"
scale_type_x30 = "source"
scale_x30 = "1.000000"
scale_type_y30 = "source"
scale_y30 = "1.000000"
shader31 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/hsm-crt-guest-advanced.slang"
filter_linear31 = "true"
wrap_mode31 = "clamp_to_border"
mipmap_input31 = "false"
alias31 = ""
float_framebuffer31 = "false"
srgb_framebuffer31 = "false"
scale_type_x31 = "viewport"
scale_x31 = "1.000000"
scale_type_y31 = "viewport"
scale_y31 = "1.000000"
shader32 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/hsm-deconvergence.slang"
filter_linear32 = "true"
wrap_mode32 = "clamp_to_border"
mipmap_input32 = "false"
alias32 = ""
float_framebuffer32 = "false"
srgb_framebuffer32 = "false"
scale_type_x32 = "viewport"
scale_x32 = "1.000000"
scale_type_y32 = "viewport"
scale_y32 = "1.000000"
shader33 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm/hsm-prep-post-crt.slang"
wrap_mode33 = "clamp_to_border"
mipmap_input33 = "false"
alias33 = "MBZ_PostCRTPass"
float_framebuffer33 = "false"
srgb_framebuffer33 = "false"
shader34 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm/hsm-linearize-crt.slang"
filter_linear34 = "true"
wrap_mode34 = "clamp_to_border"
mipmap_input34 = "true"
alias34 = "BR_MirrorLowResPass"
float_framebuffer34 = "false"
srgb_framebuffer34 = "false"
scale_type_x34 = "absolute"
scale_x34 = "800"
scale_type_y34 = "absolute"
scale_y34 = "600"
shader35 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm/hsm-blur-outside-screen-horiz.slang"
filter_linear35 = "true"
wrap_mode35 = "clamp_to_border"
mipmap_input35 = "true"
alias35 = ""
float_framebuffer35 = "false"
srgb_framebuffer35 = "false"
shader36 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm/hsm-blur-outside-screen-vert.slang"
filter_linear36 = "true"
wrap_mode36 = "clamp_to_border"
mipmap_input36 = "false"
alias36 = "BR_MirrorBlurredPass"
float_framebuffer36 = "false"
srgb_framebuffer36 = "false"
shader37 = "shaders_slang/blurs/blur9x9.slang"
filter_linear37 = "true"
wrap_mode37 = "clamp_to_border"
mipmap_input37 = "true"
alias37 = "BR_MirrorReflectionDiffusedPass"
float_framebuffer37 = "false"
srgb_framebuffer37 = "false"
scale_type_x37 = "absolute"
scale_x37 = "128"
scale_type_y37 = "absolute"
scale_y37 = "128"
shader38 = "shaders_slang/blurs/blur9x9.slang"
filter_linear38 = "true"
wrap_mode38 = "clamp_to_border"
mipmap_input38 = "true"
alias38 = "BR_MirrorFullscreenGlowPass"
float_framebuffer38 = "false"
srgb_framebuffer38 = "false"
scale_type_x38 = "absolute"
scale_x38 = "12"
scale_type_y38 = "absolute"
scale_y38 = "12"
shader39 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm/hsm-bezel-reflection-standard.slang"
wrap_mode39 = "clamp_to_border"
mipmap_input39 = "false"
alias39 = "BR_CRTAndReflectionPass"
float_framebuffer39 = "true"
srgb_framebuffer39 = "false"
scale_type_x39 = "viewport"
scale_x39 = "1.000000"
scale_type_y39 = "viewport"
scale_y39 = "1.000000"
HSM_INT_SCALE_MODE = "1.000000"
HSM_INT_SCALE_BORDER_MIN_HEIGHT = "0.000000"
HSM_NON_INTEGER_SCALE = "100.169739"
HSM_CURVATURE_MODE = "-1.000000"
HSM_GAMMA_IN_LINEARIZE = "2.399999"
HSM_GAMMA_OUT_CRT = "1.800001"
HSM_POST_CRT_BRIGHTNESS = "700.000000"
HSM_TUBE_BLACK_EDGE_CURVATURE_SCALE = "1000.000000"
HSM_FRM_THICKNESS = "150.000000"
g_gamma_out = "2.550000"
g_crtgamut = "0.000000"
g_vignette = "0.000000"
wp_temperature = "6504.000000"
WP = "-100.000000"
glow = "0.005000"
brightboost = "1.000000"
brightboost1 = "1.000000"
gsl = "1.000000"
beam_min = "1.500000"
beam_max = "1.500000"
beam_size = "1.000000"
vertmask = "0.200000"
scans = "1.000000"
spike = "0.000000"
h_sharp = "4.500000"
s_sharp = "0.000000"
maskstr = "1.000000"
mcut = "1.000000"
masksize = "1.000000"
mask_gamma = "2.399999"
slotwidth = "3.000000"
mclip = "0.000000"
decons = "-0.000000"
textures = "SamplerLUT1;SamplerLUT2;SamplerLUT3;SamplerLUT4;IntroImage;ScreenPlacementImage;ColoredGelImage;TubeStaticReflectionImage;BackgroundImage;BackgroundVertImage;ReflectionMaskImage;FrameTextureImage;CabinetGlassImage;DeviceImage;DeviceVertImage;DecalImage;NightLightingImage;LEDImage;TopLayerImage"
SamplerLUT1 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/lut/trinitron-lut.png"
SamplerLUT1_linear = "true"
SamplerLUT1_wrap_mode = "clamp_to_border"
SamplerLUT1_mipmap = "false"
SamplerLUT2 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/lut/inv-trinitron-lut.png"
SamplerLUT2_linear = "true"
SamplerLUT2_wrap_mode = "clamp_to_border"
SamplerLUT2_mipmap = "false"
SamplerLUT3 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/lut/nec-lut.png"
SamplerLUT3_linear = "true"
SamplerLUT3_wrap_mode = "clamp_to_border"
SamplerLUT3_mipmap = "false"
SamplerLUT4 = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/hsm-guest/lut/ntsc-lut.png"
SamplerLUT4_linear = "true"
SamplerLUT4_wrap_mode = "clamp_to_border"
SamplerLUT4_mipmap = "false"
IntroImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/IntroImage_MegaBezelLogo.png"
IntroImage_linear = "true"
IntroImage_wrap_mode = "clamp_to_border"
IntroImage_mipmap = "false"
ScreenPlacementImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/Placeholder_Transparent_16x16.png"
ScreenPlacementImage_linear = "false"
ScreenPlacementImage_wrap_mode = "clamp_to_border"
ScreenPlacementImage_mipmap = "false"
ColoredGelImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/Placeholder_Transparent_16x16.png"
ColoredGelImage_linear = "true"
ColoredGelImage_wrap_mode = "clamp_to_border"
ColoredGelImage_mipmap = "false"
TubeStaticReflectionImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/TubeGlassOverlayImage_3840x2160.png"
TubeStaticReflectionImage_linear = "true"
TubeStaticReflectionImage_wrap_mode = "clamp_to_border"
TubeStaticReflectionImage_mipmap = "false"
BackgroundImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/BackgroundImage_Carbon_3840x2160.png"
BackgroundImage_linear = "true"
BackgroundImage_wrap_mode = "clamp_to_border"
BackgroundImage_mipmap = "false"
BackgroundVertImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/BackgroundImage_Carbon_3840x2160.png"
BackgroundVertImage_linear = "true"
BackgroundVertImage_wrap_mode = "clamp_to_border"
BackgroundVertImage_mipmap = "false"
ReflectionMaskImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/Placeholder_White_16x16.png"
ReflectionMaskImage_linear = "true"
ReflectionMaskImage_wrap_mode = "clamp_to_border"
ReflectionMaskImage_mipmap = "false"
FrameTextureImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/FrameTexture_2800x2120.png"
FrameTextureImage_linear = "true"
FrameTextureImage_wrap_mode = "clamp_to_border"
FrameTextureImage_mipmap = "false"
CabinetGlassImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/Placeholder_Transparent_16x16.png"
CabinetGlassImage_linear = "true"
CabinetGlassImage_wrap_mode = "clamp_to_border"
CabinetGlassImage_mipmap = "false"
DeviceImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/Placeholder_Transparent_16x16.png"
DeviceImage_linear = "true"
DeviceImage_wrap_mode = "clamp_to_border"
DeviceImage_mipmap = "false"
DeviceVertImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/Placeholder_Transparent_16x16.png"
DeviceVertImage_linear = "true"
DeviceVertImage_wrap_mode = "clamp_to_border"
DeviceVertImage_mipmap = "false"
DecalImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/Placeholder_Transparent_16x16.png"
DecalImage_linear = "true"
DecalImage_wrap_mode = "clamp_to_border"
DecalImage_mipmap = "false"
NightLightingImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/NightLighting_3840x2160.jpg"
NightLightingImage_linear = "true"
NightLightingImage_wrap_mode = "clamp_to_border"
NightLightingImage_mipmap = "false"
LEDImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/Placeholder_Transparent_16x16.png"
LEDImage_linear = "true"
LEDImage_wrap_mode = "clamp_to_border"
LEDImage_mipmap = "false"
TopLayerImage = "shaders_slang/bezel/Mega_Bezel/shaders/HyperspaceMadness/textures/Placeholder_Transparent_16x16.png"
TopLayerImage_linear = "true"
TopLayerImage_wrap_mode = "clamp_to_border"
TopLayerImage_mipmap = "false"
2 Likes

I really hope this ends up a success! So far I like the idea and what I’m seeing (and learning). Perhaps when you accomplish the main goal, you can move on to simulating other types of sets. If the technology isn’t there yet to get that perfect or almost perfect simulation then perhaps some compromises might have to be made until better methods or physical hardware becomes available. By that I mean some alternative settings that might be able to be as accurate as possible without resorting to exotic backlight settings that almost any end user can apply.

Anyway, I came across this beautiful picture of a JVC CRT in action and I just had to share it. Hopefully it can be used as a nice reference! Maybe one day, we’ll be able to match this with a picture of a shader running on an LCD or OLED TV!

3 Likes

There’s already plenty of that out there so I’m not really interested.

Adjusting the backlight is trivial. In fact, a lot of monitors come shipped with the backlight already adjusted to 100% because why not?

The goal in this thread is to be as accurate as possible with 0 compromises.

Nice JVC. JVC uses a slot mask, though. I’m not even going to touch that until I have an 8K display.

4 Likes

I’m at the “making small adjustments” phase of this now.

6 Likes

I also tried the slot mask in various configurations and it is indeed too coarse even in 4K (the mask looks like many “S” letters). It needs to be finer and that’s why you are right regarding 8K.

As I am a fan of the aperture grille mask, I’m happy that it works well with 4K.

BTW, I tried your recommendation setting “keep mask with clipping” to 0.00, but with the Trinitron mask 7 it does not do anything. From 0.00 to 1.00 it looks always the same. Maybe it is for Slot mask only, because in the menu it is listed under the slot mask settings.

3 Likes

I think it only applies with mask strength less than 100%, I’m not sure exactly how it works.

2 Likes

I found some interesting info about old monitors, example 1084s has a dot pitch 0.42mm that means you have rgb subpixels on 0.42mm space or say it otherwise 1 pixel has around 0.42mm size on 14" screen size. I don’t know if that can be emulated too. I know most todays screens have around 0.20 so you would need 2 pixels to emulate that. So in the end maybe mask 0 is most accurate if actual LCD subpixel structure permits it (i have a monitor that has rgb rotated to the left structure, so it’s bgr up to down, so not there).

2 Likes

Pardon my ignorance, but is what you’re looking for essentially just HDR? I know retroarch now has HDR functionality but I’m not certain how it works with shaders. But I’d think it could compensate missing brightness/create the sort of contrast between bright scanlines and the black space between much more accurately.

3 Likes

Hmm on 1080 you need 4 pixels mask to match a consumer crt. So maybe mask 2 of lottes (rgb) with 1 black line added? But then you have a dot pitch of 0.80!? (usually around 0.50 on normal Crts). Tricky. If you use mask 0 you get 540 TVL but dot pitch is correct. The proper image is scale it 2x and apply mask 0 but then you get a tiny window used. Probably the reason why retro games look really well on psp, because using its own mask (0.20) and TVL is correct although too sharp.

Ps probably mask 2 of lottes as it is, 360 TVL and 0.60 dot pitch. A bit off but good enough

2 Likes

AFAIK Retroarch HDR only works in DX12 video so it has limitations. I suggested some kind of fake HDR like some reshade shaders.

Hopefully @guest.r or @HyperspaceMadness takes up the challenge. :wink:

5 Likes

It should work with d3d11 now, too.

5 Likes

What do you think of this @Nesguy? Is it close, better or worse than the best we have available here on RetroArch currently?

1 Like

I don’t think you can get a shadow mask or aperture grille mask etc to be bright enough on a standard dynamic range monitor. Which will be what someone with a MiSTer is using as HDR is flat out not supported.

If you think about it this makes sense as a mask is only going to darken the screen. At best it will keep it the same and as SDR monitors aren’t as bright as a CRT (my Sony PVM 2730 at least) then you aren’t going to get the brightness (or colours).

(Shameless plug) See my new shader which does everything in HDR for an example of getting the natural brightness of a CRT - you’ll need an LCD capable of 700 nits and more in my experience.

Also 4k is an absolute minimum I’d say for a 600TVL 4:3. As that’s number of lines across the screen to the height of the screen so a 600TVL will actually have 800 (600*(4/3)) lines across the whole width. Minimum pattern is 3 pixels really so that’s 3*800=2400 and the 3840 pixels of a 4k LCD is across a 16:9 screen i.e you have to take off a quarter of the pixels to get into 4:3 ratio i.e you have 2880 pixels to play with.

I squeeze a four pixel pattern into it and it seems to produce a close resolution.

Shaders: slang_shaders/HDR/CRT-sony-pvm-2730-4k-hdr.slangp

TVL description: https://andynumbers.wordpress.com/2016/07/21/lets-talk-about-tvl-count/

More info:

4 Likes

Also you really need to take photos of the screen - not screenshots taken with a snipping tool or video grabber etc as that’s not going to let you see the natural bloom of a bright screen like a CRT or high end LCD. (Even photos are poor proxies to the real thing)

2 Likes

This is like zfast-crt level stuff, not much to get excited about IMO.

@MajorPainTheCactus

Some time ago I said that with 4K and HDR all we need is a very simple shader- just scanlines, mask, and some color grading. You’ve gone and proved it. Very nice work! Now I need to buy an HDR graphics card.

2 Likes

Thanks @Nesguy! As always there’s lots we can improve upon especially more colour grading options, shadow and slot masks, geometry warping and introducing some of the ‘defects’ in CRT’s like misaligned convergence but we’ve got a good chunk of the way there given today’s display hardware limitations.

All we need now is for Linux/Vulkan to support HDR! I’d also like to see this in a lower powered device like a Raspberry Pi - the greatly simplified shaders make this much more possible. (Although 4K still seems out of the reach of the Pi 4 at the moment.)

3 Likes

Yeah, this is my dream :star_struck:,

Thanks so much! I think this is a really amazing addition to retroarch and gift to the community.

I have an HDR monitor here, so I’m looking forward to try this out!

2 Likes