From 36db5c17cbcb06ce6634a796d482b57fec7cef43 Mon Sep 17 00:00:00 2001 From: hunterk Date: Wed, 2 May 2018 14:26:13 -0500 Subject: [PATCH] fix pal-r57shell and remove unnecessary multipass version, add royale ntsc/pal presets --- crt/crt-royale-ntsc-256px-composite.slangp | 224 ++++++++++ crt/crt-royale-ntsc-256px-svideo.slangp | 224 ++++++++++ crt/crt-royale-ntsc-320px-composite.slangp | 224 ++++++++++ crt/crt-royale-ntsc-320px-svideo.slangp | 224 ++++++++++ crt/crt-royale-pal-r57shell.slangp | 219 ++++++++++ pal/pal-r57shell-multipass.slangp | 11 - pal/pal-r57shell.slangp | 15 + pal/shaders/pal-r57shell-multipass0.slang | 480 --------------------- pal/shaders/pal-r57shell-multipass1.slang | 107 ----- pal/shaders/pal-r57shell.slang | 25 +- 10 files changed, 1145 insertions(+), 608 deletions(-) create mode 100644 crt/crt-royale-ntsc-256px-composite.slangp create mode 100644 crt/crt-royale-ntsc-256px-svideo.slangp create mode 100644 crt/crt-royale-ntsc-320px-composite.slangp create mode 100644 crt/crt-royale-ntsc-320px-svideo.slangp create mode 100644 crt/crt-royale-pal-r57shell.slangp delete mode 100644 pal/pal-r57shell-multipass.slangp delete mode 100644 pal/shaders/pal-r57shell-multipass0.slang delete mode 100644 pal/shaders/pal-r57shell-multipass1.slang diff --git a/crt/crt-royale-ntsc-256px-composite.slangp b/crt/crt-royale-ntsc-256px-composite.slangp new file mode 100644 index 0000000..4f8ebf7 --- /dev/null +++ b/crt/crt-royale-ntsc-256px-composite.slangp @@ -0,0 +1,224 @@ +# IMPORTANT: +# Shader passes need to know details about the image in the mask_texture LUT +# files, so set the following constants in user-cgp-constants.h accordingly: +# 1.) mask_triads_per_tile = (number of horizontal triads in mask texture LUT's) +# 2.) mask_texture_small_size = (texture size of mask*texture_small LUT's) +# 3.) mask_texture_large_size = (texture size of mask*texture_large LUT's) +# 4.) mask_grille_avg_color = (avg. brightness of mask_grille_texture* LUT's, in [0, 1]) +# 5.) mask_slot_avg_color = (avg. brightness of mask_slot_texture* LUT's, in [0, 1]) +# 6.) mask_shadow_avg_color = (avg. brightness of mask_shadow_texture* LUT's, in [0, 1]) +# Shader passes also need to know certain scales set in this .slangp, but their +# compilation model doesn't currently allow the .slangp file to tell them. Make +# sure to set the following constants in user-cgp-constants.h accordingly too: +# 1.) bloom_approx_scale_x = scale_x2 +# 2.) mask_resize_viewport_scale = float2(scale_x6, scale_y5) +# Finally, shader passes need to know the value of geom_max_aspect_ratio used to +# calculate scale_y5 (among other values): +# 1.) geom_max_aspect_ratio = (geom_max_aspect_ratio used to calculate scale_y5) + +shaders = "14" + +# NTSC Shader Passes +shader0 = "../ntsc/shaders/ntsc-pass1-composite-3phase.slang" +shader1 = "../ntsc/shaders/ntsc-pass2-3phase.slang" + +filter_linear0 = false +filter_linear1 = false + +scale_type_x0 = absolute +scale_type_y0 = source +scale_x0 = 1024 +scale_y0 = 1.0 +frame_count_mod0 = 2 +float_framebuffer0 = true + +scale_type1 = source +scale_x1 = 0.5 +scale_y1 = 1.0 + +# Set an identifier, filename, and sampling traits for the phosphor mask texture. +# Load an aperture grille, slot mask, and an EDP shadow mask, and load a small +# non-mipmapped version and a large mipmapped version. +# TODO: Test masks in other directories. +textures = "mask_grille_texture_small;mask_grille_texture_large;mask_slot_texture_small;mask_slot_texture_large;mask_shadow_texture_small;mask_shadow_texture_large" +mask_grille_texture_small = "shaders/crt-royale/TileableLinearApertureGrille15Wide8And5d5SpacingResizeTo64.png" +mask_grille_texture_large = "shaders/crt-royale/TileableLinearApertureGrille15Wide8And5d5Spacing.png" +mask_slot_texture_small = "shaders/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacingResizeTo64.png" +mask_slot_texture_large = "shaders/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing.png" +mask_shadow_texture_small = "shaders/crt-royale/TileableLinearShadowMaskEDPResizeTo64.png" +mask_shadow_texture_large = "shaders/crt-royale/TileableLinearShadowMaskEDP.png" +mask_grille_texture_small_wrap_mode = "repeat" +mask_grille_texture_large_wrap_mode = "repeat" +mask_slot_texture_small_wrap_mode = "repeat" +mask_slot_texture_large_wrap_mode = "repeat" +mask_shadow_texture_small_wrap_mode = "repeat" +mask_shadow_texture_large_wrap_mode = "repeat" +mask_grille_texture_small_linear = "true" +mask_grille_texture_large_linear = "true" +mask_slot_texture_small_linear = "true" +mask_slot_texture_large_linear = "true" +mask_shadow_texture_small_linear = "true" +mask_shadow_texture_large_linear = "true" +mask_grille_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_grille_texture_large_mipmap = "true" # Essential for hardware-resized masks +mask_slot_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_slot_texture_large_mipmap = "true" # Essential for hardware-resized masks +mask_shadow_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_shadow_texture_large_mipmap = "true" # Essential for hardware-resized masks + + +# Pass2: Linearize the input based on CRT gamma and bob interlaced fields. +# (Bobbing ensures we can immediately blur without getting artifacts.) +shader2 = "shaders/crt-royale/src/crt-royale-first-pass-linearize-crt-gamma-bob-fields.slang" +alias2 = "ORIG_LINEARIZED" +filter_linear2 = "false" +scale_type2 = "source" +scale2 = "1.0" +srgb_framebuffer2 = "true" + +# Pass3: Resample interlaced (and misconverged) scanlines vertically. +# Separating vertical/horizontal scanline sampling is faster: It lets us +# consider more scanlines while calculating weights for fewer pixels, and +# it reduces our samples from vertical*horizontal to vertical+horizontal. +# This has to come right after ORIG_LINEARIZED, because there's no +# "original_source" scale_type we can use later. +shader3 = "shaders/crt-royale/src/crt-royale-scanlines-vertical-interlacing.slang" +alias3 = "VERTICAL_SCANLINES" +filter_linear3 = "true" +scale_type_x3 = "source" +scale_x3 = "1.0" +scale_type_y3 = "viewport" +scale_y3 = "1.0" +#float_framebuffer3 = "true" +srgb_framebuffer3 = "true" + +# Pass4: Do a small resize blur of ORIG_LINEARIZED at an absolute size, and +# account for convergence offsets. We want to blur a predictable portion of the +# screen to match the phosphor bloom, and absolute scale works best for +# reliable results with a fixed-size bloom. Picking a scale is tricky: +# a.) 400x300 is a good compromise for the "fake-bloom" version: It's low enough +# to blur high-res/interlaced sources but high enough that resampling +# doesn't smear low-res sources too much. +# b.) 320x240 works well for the "real bloom" version: It's 1-1.5% faster, and +# the only noticeable visual difference is a larger halation spread (which +# may be a good thing for people who like to crank it up). +# Note the 4:3 aspect ratio assumes the input has cropped geom_overscan (so it's +# *intended* for an ~4:3 aspect ratio). +shader4 = "shaders/crt-royale/src/crt-royale-bloom-approx.slang" +alias4 = "BLOOM_APPROX" +filter_linear4 = "true" +scale_type4 = "absolute" +scale_x4 = "320" +scale_y4 = "240" +srgb_framebuffer4 = "true" + +# Pass5: Vertically blur the input for halation and refractive diffusion. +# Base this on BLOOM_APPROX: This blur should be small and fast, and blurring +# a constant portion of the screen is probably physically correct if the +# viewport resolution is proportional to the simulated CRT size. +shader5 = "../blurs/blur9fast-vertical.slang" +filter_linear5 = "true" +scale_type5 = "source" +scale5 = "1.0" +srgb_framebuffer5 = "true" + +# Pass6: Horizontally blur the input for halation and refractive diffusion. +# Note: Using a one-pass 9x9 blur is about 1% slower. +shader6 = "../blurs/blur9fast-horizontal.slang" +alias6 = "HALATION_BLUR" +filter_linear6 = "true" +scale_type6 = "source" +scale6 = "1.0" +srgb_framebuffer6 = "true" + +# Pass7: Lanczos-resize the phosphor mask vertically. Set the absolute +# scale_x7 == mask_texture_small_size.x (see IMPORTANT above). Larger scales +# will blur, and smaller scales could get nasty. The vertical size must be +# based on the viewport size and calculated carefully to avoid artifacts later. +# First calculate the minimum number of mask tiles we need to draw. +# Since curvature is computed after the scanline masking pass: +# num_resized_mask_tiles = 2.0; +# If curvature were computed in the scanline masking pass (it's not): +# max_mask_texel_border = ~3.0 * (1/3.0 + 4.0*sqrt(2.0) + 0.5 + 1.0); +# max_mask_tile_border = max_mask_texel_border/ +# (min_resized_phosphor_triad_size * mask_triads_per_tile); +# num_resized_mask_tiles = max(2.0, 1.0 + max_mask_tile_border * 2.0); +# At typical values (triad_size >= 2.0, mask_triads_per_tile == 8): +# num_resized_mask_tiles = ~3.8 +# Triad sizes are given in horizontal terms, so we need geom_max_aspect_ratio +# to relate them to vertical resolution. The widest we expect is: +# geom_max_aspect_ratio = 4.0/3.0 # Note: Shader passes need to know this! +# The fewer triads we tile across the screen, the larger each triad will be as a +# fraction of the viewport size, and the larger scale_y5 must be to draw a full +# num_resized_mask_tiles. Therefore, we must decide the smallest number of +# triads we'll guarantee can be displayed on screen. We'll set this according +# to 3-pixel triads at 768p resolution (the lowest anyone's likely to use): +# min_allowed_viewport_triads = 768.0*geom_max_aspect_ratio / 3.0 = 341.333333 +# Now calculate the viewport scale that ensures we can draw resized_mask_tiles: +# min_scale_x = resized_mask_tiles * mask_triads_per_tile / +# min_allowed_viewport_triads +# scale_y7 = geom_max_aspect_ratio * min_scale_x +# # Some code might depend on equal scales: +# scale_x8 = scale_y7 +# Given our default geom_max_aspect_ratio and min_allowed_viewport_triads: +# scale_y7 = 4.0/3.0 * 2.0/(341.33333 / 8.0) = 0.0625 +# IMPORTANT: The scales MUST be calculated in this way. If you wish to change +# geom_max_aspect_ratio, update that constant in user-cgp-constants.h! +shader7 = "shaders/crt-royale/src/crt-royale-mask-resize-vertical.slang" +filter_linear7 = "true" +scale_type_x7 = "absolute" +scale_x7 = "64" +scale_type_y7 = "viewport" +scale_y7 = "0.0625" # Safe for >= 341.333 horizontal triads at viewport size +#srgb_framebuffer7 = "false" # mask_texture is already assumed linear + +# Pass8: Lanczos-resize the phosphor mask horizontally. scale_x8 = scale_y7. +# TODO: Check again if the shaders actually require equal scales. +shader8 = "shaders/crt-royale/src/crt-royale-mask-resize-horizontal.slang" +alias8 = "MASK_RESIZE" +filter_linear8 = "false" +scale_type_x8 = "viewport" +scale_x8 = "0.0625" +scale_type_y8 = "source" +scale_y8 = "1.0" +#srgb_framebuffer8 = "false" # mask_texture is already assumed linear + +# Pass9: Resample (misconverged) scanlines horizontally, apply halation, and +# apply the phosphor mask. +shader9 = "shaders/crt-royale/src/crt-royale-scanlines-horizontal-apply-mask.slang" +alias9 = "MASKED_SCANLINES" +filter_linear9 = "true" # This could just as easily be nearest neighbor. +scale_type9 = "viewport" +scale9 = "1.0" +#float_framebuffer9 = "true" +srgb_framebuffer9 = "true" + +# Pass 10: Compute a brightpass. This will require reading the final mask. +shader10 = "shaders/crt-royale/src/crt-royale-brightpass.slang" +alias10 = "BRIGHTPASS" +filter_linear10 = "true" # This could just as easily be nearest neighbor. +scale_type10 = "viewport" +scale10 = "1.0" +srgb_framebuffer10 = "true" + +# Pass 11: Blur the brightpass vertically +shader11 = "shaders/crt-royale/src/crt-royale-bloom-vertical.slang" +filter_linear11 = "true" # This could just as easily be nearest neighbor. +scale_type11 = "source" +scale11 = "1.0" +srgb_framebuffer11 = "true" + +# Pass 12: Blur the brightpass horizontally and combine it with the dimpass: +shader12 = "shaders/crt-royale/src/crt-royale-bloom-horizontal-reconstitute.slang" +filter_linear12 = "true" +scale_type12 = "source" +scale12 = "1.0" +srgb_framebuffer12 = "true" + +# Pass 13: Compute curvature/AA: +shader13 = "shaders/crt-royale/src/crt-royale-geometry-aa-last-pass.slang" +filter_linear13 = "true" +scale_type13 = "viewport" +mipmap_input13 = "true" +texture_wrap_mode13 = "clamp_to_edge" + diff --git a/crt/crt-royale-ntsc-256px-svideo.slangp b/crt/crt-royale-ntsc-256px-svideo.slangp new file mode 100644 index 0000000..51678d8 --- /dev/null +++ b/crt/crt-royale-ntsc-256px-svideo.slangp @@ -0,0 +1,224 @@ +# IMPORTANT: +# Shader passes need to know details about the image in the mask_texture LUT +# files, so set the following constants in user-cgp-constants.h accordingly: +# 1.) mask_triads_per_tile = (number of horizontal triads in mask texture LUT's) +# 2.) mask_texture_small_size = (texture size of mask*texture_small LUT's) +# 3.) mask_texture_large_size = (texture size of mask*texture_large LUT's) +# 4.) mask_grille_avg_color = (avg. brightness of mask_grille_texture* LUT's, in [0, 1]) +# 5.) mask_slot_avg_color = (avg. brightness of mask_slot_texture* LUT's, in [0, 1]) +# 6.) mask_shadow_avg_color = (avg. brightness of mask_shadow_texture* LUT's, in [0, 1]) +# Shader passes also need to know certain scales set in this .slangp, but their +# compilation model doesn't currently allow the .slangp file to tell them. Make +# sure to set the following constants in user-cgp-constants.h accordingly too: +# 1.) bloom_approx_scale_x = scale_x2 +# 2.) mask_resize_viewport_scale = float2(scale_x6, scale_y5) +# Finally, shader passes need to know the value of geom_max_aspect_ratio used to +# calculate scale_y5 (among other values): +# 1.) geom_max_aspect_ratio = (geom_max_aspect_ratio used to calculate scale_y5) + +shaders = "14" + +# NTSC Shader Passes +shader0 = "../ntsc/shaders/ntsc-pass1-svideo-3phase.slang" +shader1 = "../ntsc/shaders/ntsc-pass2-3phase.slang" + +filter_linear0 = false +filter_linear1 = false + +scale_type_x0 = absolute +scale_type_y0 = source +scale_x0 = 1536 +scale_y0 = 1.0 +frame_count_mod0 = 2 +float_framebuffer0 = true + +scale_type1 = source +scale_x1 = 0.5 +scale_y1 = 1.0 + +# Set an identifier, filename, and sampling traits for the phosphor mask texture. +# Load an aperture grille, slot mask, and an EDP shadow mask, and load a small +# non-mipmapped version and a large mipmapped version. +# TODO: Test masks in other directories. +textures = "mask_grille_texture_small;mask_grille_texture_large;mask_slot_texture_small;mask_slot_texture_large;mask_shadow_texture_small;mask_shadow_texture_large" +mask_grille_texture_small = "shaders/crt-royale/TileableLinearApertureGrille15Wide8And5d5SpacingResizeTo64.png" +mask_grille_texture_large = "shaders/crt-royale/TileableLinearApertureGrille15Wide8And5d5Spacing.png" +mask_slot_texture_small = "shaders/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacingResizeTo64.png" +mask_slot_texture_large = "shaders/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing.png" +mask_shadow_texture_small = "shaders/crt-royale/TileableLinearShadowMaskEDPResizeTo64.png" +mask_shadow_texture_large = "shaders/crt-royale/TileableLinearShadowMaskEDP.png" +mask_grille_texture_small_wrap_mode = "repeat" +mask_grille_texture_large_wrap_mode = "repeat" +mask_slot_texture_small_wrap_mode = "repeat" +mask_slot_texture_large_wrap_mode = "repeat" +mask_shadow_texture_small_wrap_mode = "repeat" +mask_shadow_texture_large_wrap_mode = "repeat" +mask_grille_texture_small_linear = "true" +mask_grille_texture_large_linear = "true" +mask_slot_texture_small_linear = "true" +mask_slot_texture_large_linear = "true" +mask_shadow_texture_small_linear = "true" +mask_shadow_texture_large_linear = "true" +mask_grille_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_grille_texture_large_mipmap = "true" # Essential for hardware-resized masks +mask_slot_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_slot_texture_large_mipmap = "true" # Essential for hardware-resized masks +mask_shadow_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_shadow_texture_large_mipmap = "true" # Essential for hardware-resized masks + + +# Pass2: Linearize the input based on CRT gamma and bob interlaced fields. +# (Bobbing ensures we can immediately blur without getting artifacts.) +shader2 = "shaders/crt-royale/src/crt-royale-first-pass-linearize-crt-gamma-bob-fields.slang" +alias2 = "ORIG_LINEARIZED" +filter_linear2 = "false" +scale_type2 = "source" +scale2 = "1.0" +srgb_framebuffer2 = "true" + +# Pass3: Resample interlaced (and misconverged) scanlines vertically. +# Separating vertical/horizontal scanline sampling is faster: It lets us +# consider more scanlines while calculating weights for fewer pixels, and +# it reduces our samples from vertical*horizontal to vertical+horizontal. +# This has to come right after ORIG_LINEARIZED, because there's no +# "original_source" scale_type we can use later. +shader3 = "shaders/crt-royale/src/crt-royale-scanlines-vertical-interlacing.slang" +alias3 = "VERTICAL_SCANLINES" +filter_linear3 = "true" +scale_type_x3 = "source" +scale_x3 = "1.0" +scale_type_y3 = "viewport" +scale_y3 = "1.0" +#float_framebuffer3 = "true" +srgb_framebuffer3 = "true" + +# Pass4: Do a small resize blur of ORIG_LINEARIZED at an absolute size, and +# account for convergence offsets. We want to blur a predictable portion of the +# screen to match the phosphor bloom, and absolute scale works best for +# reliable results with a fixed-size bloom. Picking a scale is tricky: +# a.) 400x300 is a good compromise for the "fake-bloom" version: It's low enough +# to blur high-res/interlaced sources but high enough that resampling +# doesn't smear low-res sources too much. +# b.) 320x240 works well for the "real bloom" version: It's 1-1.5% faster, and +# the only noticeable visual difference is a larger halation spread (which +# may be a good thing for people who like to crank it up). +# Note the 4:3 aspect ratio assumes the input has cropped geom_overscan (so it's +# *intended* for an ~4:3 aspect ratio). +shader4 = "shaders/crt-royale/src/crt-royale-bloom-approx.slang" +alias4 = "BLOOM_APPROX" +filter_linear4 = "true" +scale_type4 = "absolute" +scale_x4 = "320" +scale_y4 = "240" +srgb_framebuffer4 = "true" + +# Pass5: Vertically blur the input for halation and refractive diffusion. +# Base this on BLOOM_APPROX: This blur should be small and fast, and blurring +# a constant portion of the screen is probably physically correct if the +# viewport resolution is proportional to the simulated CRT size. +shader5 = "../blurs/blur9fast-vertical.slang" +filter_linear5 = "true" +scale_type5 = "source" +scale5 = "1.0" +srgb_framebuffer5 = "true" + +# Pass6: Horizontally blur the input for halation and refractive diffusion. +# Note: Using a one-pass 9x9 blur is about 1% slower. +shader6 = "../blurs/blur9fast-horizontal.slang" +alias6 = "HALATION_BLUR" +filter_linear6 = "true" +scale_type6 = "source" +scale6 = "1.0" +srgb_framebuffer6 = "true" + +# Pass7: Lanczos-resize the phosphor mask vertically. Set the absolute +# scale_x7 == mask_texture_small_size.x (see IMPORTANT above). Larger scales +# will blur, and smaller scales could get nasty. The vertical size must be +# based on the viewport size and calculated carefully to avoid artifacts later. +# First calculate the minimum number of mask tiles we need to draw. +# Since curvature is computed after the scanline masking pass: +# num_resized_mask_tiles = 2.0; +# If curvature were computed in the scanline masking pass (it's not): +# max_mask_texel_border = ~3.0 * (1/3.0 + 4.0*sqrt(2.0) + 0.5 + 1.0); +# max_mask_tile_border = max_mask_texel_border/ +# (min_resized_phosphor_triad_size * mask_triads_per_tile); +# num_resized_mask_tiles = max(2.0, 1.0 + max_mask_tile_border * 2.0); +# At typical values (triad_size >= 2.0, mask_triads_per_tile == 8): +# num_resized_mask_tiles = ~3.8 +# Triad sizes are given in horizontal terms, so we need geom_max_aspect_ratio +# to relate them to vertical resolution. The widest we expect is: +# geom_max_aspect_ratio = 4.0/3.0 # Note: Shader passes need to know this! +# The fewer triads we tile across the screen, the larger each triad will be as a +# fraction of the viewport size, and the larger scale_y5 must be to draw a full +# num_resized_mask_tiles. Therefore, we must decide the smallest number of +# triads we'll guarantee can be displayed on screen. We'll set this according +# to 3-pixel triads at 768p resolution (the lowest anyone's likely to use): +# min_allowed_viewport_triads = 768.0*geom_max_aspect_ratio / 3.0 = 341.333333 +# Now calculate the viewport scale that ensures we can draw resized_mask_tiles: +# min_scale_x = resized_mask_tiles * mask_triads_per_tile / +# min_allowed_viewport_triads +# scale_y7 = geom_max_aspect_ratio * min_scale_x +# # Some code might depend on equal scales: +# scale_x8 = scale_y7 +# Given our default geom_max_aspect_ratio and min_allowed_viewport_triads: +# scale_y7 = 4.0/3.0 * 2.0/(341.33333 / 8.0) = 0.0625 +# IMPORTANT: The scales MUST be calculated in this way. If you wish to change +# geom_max_aspect_ratio, update that constant in user-cgp-constants.h! +shader7 = "shaders/crt-royale/src/crt-royale-mask-resize-vertical.slang" +filter_linear7 = "true" +scale_type_x7 = "absolute" +scale_x7 = "64" +scale_type_y7 = "viewport" +scale_y7 = "0.0625" # Safe for >= 341.333 horizontal triads at viewport size +#srgb_framebuffer7 = "false" # mask_texture is already assumed linear + +# Pass8: Lanczos-resize the phosphor mask horizontally. scale_x8 = scale_y7. +# TODO: Check again if the shaders actually require equal scales. +shader8 = "shaders/crt-royale/src/crt-royale-mask-resize-horizontal.slang" +alias8 = "MASK_RESIZE" +filter_linear8 = "false" +scale_type_x8 = "viewport" +scale_x8 = "0.0625" +scale_type_y8 = "source" +scale_y8 = "1.0" +#srgb_framebuffer8 = "false" # mask_texture is already assumed linear + +# Pass9: Resample (misconverged) scanlines horizontally, apply halation, and +# apply the phosphor mask. +shader9 = "shaders/crt-royale/src/crt-royale-scanlines-horizontal-apply-mask.slang" +alias9 = "MASKED_SCANLINES" +filter_linear9 = "true" # This could just as easily be nearest neighbor. +scale_type9 = "viewport" +scale9 = "1.0" +#float_framebuffer9 = "true" +srgb_framebuffer9 = "true" + +# Pass 10: Compute a brightpass. This will require reading the final mask. +shader10 = "shaders/crt-royale/src/crt-royale-brightpass.slang" +alias10 = "BRIGHTPASS" +filter_linear10 = "true" # This could just as easily be nearest neighbor. +scale_type10 = "viewport" +scale10 = "1.0" +srgb_framebuffer10 = "true" + +# Pass 11: Blur the brightpass vertically +shader11 = "shaders/crt-royale/src/crt-royale-bloom-vertical.slang" +filter_linear11 = "true" # This could just as easily be nearest neighbor. +scale_type11 = "source" +scale11 = "1.0" +srgb_framebuffer11 = "true" + +# Pass 12: Blur the brightpass horizontally and combine it with the dimpass: +shader12 = "shaders/crt-royale/src/crt-royale-bloom-horizontal-reconstitute.slang" +filter_linear12 = "true" +scale_type12 = "source" +scale12 = "1.0" +srgb_framebuffer12 = "true" + +# Pass 13: Compute curvature/AA: +shader13 = "shaders/crt-royale/src/crt-royale-geometry-aa-last-pass.slang" +filter_linear13 = "true" +scale_type13 = "viewport" +mipmap_input13 = "true" +texture_wrap_mode13 = "clamp_to_edge" + diff --git a/crt/crt-royale-ntsc-320px-composite.slangp b/crt/crt-royale-ntsc-320px-composite.slangp new file mode 100644 index 0000000..fa2fb02 --- /dev/null +++ b/crt/crt-royale-ntsc-320px-composite.slangp @@ -0,0 +1,224 @@ +# IMPORTANT: +# Shader passes need to know details about the image in the mask_texture LUT +# files, so set the following constants in user-cgp-constants.h accordingly: +# 1.) mask_triads_per_tile = (number of horizontal triads in mask texture LUT's) +# 2.) mask_texture_small_size = (texture size of mask*texture_small LUT's) +# 3.) mask_texture_large_size = (texture size of mask*texture_large LUT's) +# 4.) mask_grille_avg_color = (avg. brightness of mask_grille_texture* LUT's, in [0, 1]) +# 5.) mask_slot_avg_color = (avg. brightness of mask_slot_texture* LUT's, in [0, 1]) +# 6.) mask_shadow_avg_color = (avg. brightness of mask_shadow_texture* LUT's, in [0, 1]) +# Shader passes also need to know certain scales set in this .slangp, but their +# compilation model doesn't currently allow the .slangp file to tell them. Make +# sure to set the following constants in user-cgp-constants.h accordingly too: +# 1.) bloom_approx_scale_x = scale_x2 +# 2.) mask_resize_viewport_scale = float2(scale_x6, scale_y5) +# Finally, shader passes need to know the value of geom_max_aspect_ratio used to +# calculate scale_y5 (among other values): +# 1.) geom_max_aspect_ratio = (geom_max_aspect_ratio used to calculate scale_y5) + +shaders = "14" + +# NTSC Shader Passes +shader0 = "../ntsc/shaders/ntsc-pass1-composite-2phase.slang" +shader1 = "../ntsc/shaders/ntsc-pass2-2phase.slang" + +filter_linear0 = false +filter_linear1 = false + +scale_type_x0 = absolute +scale_type_y0 = source +scale_x0 = 1280 +scale_y0 = 1.0 +frame_count_mod0 = 2 +float_framebuffer0 = true + +scale_type1 = source +scale_x1 = 0.5 +scale_y1 = 1.0 + +# Set an identifier, filename, and sampling traits for the phosphor mask texture. +# Load an aperture grille, slot mask, and an EDP shadow mask, and load a small +# non-mipmapped version and a large mipmapped version. +# TODO: Test masks in other directories. +textures = "mask_grille_texture_small;mask_grille_texture_large;mask_slot_texture_small;mask_slot_texture_large;mask_shadow_texture_small;mask_shadow_texture_large" +mask_grille_texture_small = "shaders/crt-royale/TileableLinearApertureGrille15Wide8And5d5SpacingResizeTo64.png" +mask_grille_texture_large = "shaders/crt-royale/TileableLinearApertureGrille15Wide8And5d5Spacing.png" +mask_slot_texture_small = "shaders/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacingResizeTo64.png" +mask_slot_texture_large = "shaders/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing.png" +mask_shadow_texture_small = "shaders/crt-royale/TileableLinearShadowMaskEDPResizeTo64.png" +mask_shadow_texture_large = "shaders/crt-royale/TileableLinearShadowMaskEDP.png" +mask_grille_texture_small_wrap_mode = "repeat" +mask_grille_texture_large_wrap_mode = "repeat" +mask_slot_texture_small_wrap_mode = "repeat" +mask_slot_texture_large_wrap_mode = "repeat" +mask_shadow_texture_small_wrap_mode = "repeat" +mask_shadow_texture_large_wrap_mode = "repeat" +mask_grille_texture_small_linear = "true" +mask_grille_texture_large_linear = "true" +mask_slot_texture_small_linear = "true" +mask_slot_texture_large_linear = "true" +mask_shadow_texture_small_linear = "true" +mask_shadow_texture_large_linear = "true" +mask_grille_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_grille_texture_large_mipmap = "true" # Essential for hardware-resized masks +mask_slot_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_slot_texture_large_mipmap = "true" # Essential for hardware-resized masks +mask_shadow_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_shadow_texture_large_mipmap = "true" # Essential for hardware-resized masks + + +# Pass2: Linearize the input based on CRT gamma and bob interlaced fields. +# (Bobbing ensures we can immediately blur without getting artifacts.) +shader2 = "shaders/crt-royale/src/crt-royale-first-pass-linearize-crt-gamma-bob-fields.slang" +alias2 = "ORIG_LINEARIZED" +filter_linear2 = "false" +scale_type2 = "source" +scale2 = "1.0" +srgb_framebuffer2 = "true" + +# Pass3: Resample interlaced (and misconverged) scanlines vertically. +# Separating vertical/horizontal scanline sampling is faster: It lets us +# consider more scanlines while calculating weights for fewer pixels, and +# it reduces our samples from vertical*horizontal to vertical+horizontal. +# This has to come right after ORIG_LINEARIZED, because there's no +# "original_source" scale_type we can use later. +shader3 = "shaders/crt-royale/src/crt-royale-scanlines-vertical-interlacing.slang" +alias3 = "VERTICAL_SCANLINES" +filter_linear3 = "true" +scale_type_x3 = "source" +scale_x3 = "1.0" +scale_type_y3 = "viewport" +scale_y3 = "1.0" +#float_framebuffer3 = "true" +srgb_framebuffer3 = "true" + +# Pass4: Do a small resize blur of ORIG_LINEARIZED at an absolute size, and +# account for convergence offsets. We want to blur a predictable portion of the +# screen to match the phosphor bloom, and absolute scale works best for +# reliable results with a fixed-size bloom. Picking a scale is tricky: +# a.) 400x300 is a good compromise for the "fake-bloom" version: It's low enough +# to blur high-res/interlaced sources but high enough that resampling +# doesn't smear low-res sources too much. +# b.) 320x240 works well for the "real bloom" version: It's 1-1.5% faster, and +# the only noticeable visual difference is a larger halation spread (which +# may be a good thing for people who like to crank it up). +# Note the 4:3 aspect ratio assumes the input has cropped geom_overscan (so it's +# *intended* for an ~4:3 aspect ratio). +shader4 = "shaders/crt-royale/src/crt-royale-bloom-approx.slang" +alias4 = "BLOOM_APPROX" +filter_linear4 = "true" +scale_type4 = "absolute" +scale_x4 = "320" +scale_y4 = "240" +srgb_framebuffer4 = "true" + +# Pass5: Vertically blur the input for halation and refractive diffusion. +# Base this on BLOOM_APPROX: This blur should be small and fast, and blurring +# a constant portion of the screen is probably physically correct if the +# viewport resolution is proportional to the simulated CRT size. +shader5 = "../blurs/blur9fast-vertical.slang" +filter_linear5 = "true" +scale_type5 = "source" +scale5 = "1.0" +srgb_framebuffer5 = "true" + +# Pass6: Horizontally blur the input for halation and refractive diffusion. +# Note: Using a one-pass 9x9 blur is about 1% slower. +shader6 = "../blurs/blur9fast-horizontal.slang" +alias6 = "HALATION_BLUR" +filter_linear6 = "true" +scale_type6 = "source" +scale6 = "1.0" +srgb_framebuffer6 = "true" + +# Pass7: Lanczos-resize the phosphor mask vertically. Set the absolute +# scale_x7 == mask_texture_small_size.x (see IMPORTANT above). Larger scales +# will blur, and smaller scales could get nasty. The vertical size must be +# based on the viewport size and calculated carefully to avoid artifacts later. +# First calculate the minimum number of mask tiles we need to draw. +# Since curvature is computed after the scanline masking pass: +# num_resized_mask_tiles = 2.0; +# If curvature were computed in the scanline masking pass (it's not): +# max_mask_texel_border = ~3.0 * (1/3.0 + 4.0*sqrt(2.0) + 0.5 + 1.0); +# max_mask_tile_border = max_mask_texel_border/ +# (min_resized_phosphor_triad_size * mask_triads_per_tile); +# num_resized_mask_tiles = max(2.0, 1.0 + max_mask_tile_border * 2.0); +# At typical values (triad_size >= 2.0, mask_triads_per_tile == 8): +# num_resized_mask_tiles = ~3.8 +# Triad sizes are given in horizontal terms, so we need geom_max_aspect_ratio +# to relate them to vertical resolution. The widest we expect is: +# geom_max_aspect_ratio = 4.0/3.0 # Note: Shader passes need to know this! +# The fewer triads we tile across the screen, the larger each triad will be as a +# fraction of the viewport size, and the larger scale_y5 must be to draw a full +# num_resized_mask_tiles. Therefore, we must decide the smallest number of +# triads we'll guarantee can be displayed on screen. We'll set this according +# to 3-pixel triads at 768p resolution (the lowest anyone's likely to use): +# min_allowed_viewport_triads = 768.0*geom_max_aspect_ratio / 3.0 = 341.333333 +# Now calculate the viewport scale that ensures we can draw resized_mask_tiles: +# min_scale_x = resized_mask_tiles * mask_triads_per_tile / +# min_allowed_viewport_triads +# scale_y7 = geom_max_aspect_ratio * min_scale_x +# # Some code might depend on equal scales: +# scale_x8 = scale_y7 +# Given our default geom_max_aspect_ratio and min_allowed_viewport_triads: +# scale_y7 = 4.0/3.0 * 2.0/(341.33333 / 8.0) = 0.0625 +# IMPORTANT: The scales MUST be calculated in this way. If you wish to change +# geom_max_aspect_ratio, update that constant in user-cgp-constants.h! +shader7 = "shaders/crt-royale/src/crt-royale-mask-resize-vertical.slang" +filter_linear7 = "true" +scale_type_x7 = "absolute" +scale_x7 = "64" +scale_type_y7 = "viewport" +scale_y7 = "0.0625" # Safe for >= 341.333 horizontal triads at viewport size +#srgb_framebuffer7 = "false" # mask_texture is already assumed linear + +# Pass8: Lanczos-resize the phosphor mask horizontally. scale_x8 = scale_y7. +# TODO: Check again if the shaders actually require equal scales. +shader8 = "shaders/crt-royale/src/crt-royale-mask-resize-horizontal.slang" +alias8 = "MASK_RESIZE" +filter_linear8 = "false" +scale_type_x8 = "viewport" +scale_x8 = "0.0625" +scale_type_y8 = "source" +scale_y8 = "1.0" +#srgb_framebuffer8 = "false" # mask_texture is already assumed linear + +# Pass9: Resample (misconverged) scanlines horizontally, apply halation, and +# apply the phosphor mask. +shader9 = "shaders/crt-royale/src/crt-royale-scanlines-horizontal-apply-mask.slang" +alias9 = "MASKED_SCANLINES" +filter_linear9 = "true" # This could just as easily be nearest neighbor. +scale_type9 = "viewport" +scale9 = "1.0" +#float_framebuffer9 = "true" +srgb_framebuffer9 = "true" + +# Pass 10: Compute a brightpass. This will require reading the final mask. +shader10 = "shaders/crt-royale/src/crt-royale-brightpass.slang" +alias10 = "BRIGHTPASS" +filter_linear10 = "true" # This could just as easily be nearest neighbor. +scale_type10 = "viewport" +scale10 = "1.0" +srgb_framebuffer10 = "true" + +# Pass 11: Blur the brightpass vertically +shader11 = "shaders/crt-royale/src/crt-royale-bloom-vertical.slang" +filter_linear11 = "true" # This could just as easily be nearest neighbor. +scale_type11 = "source" +scale11 = "1.0" +srgb_framebuffer11 = "true" + +# Pass 12: Blur the brightpass horizontally and combine it with the dimpass: +shader12 = "shaders/crt-royale/src/crt-royale-bloom-horizontal-reconstitute.slang" +filter_linear12 = "true" +scale_type12 = "source" +scale12 = "1.0" +srgb_framebuffer12 = "true" + +# Pass 13: Compute curvature/AA: +shader13 = "shaders/crt-royale/src/crt-royale-geometry-aa-last-pass.slang" +filter_linear13 = "true" +scale_type13 = "viewport" +mipmap_input13 = "true" +texture_wrap_mode13 = "clamp_to_edge" + diff --git a/crt/crt-royale-ntsc-320px-svideo.slangp b/crt/crt-royale-ntsc-320px-svideo.slangp new file mode 100644 index 0000000..c7b3ae1 --- /dev/null +++ b/crt/crt-royale-ntsc-320px-svideo.slangp @@ -0,0 +1,224 @@ +# IMPORTANT: +# Shader passes need to know details about the image in the mask_texture LUT +# files, so set the following constants in user-cgp-constants.h accordingly: +# 1.) mask_triads_per_tile = (number of horizontal triads in mask texture LUT's) +# 2.) mask_texture_small_size = (texture size of mask*texture_small LUT's) +# 3.) mask_texture_large_size = (texture size of mask*texture_large LUT's) +# 4.) mask_grille_avg_color = (avg. brightness of mask_grille_texture* LUT's, in [0, 1]) +# 5.) mask_slot_avg_color = (avg. brightness of mask_slot_texture* LUT's, in [0, 1]) +# 6.) mask_shadow_avg_color = (avg. brightness of mask_shadow_texture* LUT's, in [0, 1]) +# Shader passes also need to know certain scales set in this .slangp, but their +# compilation model doesn't currently allow the .slangp file to tell them. Make +# sure to set the following constants in user-cgp-constants.h accordingly too: +# 1.) bloom_approx_scale_x = scale_x2 +# 2.) mask_resize_viewport_scale = float2(scale_x6, scale_y5) +# Finally, shader passes need to know the value of geom_max_aspect_ratio used to +# calculate scale_y5 (among other values): +# 1.) geom_max_aspect_ratio = (geom_max_aspect_ratio used to calculate scale_y5) + +shaders = "14" + +# NTSC Shader Passes +shader0 = "../ntsc/shaders/ntsc-pass1-svideo-2phase.slang" +shader1 = "../ntsc/shaders/ntsc-pass2-2phase.slang" + +filter_linear0 = false +filter_linear1 = false + +scale_type_x0 = absolute +scale_type_y0 = source +scale_x0 = 1920 +scale_y0 = 1.0 +frame_count_mod0 = 2 +float_framebuffer0 = true + +scale_type1 = source +scale_x1 = 0.5 +scale_y1 = 1.0 + +# Set an identifier, filename, and sampling traits for the phosphor mask texture. +# Load an aperture grille, slot mask, and an EDP shadow mask, and load a small +# non-mipmapped version and a large mipmapped version. +# TODO: Test masks in other directories. +textures = "mask_grille_texture_small;mask_grille_texture_large;mask_slot_texture_small;mask_slot_texture_large;mask_shadow_texture_small;mask_shadow_texture_large" +mask_grille_texture_small = "shaders/crt-royale/TileableLinearApertureGrille15Wide8And5d5SpacingResizeTo64.png" +mask_grille_texture_large = "shaders/crt-royale/TileableLinearApertureGrille15Wide8And5d5Spacing.png" +mask_slot_texture_small = "shaders/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacingResizeTo64.png" +mask_slot_texture_large = "shaders/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing.png" +mask_shadow_texture_small = "shaders/crt-royale/TileableLinearShadowMaskEDPResizeTo64.png" +mask_shadow_texture_large = "shaders/crt-royale/TileableLinearShadowMaskEDP.png" +mask_grille_texture_small_wrap_mode = "repeat" +mask_grille_texture_large_wrap_mode = "repeat" +mask_slot_texture_small_wrap_mode = "repeat" +mask_slot_texture_large_wrap_mode = "repeat" +mask_shadow_texture_small_wrap_mode = "repeat" +mask_shadow_texture_large_wrap_mode = "repeat" +mask_grille_texture_small_linear = "true" +mask_grille_texture_large_linear = "true" +mask_slot_texture_small_linear = "true" +mask_slot_texture_large_linear = "true" +mask_shadow_texture_small_linear = "true" +mask_shadow_texture_large_linear = "true" +mask_grille_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_grille_texture_large_mipmap = "true" # Essential for hardware-resized masks +mask_slot_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_slot_texture_large_mipmap = "true" # Essential for hardware-resized masks +mask_shadow_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_shadow_texture_large_mipmap = "true" # Essential for hardware-resized masks + + +# Pass2: Linearize the input based on CRT gamma and bob interlaced fields. +# (Bobbing ensures we can immediately blur without getting artifacts.) +shader2 = "shaders/crt-royale/src/crt-royale-first-pass-linearize-crt-gamma-bob-fields.slang" +alias2 = "ORIG_LINEARIZED" +filter_linear2 = "false" +scale_type2 = "source" +scale2 = "1.0" +srgb_framebuffer2 = "true" + +# Pass3: Resample interlaced (and misconverged) scanlines vertically. +# Separating vertical/horizontal scanline sampling is faster: It lets us +# consider more scanlines while calculating weights for fewer pixels, and +# it reduces our samples from vertical*horizontal to vertical+horizontal. +# This has to come right after ORIG_LINEARIZED, because there's no +# "original_source" scale_type we can use later. +shader3 = "shaders/crt-royale/src/crt-royale-scanlines-vertical-interlacing.slang" +alias3 = "VERTICAL_SCANLINES" +filter_linear3 = "true" +scale_type_x3 = "source" +scale_x3 = "1.0" +scale_type_y3 = "viewport" +scale_y3 = "1.0" +#float_framebuffer3 = "true" +srgb_framebuffer3 = "true" + +# Pass4: Do a small resize blur of ORIG_LINEARIZED at an absolute size, and +# account for convergence offsets. We want to blur a predictable portion of the +# screen to match the phosphor bloom, and absolute scale works best for +# reliable results with a fixed-size bloom. Picking a scale is tricky: +# a.) 400x300 is a good compromise for the "fake-bloom" version: It's low enough +# to blur high-res/interlaced sources but high enough that resampling +# doesn't smear low-res sources too much. +# b.) 320x240 works well for the "real bloom" version: It's 1-1.5% faster, and +# the only noticeable visual difference is a larger halation spread (which +# may be a good thing for people who like to crank it up). +# Note the 4:3 aspect ratio assumes the input has cropped geom_overscan (so it's +# *intended* for an ~4:3 aspect ratio). +shader4 = "shaders/crt-royale/src/crt-royale-bloom-approx.slang" +alias4 = "BLOOM_APPROX" +filter_linear4 = "true" +scale_type4 = "absolute" +scale_x4 = "320" +scale_y4 = "240" +srgb_framebuffer4 = "true" + +# Pass5: Vertically blur the input for halation and refractive diffusion. +# Base this on BLOOM_APPROX: This blur should be small and fast, and blurring +# a constant portion of the screen is probably physically correct if the +# viewport resolution is proportional to the simulated CRT size. +shader5 = "../blurs/blur9fast-vertical.slang" +filter_linear5 = "true" +scale_type5 = "source" +scale5 = "1.0" +srgb_framebuffer5 = "true" + +# Pass6: Horizontally blur the input for halation and refractive diffusion. +# Note: Using a one-pass 9x9 blur is about 1% slower. +shader6 = "../blurs/blur9fast-horizontal.slang" +alias6 = "HALATION_BLUR" +filter_linear6 = "true" +scale_type6 = "source" +scale6 = "1.0" +srgb_framebuffer6 = "true" + +# Pass7: Lanczos-resize the phosphor mask vertically. Set the absolute +# scale_x7 == mask_texture_small_size.x (see IMPORTANT above). Larger scales +# will blur, and smaller scales could get nasty. The vertical size must be +# based on the viewport size and calculated carefully to avoid artifacts later. +# First calculate the minimum number of mask tiles we need to draw. +# Since curvature is computed after the scanline masking pass: +# num_resized_mask_tiles = 2.0; +# If curvature were computed in the scanline masking pass (it's not): +# max_mask_texel_border = ~3.0 * (1/3.0 + 4.0*sqrt(2.0) + 0.5 + 1.0); +# max_mask_tile_border = max_mask_texel_border/ +# (min_resized_phosphor_triad_size * mask_triads_per_tile); +# num_resized_mask_tiles = max(2.0, 1.0 + max_mask_tile_border * 2.0); +# At typical values (triad_size >= 2.0, mask_triads_per_tile == 8): +# num_resized_mask_tiles = ~3.8 +# Triad sizes are given in horizontal terms, so we need geom_max_aspect_ratio +# to relate them to vertical resolution. The widest we expect is: +# geom_max_aspect_ratio = 4.0/3.0 # Note: Shader passes need to know this! +# The fewer triads we tile across the screen, the larger each triad will be as a +# fraction of the viewport size, and the larger scale_y5 must be to draw a full +# num_resized_mask_tiles. Therefore, we must decide the smallest number of +# triads we'll guarantee can be displayed on screen. We'll set this according +# to 3-pixel triads at 768p resolution (the lowest anyone's likely to use): +# min_allowed_viewport_triads = 768.0*geom_max_aspect_ratio / 3.0 = 341.333333 +# Now calculate the viewport scale that ensures we can draw resized_mask_tiles: +# min_scale_x = resized_mask_tiles * mask_triads_per_tile / +# min_allowed_viewport_triads +# scale_y7 = geom_max_aspect_ratio * min_scale_x +# # Some code might depend on equal scales: +# scale_x8 = scale_y7 +# Given our default geom_max_aspect_ratio and min_allowed_viewport_triads: +# scale_y7 = 4.0/3.0 * 2.0/(341.33333 / 8.0) = 0.0625 +# IMPORTANT: The scales MUST be calculated in this way. If you wish to change +# geom_max_aspect_ratio, update that constant in user-cgp-constants.h! +shader7 = "shaders/crt-royale/src/crt-royale-mask-resize-vertical.slang" +filter_linear7 = "true" +scale_type_x7 = "absolute" +scale_x7 = "64" +scale_type_y7 = "viewport" +scale_y7 = "0.0625" # Safe for >= 341.333 horizontal triads at viewport size +#srgb_framebuffer7 = "false" # mask_texture is already assumed linear + +# Pass8: Lanczos-resize the phosphor mask horizontally. scale_x8 = scale_y7. +# TODO: Check again if the shaders actually require equal scales. +shader8 = "shaders/crt-royale/src/crt-royale-mask-resize-horizontal.slang" +alias8 = "MASK_RESIZE" +filter_linear8 = "false" +scale_type_x8 = "viewport" +scale_x8 = "0.0625" +scale_type_y8 = "source" +scale_y8 = "1.0" +#srgb_framebuffer8 = "false" # mask_texture is already assumed linear + +# Pass9: Resample (misconverged) scanlines horizontally, apply halation, and +# apply the phosphor mask. +shader9 = "shaders/crt-royale/src/crt-royale-scanlines-horizontal-apply-mask.slang" +alias9 = "MASKED_SCANLINES" +filter_linear9 = "true" # This could just as easily be nearest neighbor. +scale_type9 = "viewport" +scale9 = "1.0" +#float_framebuffer9 = "true" +srgb_framebuffer9 = "true" + +# Pass 10: Compute a brightpass. This will require reading the final mask. +shader10 = "shaders/crt-royale/src/crt-royale-brightpass.slang" +alias10 = "BRIGHTPASS" +filter_linear10 = "true" # This could just as easily be nearest neighbor. +scale_type10 = "viewport" +scale10 = "1.0" +srgb_framebuffer10 = "true" + +# Pass 11: Blur the brightpass vertically +shader11 = "shaders/crt-royale/src/crt-royale-bloom-vertical.slang" +filter_linear11 = "true" # This could just as easily be nearest neighbor. +scale_type11 = "source" +scale11 = "1.0" +srgb_framebuffer11 = "true" + +# Pass 12: Blur the brightpass horizontally and combine it with the dimpass: +shader12 = "shaders/crt-royale/src/crt-royale-bloom-horizontal-reconstitute.slang" +filter_linear12 = "true" +scale_type12 = "source" +scale12 = "1.0" +srgb_framebuffer12 = "true" + +# Pass 13: Compute curvature/AA: +shader13 = "shaders/crt-royale/src/crt-royale-geometry-aa-last-pass.slang" +filter_linear13 = "true" +scale_type13 = "viewport" +mipmap_input13 = "true" +texture_wrap_mode13 = "clamp_to_edge" + diff --git a/crt/crt-royale-pal-r57shell.slangp b/crt/crt-royale-pal-r57shell.slangp new file mode 100644 index 0000000..b5b762b --- /dev/null +++ b/crt/crt-royale-pal-r57shell.slangp @@ -0,0 +1,219 @@ +# IMPORTANT: +# Shader passes need to know details about the image in the mask_texture LUT +# files, so set the following constants in user-cgp-constants.h accordingly: +# 1.) mask_triads_per_tile = (number of horizontal triads in mask texture LUT's) +# 2.) mask_texture_small_size = (texture size of mask*texture_small LUT's) +# 3.) mask_texture_large_size = (texture size of mask*texture_large LUT's) +# 4.) mask_grille_avg_color = (avg. brightness of mask_grille_texture* LUT's, in [0, 1]) +# 5.) mask_slot_avg_color = (avg. brightness of mask_slot_texture* LUT's, in [0, 1]) +# 6.) mask_shadow_avg_color = (avg. brightness of mask_shadow_texture* LUT's, in [0, 1]) +# Shader passes also need to know certain scales set in this .slangp, but their +# compilation model doesn't currently allow the .slangp file to tell them. Make +# sure to set the following constants in user-cgp-constants.h accordingly too: +# 1.) bloom_approx_scale_x = scale_x3 +# 2.) mask_resize_viewport_scale = float2(scale_x7, scale_y6) +# Finally, shader passes need to know the value of geom_max_aspect_ratio used to +# calculate scale_y5 (among other values): +# 1.) geom_max_aspect_ratio = (geom_max_aspect_ratio used to calculate scale_y5) + +shaders = "13" + +shader0 = "../pal/shaders/pal-r57shell.slang" + +nes_lut = "../pal/resources/nes_lut.png" +nes_lut_linear = "false" +nes_lut_wrap_mode = "repeat" +nes_lut_mipmap = "false" + +filter_linear0 = false +scale_type_x0 = absolute +scale_type_y0 = source +scale_x0 = 1024 +scale_y0 = 1.0 +frame_count_mod0 = 2 + +# Set an identifier, filename, and sampling traits for the phosphor mask texture. +# Load an aperture grille, slot mask, and an EDP shadow mask, and load a small +# non-mipmapped version and a large mipmapped version. +# TODO: Test masks in other directories. +textures = "nes_lut;mask_grille_texture_small;mask_grille_texture_large;mask_slot_texture_small;mask_slot_texture_large;mask_shadow_texture_small;mask_shadow_texture_large" +mask_grille_texture_small = "shaders/crt-royale/TileableLinearApertureGrille15Wide8And5d5SpacingResizeTo64.png" +mask_grille_texture_large = "shaders/crt-royale/TileableLinearApertureGrille15Wide8And5d5Spacing.png" +mask_slot_texture_small = "shaders/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacingResizeTo64.png" +mask_slot_texture_large = "shaders/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing.png" +mask_shadow_texture_small = "shaders/crt-royale/TileableLinearShadowMaskEDPResizeTo64.png" +mask_shadow_texture_large = "shaders/crt-royale/TileableLinearShadowMaskEDP.png" +mask_grille_texture_small_wrap_mode = "repeat" +mask_grille_texture_large_wrap_mode = "repeat" +mask_slot_texture_small_wrap_mode = "repeat" +mask_slot_texture_large_wrap_mode = "repeat" +mask_shadow_texture_small_wrap_mode = "repeat" +mask_shadow_texture_large_wrap_mode = "repeat" +mask_grille_texture_small_linear = "true" +mask_grille_texture_large_linear = "true" +mask_slot_texture_small_linear = "true" +mask_slot_texture_large_linear = "true" +mask_shadow_texture_small_linear = "true" +mask_shadow_texture_large_linear = "true" +mask_grille_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_grille_texture_large_mipmap = "true" # Essential for hardware-resized masks +mask_slot_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_slot_texture_large_mipmap = "true" # Essential for hardware-resized masks +mask_shadow_texture_small_mipmap = "false" # Mipmapping causes artifacts with manually resized masks without tex2Dlod +mask_shadow_texture_large_mipmap = "true" # Essential for hardware-resized masks + + +# Pass1: Linearize the input based on CRT gamma and bob interlaced fields. +# (Bobbing ensures we can immediately blur without getting artifacts.) +shader1 = "shaders/crt-royale/src/crt-royale-first-pass-linearize-crt-gamma-bob-fields.slang" +alias1 = "ORIG_LINEARIZED" +filter_linear1 = "false" +scale_type1 = "source" +scale1 = "1.0" +srgb_framebuffer1 = "true" + +# Pass2: Resample interlaced (and misconverged) scanlines vertically. +# Separating vertical/horizontal scanline sampling is faster: It lets us +# consider more scanlines while calculating weights for fewer pixels, and +# it reduces our samples from vertical*horizontal to vertical+horizontal. +# This has to come right after ORIG_LINEARIZED, because there's no +# "original_source" scale_type we can use later. +shader2 = "shaders/crt-royale/src/crt-royale-scanlines-vertical-interlacing.slang" +alias2 = "VERTICAL_SCANLINES" +filter_linear2 = "true" +scale_type_x2 = "source" +scale_x2 = "1.0" +scale_type_y2 = "viewport" +scale_y2 = "1.0" +#float_framebuffer2 = "true" +srgb_framebuffer2 = "true" + +# Pass3: Do a small resize blur of ORIG_LINEARIZED at an absolute size, and +# account for convergence offsets. We want to blur a predictable portion of the +# screen to match the phosphor bloom, and absolute scale works best for +# reliable results with a fixed-size bloom. Picking a scale is tricky: +# a.) 400x300 is a good compromise for the "fake-bloom" version: It's low enough +# to blur high-res/interlaced sources but high enough that resampling +# doesn't smear low-res sources too much. +# b.) 320x240 works well for the "real bloom" version: It's 1-1.5% faster, and +# the only noticeable visual difference is a larger halation spread (which +# may be a good thing for people who like to crank it up). +# Note the 4:3 aspect ratio assumes the input has cropped geom_overscan (so it's +# *intended* for an ~4:3 aspect ratio). +shader3 = "shaders/crt-royale/src/crt-royale-bloom-approx.slang" +alias3 = "BLOOM_APPROX" +filter_linear3 = "true" +scale_type3 = "absolute" +scale_x3 = "320" +scale_y3 = "240" +srgb_framebuffer3 = "true" + +# Pass4: Vertically blur the input for halation and refractive diffusion. +# Base this on BLOOM_APPROX: This blur should be small and fast, and blurring +# a constant portion of the screen is probably physically correct if the +# viewport resolution is proportional to the simulated CRT size. +shader4 = "../blurs/blur9fast-vertical.slang" +filter_linear4 = "true" +scale_type4 = "source" +scale4 = "1.0" +srgb_framebuffer4 = "true" + +# Pass5: Horizontally blur the input for halation and refractive diffusion. +# Note: Using a one-pass 9x9 blur is about 1% slower. +shader5 = "../blurs/blur9fast-horizontal.slang" +alias5 = "HALATION_BLUR" +filter_linear5 = "true" +scale_type5 = "source" +scale5 = "1.0" +srgb_framebuffer5 = "true" + +# Pass6: Lanczos-resize the phosphor mask vertically. Set the absolute +# scale_x5 == mask_texture_small_size.x (see IMPORTANT above). Larger scales +# will blur, and smaller scales could get nasty. The vertical size must be +# based on the viewport size and calculated carefully to avoid artifacts later. +# First calculate the minimum number of mask tiles we need to draw. +# Since curvature is computed after the scanline masking pass: +# num_resized_mask_tiles = 2.0; +# If curvature were computed in the scanline masking pass (it's not): +# max_mask_texel_border = ~3.0 * (1/3.0 + 4.0*sqrt(2.0) + 0.5 + 1.0); +# max_mask_tile_border = max_mask_texel_border/ +# (min_resized_phosphor_triad_size * mask_triads_per_tile); +# num_resized_mask_tiles = max(2.0, 1.0 + max_mask_tile_border * 2.0); +# At typical values (triad_size >= 2.0, mask_triads_per_tile == 8): +# num_resized_mask_tiles = ~3.8 +# Triad sizes are given in horizontal terms, so we need geom_max_aspect_ratio +# to relate them to vertical resolution. The widest we expect is: +# geom_max_aspect_ratio = 4.0/3.0 # Note: Shader passes need to know this! +# The fewer triads we tile across the screen, the larger each triad will be as a +# fraction of the viewport size, and the larger scale_y5 must be to draw a full +# num_resized_mask_tiles. Therefore, we must decide the smallest number of +# triads we'll guarantee can be displayed on screen. We'll set this according +# to 3-pixel triads at 768p resolution (the lowest anyone's likely to use): +# min_allowed_viewport_triads = 768.0*geom_max_aspect_ratio / 3.0 = 341.333333 +# Now calculate the viewport scale that ensures we can draw resized_mask_tiles: +# min_scale_x = resized_mask_tiles * mask_triads_per_tile / +# min_allowed_viewport_triads +# scale_y6 = geom_max_aspect_ratio * min_scale_x +# # Some code might depend on equal scales: +# scale_x7 = scale_y6 +# Given our default geom_max_aspect_ratio and min_allowed_viewport_triads: +# scale_y6 = 4.0/3.0 * 2.0/(341.33333 / 8.0) = 0.0625 +# IMPORTANT: The scales MUST be calculated in this way. If you wish to change +# geom_max_aspect_ratio, update that constant in user-cgp-constants.h! +shader6 = "shaders/crt-royale/src/crt-royale-mask-resize-vertical.slang" +filter_linear6 = "true" +scale_type_x6 = "absolute" +scale_x6 = "64" +scale_type_y6 = "viewport" +scale_y6 = "0.0625" # Safe for >= 341.333 horizontal triads at viewport size +#srgb_framebuffer6 = "false" # mask_texture is already assumed linear + +# Pass7: Lanczos-resize the phosphor mask horizontally. scale_x7 = scale_y6. +# TODO: Check again if the shaders actually require equal scales. +shader7 = "shaders/crt-royale/src/crt-royale-mask-resize-horizontal.slang" +alias7 = "MASK_RESIZE" +filter_linear7 = "false" +scale_type_x7 = "viewport" +scale_x7 = "0.0625" +scale_type_y7 = "source" +scale_y7 = "1.0" +#srgb_framebuffer7 = "false" # mask_texture is already assumed linear + +# Pass8: Resample (misconverged) scanlines horizontally, apply halation, and +# apply the phosphor mask. +shader8 = "shaders/crt-royale/src/crt-royale-scanlines-horizontal-apply-mask.slang" +alias8 = "MASKED_SCANLINES" +filter_linear8 = "true" # This could just as easily be nearest neighbor. +scale_type8 = "viewport" +scale8 = "1.0" +#float_framebuffer8 = "true" +srgb_framebuffer8 = "true" + +# Pass 9: Compute a brightpass. This will require reading the final mask. +shader9 = "shaders/crt-royale/src/crt-royale-brightpass.slang" +alias9 = "BRIGHTPASS" +filter_linear9 = "true" # This could just as easily be nearest neighbor. +scale_type9 = "viewport" +scale9 = "1.0" +srgb_framebuffer9 = "true" + +# Pass 10: Blur the brightpass vertically +shader10 = "shaders/crt-royale/src/crt-royale-bloom-vertical.slang" +filter_linear10 = "true" # This could just as easily be nearest neighbor. +scale_type10 = "source" +scale10 = "1.0" +srgb_framebuffer10 = "true" + +# Pass 11: Blur the brightpass horizontally and combine it with the dimpass: +shader11 = "shaders/crt-royale/src/crt-royale-bloom-horizontal-reconstitute.slang" +filter_linear11 = "true" +scale_type11 = "source" +scale11 = "1.0" +srgb_framebuffer11 = "true" + +# Pass 12: Compute curvature/AA: +shader12 = "shaders/crt-royale/src/crt-royale-geometry-aa-last-pass.slang" +filter_linear12 = "true" +scale_type12 = "viewport" +mipmap_input12 = "true" +texture_wrap_mode12 = "clamp_to_edge" diff --git a/pal/pal-r57shell-multipass.slangp b/pal/pal-r57shell-multipass.slangp deleted file mode 100644 index 0791b65..0000000 --- a/pal/pal-r57shell-multipass.slangp +++ /dev/null @@ -1,11 +0,0 @@ -shaders = 2 - -shader0 = shaders/pal-r57shell-multipass0.slang -alias0 = Pass0 -scale_type0 = source -scale0 = 2.0 - -shader1 = shaders/pal-r57shell-multipass1.slang - -textures = "nes_lut" -nes_lut = resources/nes_lut.png \ No newline at end of file diff --git a/pal/pal-r57shell.slangp b/pal/pal-r57shell.slangp index 8cd3edb..8e6604d 100644 --- a/pal/pal-r57shell.slangp +++ b/pal/pal-r57shell.slangp @@ -1,6 +1,21 @@ shaders = 1 shader0 = shaders/pal-r57shell.slang +filter_linear0 = "false" +wrap_mode0 = "clamp_to_border" +mipmap_input0 = "false" +alias0 = "ORIG_LINEARIZED" +float_framebuffer0 = "false" +srgb_framebuffer0 = "0" +scale_type_x0 = "viewport" +scale_x0 = "1.000000" +scale_type_y0 = "source" +scale_y0 = "1.000000" +textures = "nes_lut" +nes_lut = "resources/nes_lut.png" +nes_lut_linear = "false" +nes_lut_wrap_mode = "repeat" +nes_lut_mipmap = "false" textures = "nes_lut" nes_lut = resources/nes_lut.png \ No newline at end of file diff --git a/pal/shaders/pal-r57shell-multipass0.slang b/pal/shaders/pal-r57shell-multipass0.slang deleted file mode 100644 index 39a156a..0000000 --- a/pal/shaders/pal-r57shell-multipass0.slang +++ /dev/null @@ -1,480 +0,0 @@ -#version 450 - -// NES PAL composite signal simulation for RetroArch -// shader by r57shell -// thanks to feos & HardWareMan & NewRisingSun - -// also TV subpixels and scanlines - -// LICENSE: PUBLIC DOMAIN - -// NOTE: for nice TV subpixels and scanlines I recommend to -// disable this features here and apply CRT-specialized shader. - -// Quality considerations - -// there are three main options: -// USE_RAW (R), USE_DELAY_LINE (D), USE_COLORIMETRY (C) -// here is table of quality in decreasing order: -// RDC, RD, RC, DC, D, C - -layout(push_constant) uniform Push -{ - vec4 SourceSize; - vec4 OriginalSize; - vec4 OutputSize; - uint FrameCount; - float Gamma; - float Brightness; - float Contrast; - float Saturation; - float HueShift; - float HueRotation; - float Ywidth; - float Uwidth; - float Vwidth; - float TV_Pixels; - float SizeX; - float SizeY; - float dark_scanline; - float Phase_Y; - float Phase_One; - float Phase_Two; -} params; - -#pragma parameter Gamma "PAL Gamma" 2.5 0.0 10.0 0.03125 -#pragma parameter Brightness "PAL Brightness" 0.0 -1.0 2.0 0.03125 -#pragma parameter Contrast "PAL Contrast" 1.0 -1.0 2.0 0.03125 -#pragma parameter Saturation "PAL Saturation" 1.0 -1.0 2.0 0.03125 -#pragma parameter HueShift "PAL Hue Shift" -2.5 -6.0 6.0 0.015625 -#pragma parameter HueRotation "PAL Hue Rotation" 2.0 -5.0 5.0 0.015625 -#pragma parameter Ywidth "PAL Y Width" 12.0 1.0 32.0 1.0 -#pragma parameter Uwidth "PAL U Width" 23.0 1.0 32.0 1.0 -#pragma parameter Vwidth "PAL V Width" 23.0 1.0 32.0 1.0 -#pragma parameter SizeX "Active Width" 256.0 1.0 4096.0 1.0 -#pragma parameter SizeY "Active Height" 240.0 1.0 4096.0 1.0 -#pragma parameter TV_Pixels "PAL TV Pixels" 200.0 1.0 2400.0 1.0 -#pragma parameter dark_scanline "PAL Scanline" 0.5 0.0 1.0 0.025 -#pragma parameter Phase_Y "PAL Phase Y" 2.0 0.0 12.0 0.025 -#pragma parameter Phase_One "PAL Phase One" 0.0 0.0 12.0 0.025 -#pragma parameter Phase_Two "PAL Phase Two" 8.0 0.0 12.0 0.025 - -// compatibility macros -#define float2 vec2 -#define float3 vec3 -#define float4 vec4 -#define frac(c) fract(c) -#define saturate(c) clamp(c, 0.0, 1.0) -#define fmod(x,y) mod(x,y) -#define mul(x,y) (y*x) -#define float2x2 mat2 -#define float3x3 mat3 -#define float4x4 mat4 -#define bool2 bvec2 -#define bool3 bvec3 -#define bool4 bvec4 - -layout(std140, set = 0, binding = 0) uniform UBO -{ - mat4 MVP; -} global; - -// TWEAKS start - -// comment this to disable dynamic settings, and use static. -// if you unable to compile shader with dynamic settings, -// and you want to tune parameters in menu, then -// try to reduce somewhere below Mwidth from 32 to lower, -// or disable USE_DELAY_LINE or USE_RAW, or all at once. -#define PARAMETER_UNIFORM - -// use delay line technique -// without delay line technique, color would interleave -// to avoid this, set HueRotation to zero. -#define USE_DELAY_LINE - -// use this if you need to swap even/odd V sign. -// sign of V changes each scanline -// so if some scanline is positive, then next is negative -// and if you want to match picture -// to actual running PAL NES on TV -// you may want to have this option, to change signs -// if they don't match -//#define SWAP_VSIGN - -// phase shift from frame to frame as NTSC NES does. -// but PAL NES doesn't -//#define ANIMATE_PHASE - -// rough simulation of scanlines -// better if you use additional shader instead -// if you still use it, make sure that SizeY -// is at least twice lower than output height -//#define USE_SCANLINES - -// this option changes active visible fields. -// this is not how actual NES works -// it does not alter fields. -//#define ANIMATE_SCANLINE - -// simulate CRT TV subpixels -// better if you use CRT-specialized shader instead -//#define USE_SUBPIXELS - -// to change gamma of virtual TV from 2.2 to something else -//#define USE_GAMMA - -// use core size. for NES use this, for other cores turn off -// for other cores use "size" tweak. -//#define USE_CORE_SIZE - -// use raw palette, turn it on if you -// have nestopia and having using raw palette -//#define USE_RAW - -// use lookup texture, faster but less accuracy -// it's working only if USE_RAW enabled. -//#define USE_LUT - -// compensate filter width -// it will make width of picture shorter -// to make picture right border visible -#define COMPENSATE_WIDTH - -// use sampled version. it's much more slower version of shader. -// because it is computing x4 more values. NOT RECOMMENDED. -#define USE_SAMPLED - -// this is using following matrixes. -// it provides more scientific approach -// by conversion into linear XYZ space -// and back to sRGB. -// it's using Gamma setting too. -// define USE_GAMMA is not required. -#define USE_COLORIMETRY - -const float3x3 RGB_to_XYZ = -mat3( - 0.4306190, 0.3415419, 0.1783091, - 0.2220379, 0.7066384, 0.0713236, - 0.0201853, 0.1295504, 0.9390944 -); - -const float3x3 XYZ_to_sRGB = -mat3( - 3.2406, -1.5372, -0.4986, - -0.9689, 1.8758, 0.0415, - 0.0557, -0.2040, 1.0570 -); - -// TWEAKS end - -const float Mwidth = 24; - -const int Ywidth_static = 1; -const int Uwidth_static = 1; -const int Vwidth_static = 1; - -const float Contrast_static = 1.; -const float Saturation_static = 1.; - - -const float YUV_u = 0.492; -const float YUV_v = 0.877; - -const mat3 RGB_to_YUV = -mat3( - float3( 0.299, 0.587, 0.114), //Y - float3(-0.299,-0.587, 0.886)*YUV_u, //B-Y - float3( 0.701,-0.587,-0.114)*YUV_v //R-Y -); - -#ifdef USE_RAW -#ifndef USE_LUT -const float Voltage_0 = 0.518; -const float Voltage_1 = 1.962; -const float DeltaV = (Voltage_1-Voltage_0); -#else -const float Voltage_0 = 0.15103768593097774; -const float Voltage_1 = 1.; -float DeltaV = (Voltage_1-Voltage_0); -#endif - -#else -const float DeltaV = 1.; -#endif - -#ifdef USE_DELAY_LINE -const float comb_line = 1.; -#else -const float comb_line = 2.; -#endif - -const double RGB_y = Contrast_static/Ywidth_static/DeltaV; -const double RGB_u = comb_line*Contrast_static*Saturation_static/YUV_u/Uwidth_static/DeltaV; -const double RGB_v = comb_line*Contrast_static*Saturation_static/YUV_v/Vwidth_static/DeltaV; - -const mat3 YUV_to_RGB = -mat3( - float3(1., 1., 1.)*RGB_y, - float3(0., -0.114/0.587, 1.)*RGB_u, - float3(1., -0.299/0.587, 0.)*RGB_v -); - -const float pi = 3.1415926535897932384626433832795; - -#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 * 1.0001; -} - -#pragma stage fragment -layout(location = 0) in vec2 vTexCoord; -layout(location = 0) out vec4 FragColor; -layout(set = 0, binding = 2) uniform sampler2D Source; -layout(set = 0, binding = 3) uniform sampler2D nes_lut; - -#ifdef USE_RAW - -bool InColorPhase(int color, float phase) -{ - return fmod((color*2. + phase),24.) < 12.; -} - -#ifndef USE_LUT -// from nesdev wiki page NTSC_video -float NTSCsignal(float3 pixel, float phase) -{ - // Voltage levels, relative to synch voltage - const float black=.518, white=1.962, attenuation=.746, - levels[8] = {.350, .518, .962,1.550, // Signal low - 1.094,1.506,1.962,1.962}; // Signal high - - // Decode the NES color. - int color = int(pixel.r*15); // 0..15 "cccc" - int level = int(pixel.g*3); // 0..3 "ll" - int emphasis = int(pixel.b*7+0.1); // 0..7 "eee" - if (color > 13) { level = 1; } // For colors 14..15, level 1 is forced. - - // The square wave for this color alternates between these two voltages: - float low = levels[0], high = levels[4]; - if (level == 1) { low = levels[1], high = levels[5]; } - if (level == 2) { low = levels[2], high = levels[6]; } - if (level == 3) { low = levels[3], high = levels[7]; } - if(color == 0) { low = high; } // For color 0, only high level is emitted - if(color > 12) { high = low; } // For colors 13..15, only low level is emitted - - - // Generate the square wave - // When de-emphasis bits are set, some parts of the signal are attenuated: - float2 e = fmod(float2(emphasis), float2(2.,4.)); - float signal = InColorPhase(color,phase) ? high : low; - - if( ((e.x != 0) && InColorPhase(0,phase)) - || ((e.y-e.x != 0) && InColorPhase(4,phase)) - || ((emphasis-e.y != 0) && InColorPhase(8,phase)) ) - return signal * attenuation; - else - return signal; -} - -#else - -float NTSCsignal(float3 pixel, float phase) -{ - return texture(nes_lut,float2(dot(pixel,float3( - 15.*(8.)/512., - 3.*(16.*8.)/512., - 7./512.) - ) + 0.5/(4.*16.*8.), frac(phase/24.))).r; -} - -#endif - -#endif - -float sinn(float x) -{ - return sin(/*fmod(x,24)*/x*(pi*2./24.)); -} - -float coss(float x) -{ - return cos(/*fmod(x,24)*/x*(pi*2./24.)); -} - -float3 monitor(sampler2D tex, float2 p) -{ -#ifdef PARAMETER_UNIFORM - const float2 size = float2(params.SizeX,params.SizeY); -#endif - // align vertical coord to center of texel - float2 uv = float2( -#ifdef COMPENSATE_WIDTH - p.x+p.x*(params.Ywidth/8.)/size.x, -#else - p.x, -#endif - (floor(p.y*params.SourceSize.y)+0.5)/params.SourceSize.y); -#ifdef USE_DELAY_LINE - float2 sh = (params.SourceSize.xy/params.SourceSize.xy/size)*float2(14./10.,-1.0); -#endif - float2 pc = uv*params.SourceSize.xy/params.SourceSize.xy*size*float2(10.,1.); - float alpha = dot(floor(float2(pc.x,pc.y)),float2(2.,params.Phase_Y*2.)); - alpha += params.Phase_One*2.; -#ifdef ANIMATE_PHASE - if (fmod(params.FrameCount,2) > 1.) - alpha += (params.Phase_Two-params.Phase_One)*2.; -#endif - - // 1/size.x of screen in uv coords = params.SourceSize.x/params.SourceSize.x/size.x; - // then 1/10*size.x of screen: - float ustep = params.SourceSize.x/params.SourceSize.x/size.x/10.; - - float border = params.SourceSize.x/params.SourceSize.x; - float ss = 2.0; -#ifdef SWAP_VSIGN -#define PAL_SWITCH(A) A < 1. -#else -#define PAL_SWITCH(A) A > 1. -#endif - if (PAL_SWITCH(fmod(uv.y*params.SourceSize.y/params.SourceSize.y*size.y,2.0))) - { - // cos(pi-alpha) = -cos(alpha) - // sin(pi-alpha) = sin(alpha) - // pi - alpha - alpha = -alpha+12012.0; - ss = -2.0; - } - - float ysum = 0., usum = 0., vsum = 0.; - for (int i=0; i= border) - sig = 0; -#ifdef USE_DELAY_LINE - float4 res1 = texture(tex, uv+sh); - float sig1 = NTSCsignal(res1.xyz,params.HueShift*2.+12012.0-alpha+res.g*ss*params.HueRotation)-Voltage_0; - if (uv.x + sh.x <= 0.0 || uv.x + sh.x >= border) - sig1 = 0; -#endif - -#else - float3 yuv = mul(RGB_to_YUV, res.xyz); - const float a1 = alpha+(params.HueShift+2.5)*2.-yuv.x*ss*params.HueRotation; - float sig = yuv.x+dot(yuv.yz,sign(float2(sinn(a1),coss(a1)))); -#ifdef USE_DELAY_LINE - float4 res1 = texture(tex, uv+sh); - float3 yuv1 = mul(RGB_to_YUV, res1.xyz); - const float a2 = (params.HueShift+2.5)*2.+12012.0-alpha+yuv.x*ss*params.HueRotation; - float sig1 = yuv1.x+dot(yuv1.yz,sign(float2(sinn(a2),coss(a2)))); -#endif - -#endif - if (i < params.Ywidth) - ysum += sig; - -#ifdef USE_DELAY_LINE - if (i < params.Uwidth) - usum += (sig+sig1)*sinn(alpha); - if (i < params.Vwidth) - vsum += (sig-sig1)*coss(alpha); -#else - if (i < params.Uwidth) - usum += sig*sinn(alpha); - if (i < params.Vwidth) - vsum += sig*coss(alpha); -#endif - alpha -= ss; - uv.x -= ustep; - } - -#ifdef PARAMETER_UNIFORM - ysum *= params.Contrast/params.Ywidth; - usum *= params.Contrast*params.Saturation/params.Uwidth; - vsum *= params.Contrast*params.Saturation/params.Vwidth; -#endif - - float3 rgb = mul(float3(ysum+params.Brightness*Ywidth_static,usum,vsum), YUV_to_RGB); -#if defined(USE_GAMMA) && !defined(USE_COLORIMETRY) - float3 rgb1 = saturate(rgb); - rgb = pow(rgb1, params.Gamma/2.2); -#endif - -#ifdef USE_COLORIMETRY - float3 rgb1 = saturate(rgb); - rgb = pow(rgb1, float3(params.Gamma, params.Gamma, params.Gamma)); -#endif - -#if (defined(USE_SUBPIXELS) || defined(USE_SCANLINES)) - float2 q = (p*params.SourceSize.xy/params.SourceSize.xy)*float2(params.TV_Pixels*3.,size.y*2.); -#endif - -#ifdef USE_SCANLINES - float scanlines = size.y/params.OutputSize.x; - float top = fmod(q.y-0.5*scanlines*2.,2.); - float bottom = top+frac(scanlines)*2.; - float2 sw = saturate(min(float2(1.,2.),float2(bottom, bottom)) - -max(float2(0.,1.),float2(top))) - +saturate(min(float2(3.,4.),float2(bottom, bottom)) - -max(float2(2.,3.),float2(top))) - +floor(scanlines); -#ifdef ANIMATE_SCANLINE -#define SCANLINE_MUL (fmod(int(params.FrameCount),2)<1 \ - ? sw.x*params.dark_scanline+sw.y \ - : sw.x+sw.y*params.dark_scanline) -#else -#define SCANLINE_MUL (sw.x*params.dark_scanline+sw.y) -#endif - rgb = rgb*SCANLINE_MUL/(sw.x+sw.y); - -#endif - - // size of pixel screen in texture coords: - //float output_pixel_size = params.SourceSize.x/(params.OutputSize.x*params.SourceSize.x); - - // correctness check - //if (fmod(p.x*output_pixel_size,2.0) < 1.0) - // rgb = float3(0.,0.,0.); - -#ifdef USE_SUBPIXELS - float pixels = params.TV_Pixels/params.OutputSize.x; - float left = fmod(q.x-0.5*pixels*3,3); - float right = left+frac(pixels)*3.; - float3 w = saturate(min(float3(1.,2.,3.),float3(right,right,right)) - -max(float3(0.,1.,2.),float3(left,left,left))) - +saturate(min(float3(4.,5.,6.),float3(right,right,right)) - -max(float3(3.,4.,5.),float3(left,left,left))) - +floor(pixels); - rgb = rgb*3.*w/(w.x+w.y+w.z); -#endif - -#ifdef USE_COLORIMETRY - float3 xyz1 = mul(RGB_to_XYZ,rgb); - float3 srgb = saturate(mul(XYZ_to_sRGB,xyz1)); - float3 a1 = 12.92*srgb; - float3 a2 = 1.055*pow(srgb,float3(1./2.4))-0.055; - float3 ssrgb; - ssrgb.x = (srgb.x<0.0031308?a1.x:a2.x); - ssrgb.y = (srgb.y<0.0031308?a1.y:a2.y); - ssrgb.z = (srgb.z<0.0031308?a1.z:a2.z); - return ssrgb; -#else - return rgb; -#endif -} - -void main() -{ - FragColor = vec4(monitor(Source, vTexCoord), 1.0); -} \ No newline at end of file diff --git a/pal/shaders/pal-r57shell-multipass1.slang b/pal/shaders/pal-r57shell-multipass1.slang deleted file mode 100644 index 712dc54..0000000 --- a/pal/shaders/pal-r57shell-multipass1.slang +++ /dev/null @@ -1,107 +0,0 @@ -#version 450 - -// NES PAL composite signal simulation for RetroArch -// shader by r57shell -// thanks to feos & HardWareMan & NewRisingSun - -// also TV subpixels and scanlines - -// LICENSE: PUBLIC DOMAIN - -// NOTE: for nice TV subpixels and scanlines I recommend to -// disable this features here and apply CRT-specialized shader. - -// Quality considerations - -// there are three main options: -// USE_RAW (R), USE_DELAY_LINE (D), USE_COLORIMETRY (C) -// here is table of quality in decreasing order: -// RDC, RD, RC, DC, D, C - -layout(push_constant) uniform Push -{ - vec4 SourceSize; - vec4 OriginalSize; - vec4 OutputSize; - uint FrameCount; -} params; - -// compatibility macros -#define float2 vec2 -#define float3 vec3 -#define float4 vec4 -#define frac(c) fract(c) -#define saturate(c) clamp(c, 0.0, 1.0) -#define fmod(x,y) mod(x,y) -#define mul(x,y) (y*x) -#define float2x2 mat2 -#define float3x3 mat3 -#define float4x4 mat4 -#define bool2 bvec2 -#define bool3 bvec3 -#define bool4 bvec4 - -layout(std140, set = 0, binding = 0) uniform UBO -{ - mat4 MVP; -} global; - -#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 * 1.0001;; -} - -#pragma stage fragment -layout(location = 0) in vec2 vTexCoord; -layout(location = 0) out vec4 FragColor; -layout(set = 0, binding = 2) uniform sampler2D Source; - -// pos (left corner, sample size) -float4 monitor_sample(float2 p, float2 sample_) -{ - // linear interpolation was... - // now other thing. - // http://imgur.com/m8Z8trV - // AT LAST IT WORKS!!!! - // going to check in retroarch... - float2 size = params.SourceSize.xy; - float2 next = float2(.25,1.)/size; - float2 f = frac(float2(4.,1.)*size*p); - sample_ *= float2(4.,1.)*size; - float2 l; - float2 r; - if (f.x+sample_.x < 1.) - { - l.x = f.x+sample_.x; - r.x = 0.; - } - else - { - l.x = 1.-f.x; - r.x = min(1.,f.x+sample_.x-1.); - } - if (f.y+sample_.y < 1.) - { - l.y = f.y+sample_.y; - r.y = 0.; - } - else - { - l.y = 1.-f.y; - r.y = min(1.,f.y+sample_.y-1.); - } - float3 top = mix(texture(Source, p).rgb, texture(Source, p+float2(next.x,0.)).rgb, r.x/(l.x+r.x)); - float3 bottom = mix(texture(Source, p+float2(0.,next.y)).rgb, texture(Source, p+next).rgb, r.x/(l.x+r.x)); - return float4(mix(top,bottom, r.y/(l.y+r.y)),1.0); -} - -void main() -{ - FragColor = monitor_sample(vTexCoord, params.OutputSize.zw); -} \ No newline at end of file diff --git a/pal/shaders/pal-r57shell.slang b/pal/shaders/pal-r57shell.slang index 924bf3d..4c2dc36 100644 --- a/pal/shaders/pal-r57shell.slang +++ b/pal/shaders/pal-r57shell.slang @@ -146,6 +146,7 @@ layout(std140, set = 0, binding = 0) uniform UBO //#define USE_SAMPLED /*#ifndef PARAMETER_UNIFORM +// commented because parameters are always available in slang // NTSC standard gamma = 2.2 // PAL standard gamma = 2.8 @@ -271,11 +272,11 @@ const float comb_line = 1.; const float comb_line = 2.; #endif -const double RGB_y = Contrast_static/Ywidth_static/DeltaV; -const double RGB_u = comb_line*Contrast_static*Saturation_static/YUV_u/Uwidth_static/DeltaV; -const double RGB_v = comb_line*Contrast_static*Saturation_static/YUV_v/Vwidth_static/DeltaV; +float RGB_y = Contrast_static/Ywidth_static/DeltaV; +float RGB_u = comb_line*Contrast_static*Saturation_static/YUV_u/Uwidth_static/DeltaV; +float RGB_v = comb_line*Contrast_static*Saturation_static/YUV_v/Vwidth_static/DeltaV; -const mat3 YUV_to_RGB = +mat3 YUV_to_RGB = mat3( float3(1., 1., 1.)*RGB_y, float3(0., -0.114/0.587, 1.)*RGB_u, @@ -312,7 +313,7 @@ bool InColorPhase(int color, float phase) float NTSCsignal(float3 pixel, float phase) { // Voltage levels, relative to synch voltage - static const float black=.518, white=1.962, attenuation=.746, + const float black=.518, white=1.962, attenuation=.746, levels[8] = {.350, .518, .962,1.550, // Signal low 1.094,1.506,1.962,1.962}; // Signal high @@ -482,7 +483,7 @@ float3 monitor(sampler2D tex, float2 p) #endif #ifdef USE_SCANLINES - float scanlines = size.y/params.OutputSize.x; + float scanlines = size.y * params.OutputSize.z; float top = fmod(q.y-0.5*scanlines*2.,2.); float bottom = top+frac(scanlines)*2.; float2 sw = saturate(min(float2(1.,2.),float2(bottom, bottom)) @@ -520,10 +521,10 @@ float3 monitor(sampler2D tex, float2 p) // rgb = float3(0.,0.,0.); #ifdef USE_SUBPIXELS - float pixels = params.TV_Pixels/params.OutputSize.x; - float left = fmod(q.x-0.5*pixels*3,3); + float pixels = params.TV_Pixels * params.OutputSize.z; + float left = fmod(q.x-0.5*pixels*3.,3.); float right = left+frac(pixels)*3.; - float3 w = saturate(min(float3(1.,2.,3.),float3(rightright,right)) + float3 w = saturate(min(float3(1.,2.,3.),float3(right,right,right)) -max(float3(0.,1.,2.),float3(left,left,left))) +saturate(min(float3(4.,5.,6.),float3(right,right,right)) -max(float3(3.,4.,5.),float3(left,left,left))) @@ -587,6 +588,10 @@ float4 monitor_sample(sampler2D tex, float2 p, float2 sample_) void main() { +#ifdef USE_SAMPLED + FragColor = vec4(monitor_sample(Source, vTexCoord, params.OutputSize.zw).rgb, 1.0); +#else + FragColor = float4(monitor(Source, vTexCoord), 1.); +#endif - FragColor = vec4(monitor_sample(Source, vTexCoord, params.OutputSize.xy).rgb, 1.0); } \ No newline at end of file