├── reshade ├── Textures │ ├── CRT-LUT-1.png │ ├── CRT-LUT-2.png │ ├── CRT-LUT-3.png │ ├── CRT-LUT-4.png │ ├── overlay │ │ ├── psx.jpg │ │ └── OVERLAY_CREDITS_AND_LICENSE.md │ ├── crt-cyclon │ │ └── bezel.png │ └── crt-royale │ │ ├── TileableLinearShadowMask.png │ │ ├── TileableLinearShadowMaskEDP.png │ │ ├── TileableLinearShadowMaskResizeTo64.png │ │ ├── TileableLinearShadowMaskEDPResizeTo64.png │ │ ├── TileableLinearApertureGrille15Wide8And5d5Spacing.png │ │ ├── TileableLinearApertureGrille15Wide8And5d5SpacingResizeTo64.png │ │ ├── TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing.png │ │ └── TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacingResizeTo64.png ├── source.txt ├── README.md └── Shaders │ ├── XY-Pos-free.fx │ ├── crt-royale │ ├── version-number.fxh │ ├── shaders │ │ ├── input-blurring.fxh │ │ ├── brightpass.fxh │ │ ├── deinterlace.fxh │ │ ├── blurring.fxh │ │ ├── bloom.fxh │ │ ├── phosphor-mask.fxh │ │ ├── content-box.fxh │ │ └── geometry-aa-last-pass.fxh │ └── lib │ │ ├── downsampling-functions.fxh │ │ └── helper-functions-and-macros.fxh │ ├── crt │ ├── crt-royale │ │ ├── include │ │ │ ├── user-cgp-constants.fxh │ │ │ └── helper-functions-and-macros.fxh │ │ └── src │ │ │ ├── crt-royale-bloom-vertical.fxh │ │ │ ├── blur9fast-vertical.fxh │ │ │ ├── blur9fast-horizontal.fxh │ │ │ ├── crt-royale-first-pass-linearize-crt-gamma-bob-fields.fxh │ │ │ ├── crt-royale-bloom-horizontal-reconstitute.fxh │ │ │ ├── crt-royale-mask-resize-horizontal.fxh │ │ │ ├── crt-royale-brightpass.fxh │ │ │ └── crt-royale-mask-resize-vertical.fxh │ └── crt-geo-zfast.fx │ ├── anti-aliasing │ └── aa-shader-4.0.fx │ ├── blur │ ├── g-sharp2-resampler.fx │ └── g-sharp2-resampler-fast.fx │ ├── interpolation │ └── lanczos3.fx │ ├── denoisers │ └── bilateral.fx │ ├── misc │ ├── deblur-luma.fx │ ├── include │ │ ├── geom.fxh │ │ └── mask.fxh │ └── geom.fx │ └── crt-royale.fx ├── README.md └── dolphinfx ├── interpolation └── JINC2.glsl ├── crt ├── ZFAST-CRT-COMPOSITE.glsl └── CRT-EASYMODE.glsl ├── celshading.glsl └── bloom.glsl /reshade/Textures/CRT-LUT-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/CRT-LUT-1.png -------------------------------------------------------------------------------- /reshade/Textures/CRT-LUT-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/CRT-LUT-2.png -------------------------------------------------------------------------------- /reshade/Textures/CRT-LUT-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/CRT-LUT-3.png -------------------------------------------------------------------------------- /reshade/Textures/CRT-LUT-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/CRT-LUT-4.png -------------------------------------------------------------------------------- /reshade/Textures/overlay/psx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/overlay/psx.jpg -------------------------------------------------------------------------------- /reshade/Textures/crt-cyclon/bezel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/crt-cyclon/bezel.png -------------------------------------------------------------------------------- /reshade/Textures/crt-royale/TileableLinearShadowMask.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/crt-royale/TileableLinearShadowMask.png -------------------------------------------------------------------------------- /reshade/Textures/crt-royale/TileableLinearShadowMaskEDP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/crt-royale/TileableLinearShadowMaskEDP.png -------------------------------------------------------------------------------- /reshade/Textures/crt-royale/TileableLinearShadowMaskResizeTo64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/crt-royale/TileableLinearShadowMaskResizeTo64.png -------------------------------------------------------------------------------- /reshade/Textures/crt-royale/TileableLinearShadowMaskEDPResizeTo64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/crt-royale/TileableLinearShadowMaskEDPResizeTo64.png -------------------------------------------------------------------------------- /reshade/Textures/crt-royale/TileableLinearApertureGrille15Wide8And5d5Spacing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/crt-royale/TileableLinearApertureGrille15Wide8And5d5Spacing.png -------------------------------------------------------------------------------- /reshade/source.txt: -------------------------------------------------------------------------------- 1 | https://github.com/crosire/reshade-shaders 2 | https://github.com/Matsilagi/RSRetroArch/ 3 | https://github.com/akgunter/crt-royale-reshade 4 | https://github.com/HelelSingh/CRT-Guest-ReShade 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GLSL and Reshade FX shaders 2 | 3 | These shaders can be used with various emulators that support the Dolphin GLSL format, or ReShade FX formats. 4 | 5 | Authorship and license information is contained within each file. 6 | -------------------------------------------------------------------------------- /reshade/Textures/crt-royale/TileableLinearApertureGrille15Wide8And5d5SpacingResizeTo64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/crt-royale/TileableLinearApertureGrille15Wide8And5d5SpacingResizeTo64.png -------------------------------------------------------------------------------- /reshade/Textures/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing.png -------------------------------------------------------------------------------- /reshade/Textures/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacingResizeTo64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stenzek/emu-shaders/HEAD/reshade/Textures/crt-royale/TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacingResizeTo64.png -------------------------------------------------------------------------------- /reshade/Textures/overlay/OVERLAY_CREDITS_AND_LICENSE.md: -------------------------------------------------------------------------------- 1 | # To Use 2 | 3 | Choose Aspect Ratio: Stretch to Fill. 4 | 5 | # Psx.jpg Credits 6 | 7 | To the Author: SOQUEROEU. 8 | 9 | The "psx.jpg" background was edited from the one obtained from "Soqueroeu TV Backgrounds 2.0" repository: https://github.com/soqueroeu/Soqueroeu-TV-Backgrounds_V2.0/tree/main. 10 | 11 | The material is free to use according to the agreement below: 12 | 13 | ## AGREEMENT 14 | 15 | This pack is free. You should not pay for anything related to this graphics pack and shader preset. You may distribute and reproduce part from this content, as long as you give credit to the authors involved. You may not profit from the sale of products that contain material in this package without the author's prior permission. 16 | -------------------------------------------------------------------------------- /reshade/README.md: -------------------------------------------------------------------------------- 1 | ReShade FX shaders 2 | ================== 3 | 4 | This repository aims to collect post-processing shaders written in the ReShade FX shader language. 5 | 6 | Installation 7 | ------------ 8 | 9 | 1. [Download](https://github.com/crosire/reshade-shaders/archive/master.zip) this repository 10 | 2. Extract the downloaded archive file somewhere 11 | 3. Start your game, open the ReShade in-game menu and switch to the "Settings" tab 12 | 4. Add the path to the extracted [Shaders](/Shaders) folder to "Effect Search Paths" 13 | 5. Add the path to the extracted [Textures](/Textures) folder to "Texture Search Paths" 14 | 6. Switch back to the "Home" tab and click on "Reload" to load the shaders 15 | 16 | Contributing 17 | ------------ 18 | 19 | Check out [the language reference document](REFERENCE.md) to get started on how to write your own! 20 | -------------------------------------------------------------------------------- /reshade/Shaders/XY-Pos-free.fx: -------------------------------------------------------------------------------- 1 | #include "ReShade.fxh" 2 | 3 | // CrashGG presents 4 | 5 | // 'XY-Pos-free' 6 | 7 | // A super-simple shader refined from the super-fast crt-cyclon.fx, It only provides 8 | // the functions of free pixel stretching and position translation on the XY axis. 9 | // Suitable for users who only want to fine-tune the screen zoom and position and do not like the bundled CRT-like effects. 10 | // Fixed some bugs in the original version, adjusted the step progress and the range. 11 | 12 | // This program is free software; you can redistribute it and/or modify it 13 | // under the terms of the GNU General Public License as published by the Free 14 | // Software Foundation; either version 2 of the License, or (at your option) 15 | // any later version. 16 | 17 | 18 | uniform float zoomx < 19 | ui_type = "drag"; 20 | ui_min = -0.3000; 21 | ui_max = 0.3000; 22 | ui_step = 0.0005; 23 | ui_label = "Zoom Image X"; 24 | > = 0.0000; 25 | 26 | uniform float zoomy < 27 | ui_type = "drag"; 28 | ui_min = -0.3000; 29 | ui_max = 0.3000; 30 | ui_step = 0.0005; 31 | ui_label = "Zoom Image Y"; 32 | > = 0.0000; 33 | 34 | uniform float centerx < 35 | ui_type = "drag"; 36 | ui_min = -9.99; 37 | ui_max = 9.99; 38 | ui_step = 0.01; 39 | ui_label = "Image Center X"; 40 | > = 0.00; 41 | 42 | uniform float centery < 43 | ui_type = "drag"; 44 | ui_min = -9.99; 45 | ui_max = 9.99; 46 | ui_step = 0.01; 47 | ui_label = "Image Center Y"; 48 | > = 0.00; 49 | 50 | 51 | float2 Warp(float2 pos) 52 | { 53 | pos = pos*2.0-1.0; 54 | pos *= float2(1.0+pos.y*pos.y*0, 1.0+pos.x*pos.x*0); 55 | pos = pos*0.5+0.5; 56 | 57 | return pos; 58 | } 59 | 60 | 61 | float4 CRT_CYCLON_PS(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD0) : SV_Target 62 | { 63 | // zoom in and center screen 64 | float2 pos = Warp((vTexCoord*float2(1.0-zoomx,1.0-zoomy)-float2(centerx,centery)/100.0)); 65 | 66 | // Convergence 67 | float3 res = tex2D(ReShade::BackBuffer,pos).rgb; 68 | 69 | // Vignette 70 | float x = 0.0; 71 | 72 | return float4(res, 1.0); 73 | } 74 | 75 | 76 | 77 | technique CRT_CYCLON 78 | { 79 | pass PS_CRT_CYCLON 80 | { 81 | VertexShader = PostProcessVS; 82 | PixelShader = CRT_CYCLON_PS; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /reshade/Shaders/crt-royale/version-number.fxh: -------------------------------------------------------------------------------- 1 | #ifndef _VERSION_NUMBER_H 2 | #define _VERSION_NUMBER_H 3 | 4 | ///////////////////////////////// MIT LICENSE //////////////////////////////// 5 | 6 | // Copyright (C) 2022 Alex Gunter 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal in the Software without restriction, including without limitation the 11 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12 | // sell copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24 | // IN THE SOFTWARE. 25 | 26 | 27 | #define MAJOR_VERSION 2 28 | #define MINOR_VERSION 1 29 | #define PATCH_VERSION 0 30 | 31 | // Yes, both sibling preprocessor functions are necessary. 32 | // Don't "simplify" this, or the substitution won't work. 33 | #define BUILD_DOT_VERSION_(mav, miv, pav) #mav "." #miv "." #pav 34 | #define BUILD_DOT_VERSION(mav, miv, pav) BUILD_DOT_VERSION_(mav, miv, pav) 35 | #define DOT_VERSION_STR BUILD_DOT_VERSION(MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION) 36 | 37 | // Again, yes, both sibling preprocessor functions are necessary. 38 | // Don't "simplify" this, or the substitution won't work. 39 | #define BUILD_UNDERSCORE_VERSION_(prefix, mav, miv, pav) prefix ## _ ## mav ## _ ## miv ## _ ## pav 40 | #define BUILD_UNDERSCORE_VERSION(p, mav, miv, pav) BUILD_UNDERSCORE_VERSION_(p, mav, miv, pav) 41 | #define APPEND_VERSION_SUFFIX(prefix) BUILD_UNDERSCORE_VERSION(prefix, MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION) 42 | 43 | 44 | #endif // _VERSION_NUMBER_H -------------------------------------------------------------------------------- /reshade/Shaders/crt-royale/shaders/input-blurring.fxh: -------------------------------------------------------------------------------- 1 | #ifndef _INPUT_BLURRING_H 2 | #define _INPUT_BLURRING_H 3 | 4 | ///////////////////////////////// MIT LICENSE //////////////////////////////// 5 | 6 | // Copyright (C) 2022 Alex Gunter 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal in the Software without restriction, including without limitation the 11 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12 | // sell copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24 | // IN THE SOFTWARE. 25 | 26 | 27 | // Theoretically this could go in blurring.fxh 28 | // But that file has a bunch of GPL stuff in it. 29 | // Keeping it separate makes it easier to communicate that this portion is 30 | // available under the MIT license. 31 | 32 | #include "../lib/downsampling-functions.fxh" 33 | 34 | #include "content-box.fxh" 35 | #include "shared-objects.fxh" 36 | 37 | 38 | void preblurVertPS( 39 | in const float4 pos : SV_Position, 40 | in const float2 texcoord : TEXCOORD0, 41 | 42 | out float4 color : SV_Target 43 | ) { 44 | const float2 texcoord_uncropped = texcoord; 45 | 46 | const float2 max_delta_uv = float2(0.0, rcp(content_size.y)) * preblur_effect_radius; 47 | const float2 delta_uv = max_delta_uv * rcp(max(preblur_sampling_radius.y, 1)); 48 | 49 | color = float4(opaque_linear_downsample( 50 | ReShade::BackBuffer, 51 | texcoord_uncropped, 52 | preblur_sampling_radius.y, 53 | delta_uv 54 | ), 1); 55 | } 56 | 57 | void preblurHorizPS( 58 | in const float4 pos : SV_Position, 59 | in const float2 texcoord : TEXCOORD0, 60 | 61 | out float4 color : SV_Target 62 | ) { 63 | const float2 max_delta_uv = float2(rcp(content_size.x), 0.0) * preblur_effect_radius; 64 | const float2 delta_uv = max_delta_uv * rcp(max(preblur_sampling_radius.x, 1)); 65 | 66 | color = float4(opaque_linear_downsample( 67 | samplerPreblurVert, 68 | texcoord, 69 | preblur_sampling_radius.x, 70 | delta_uv 71 | ), 1); 72 | } 73 | 74 | #endif // _INPUT_BLURRING_H -------------------------------------------------------------------------------- /reshade/Shaders/crt/crt-royale/include/user-cgp-constants.fxh: -------------------------------------------------------------------------------- 1 | #ifndef USER_CGP_CONSTANTS_H 2 | #define USER_CGP_CONSTANTS_H 3 | 4 | // IMPORTANT: 5 | // These constants MUST be set appropriately for the settings in crt-royale.cgp 6 | // (or whatever related .cgp file you're using). If they aren't, you're likely 7 | // to get artifacts, the wrong phosphor mask size, etc. I wish these could be 8 | // set directly in the .cgp file to make things easier, but...they can't. 9 | 10 | // PASS SCALES AND RELATED CONSTANTS: 11 | // Copy the absolute scale_x for BLOOM_APPROX. There are two major versions of 12 | // this shader: One does a viewport-scale bloom, and the other skips it. The 13 | // latter benefits from a higher bloom_approx_scale_x, so save both separately: 14 | static const float bloom_approx_size_x = 320.0; 15 | static const float bloom_approx_size_x_for_fake = 400.0; 16 | // Copy the viewport-relative scales of the phosphor mask resize passes 17 | // (MASK_RESIZE and the pass immediately preceding it): 18 | static const float2 mask_resize_viewport_scale = float2(0.0625, 0.0625); 19 | // Copy the geom_max_aspect_ratio used to calculate the MASK_RESIZE scales, etc.: 20 | static const float geom_max_aspect_ratio = 4.0/3.0; 21 | 22 | // PHOSPHOR MASK TEXTURE CONSTANTS: 23 | // Set the following constants to reflect the properties of the phosphor mask 24 | // texture named in crt-royale.cgp. The shader optionally resizes a mask tile 25 | // based on user settings, then repeats a single tile until filling the screen. 26 | // The shader must know the input texture size (default 64x64), and to manually 27 | // resize, it must also know the horizontal triads per tile (default 8). 28 | static const float2 mask_texture_small_size = 64.0.xx; 29 | static const float2 mask_texture_large_size = 512.0.xx; 30 | static const float mask_triads_per_tile = 8.0; 31 | // We need the average brightness of the phosphor mask to compensate for the 32 | // dimming it causes. The following four values are roughly correct for the 33 | // masks included with the shader. Update the value for any LUT texture you 34 | // change. [Un]comment "#define PHOSPHOR_MASK_GRILLE14" depending on whether 35 | // the loaded aperture grille uses 14-pixel or 15-pixel stripes (default 15). 36 | //#define PHOSPHOR_MASK_GRILLE14 37 | static const float mask_grille14_avg_color = 50.6666666/255.0; 38 | // TileableLinearApertureGrille14Wide7d33Spacing*.png 39 | // TileableLinearApertureGrille14Wide10And6Spacing*.png 40 | static const float mask_grille15_avg_color = 53.0/255.0; 41 | // TileableLinearApertureGrille15Wide6d33Spacing*.png 42 | // TileableLinearApertureGrille15Wide8And5d5Spacing*.png 43 | static const float mask_slot_avg_color = 46.0/255.0; 44 | // TileableLinearSlotMask15Wide9And4d5Horizontal8VerticalSpacing*.png 45 | // TileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing*.png 46 | static const float mask_shadow_avg_color = 41.0/255.0; 47 | // TileableLinearShadowMask*.png 48 | // TileableLinearShadowMaskEDP*.png 49 | 50 | #ifdef PHOSPHOR_MASK_GRILLE14 51 | static const float mask_grille_avg_color = mask_grille14_avg_color; 52 | #else 53 | static const float mask_grille_avg_color = mask_grille15_avg_color; 54 | #endif 55 | 56 | 57 | #endif // USER_CGP_CONSTANTS_H 58 | 59 | -------------------------------------------------------------------------------- /reshade/Shaders/crt-royale/lib/downsampling-functions.fxh: -------------------------------------------------------------------------------- 1 | #ifndef _DOWNSAMPLING_FUNCTIONS_H 2 | #define _DOWNSAMPLING_FUNCTIONS_H 3 | 4 | ///////////////////////////////// MIT LICENSE //////////////////////////////// 5 | 6 | // Copyright (C) 2020 Alex Gunter 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal in the Software without restriction, including without limitation the 11 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12 | // sell copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24 | // IN THE SOFTWARE. 25 | 26 | float3 opaque_linear_downsample( 27 | const sampler2D tex, 28 | const float2 texcoord, 29 | const uint num_pairs, 30 | const float2 delta_uv 31 | ) { 32 | const uint total_num_samples = num_pairs * 2 + 1; 33 | const float2 coord_left = texcoord - delta_uv * num_pairs; 34 | 35 | float3 acc = 0; 36 | for(int i = 0; i < total_num_samples; i++) { 37 | const float2 coord = coord_left + i * delta_uv; 38 | acc += tex2D_nograd(tex, coord).rgb; 39 | } 40 | 41 | return acc / total_num_samples; 42 | } 43 | 44 | 45 | float3 opaque_lanczos_downsample( 46 | const sampler2D tex, 47 | const float2 texcoord, 48 | const uint num_pairs, 49 | const float2 delta_uv, 50 | const float num_sinc_lobes, 51 | const float weight_at_center 52 | ) { 53 | const uint total_num_samples = num_pairs * 2 + 1; 54 | const float2 coord_left = texcoord - delta_uv * num_pairs; 55 | const float sinc_dx = num_sinc_lobes / num_pairs; // 2 * num_sinc_lobes / (total_num_samples - 1) 56 | 57 | float3 acc = 0; 58 | float w_sum = 0; 59 | for(int i = 0; i < total_num_samples; i++) { 60 | const float2 coord = coord_left + i * delta_uv; 61 | const float sinc_x = i * sinc_dx; 62 | 63 | const float weight = (i != num_pairs) ? 64 | num_sinc_lobes * sin(pi*sinc_x) * sin(pi*sinc_x/num_sinc_lobes) / (pi*pi * sinc_x*sinc_x) : 65 | weight_at_center; 66 | 67 | acc += weight * tex2D_nograd(tex, coord).rgb; 68 | w_sum += weight; 69 | } 70 | 71 | return acc / w_sum; 72 | } 73 | 74 | float3 opaque_lanczos_downsample( 75 | const sampler2D tex, 76 | const float2 texcoord, 77 | const uint num_pairs, 78 | const float2 delta_uv, 79 | const float num_sinc_lobes 80 | ) { 81 | return opaque_lanczos_downsample(tex, texcoord, num_pairs, delta_uv, num_sinc_lobes, 1); 82 | } 83 | 84 | #endif // _DOWNSAMPLING_FUNCTIONS_H -------------------------------------------------------------------------------- /reshade/Shaders/crt/crt-royale/src/crt-royale-bloom-vertical.fxh: -------------------------------------------------------------------------------- 1 | ///////////////////////////// GPL LICENSE NOTICE ///////////////////////////// 2 | 3 | // crt-royale: A full-featured CRT shader, with cheese. 4 | // Copyright (C) 2014 TroggleMonkey 5 | // 6 | // This program is free software; you can redistribute it and/or modify it 7 | // under the terms of the GNU General Public License as published by the Free 8 | // Software Foundation; either version 2 of the License, or any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, but WITHOUT 11 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 | // more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along with 16 | // this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | // Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | 20 | ///////////////////////////// SETTINGS MANAGEMENT //////////////////////////// 21 | 22 | #include "../include/user-settings.fxh" 23 | #include "../include/derived-settings-and-constants.fxh" 24 | #include "../include/bind-shader-params.fxh" 25 | 26 | ////////////////////////////////// INCLUDES ////////////////////////////////// 27 | 28 | #include "../include/gamma-management.fxh" 29 | #include "../include/bloom-functions.fxh" 30 | #include "../include/phosphor-mask-resizing.fxh" 31 | 32 | 33 | ///////////////////////////////// STRUCTURES ///////////////////////////////// 34 | 35 | struct out_vertex_p9 36 | { 37 | float2 tex_uv : TEXCOORD1; 38 | float2 bloom_dxdy : TEXCOORD2; 39 | float bloom_sigma_runtime : TEXCOORD3; 40 | }; 41 | 42 | 43 | //////////////////////////////// VERTEX SHADER /////////////////////////////// 44 | 45 | // Vertex shader generating a triangle covering the entire screen 46 | void VS_Bloom_Vertical(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out out_vertex_p9 OUT) 47 | { 48 | texcoord.x = (id == 2) ? 2.0 : 0.0; 49 | texcoord.y = (id == 1) ? 2.0 : 0.0; 50 | position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 51 | 52 | float2 texture_size = BLOOM_VERTICAL_texture_size; 53 | float2 output_size = VIEWPORT_SIZE; 54 | 55 | OUT.tex_uv = texcoord; 56 | 57 | // Get the uv sample distance between output pixels. Calculate dxdy like 58 | // blurs/vertex-shader-blur-fast-vertical.h. 59 | const float2 dxdy_scale = video_size/output_size; 60 | const float2 dxdy = dxdy_scale/texture_size; 61 | // This blur is vertical-only, so zero out the vertical offset: 62 | OUT.bloom_dxdy = float2(0.0, dxdy.y); 63 | 64 | // Calculate a runtime bloom_sigma in case it's needed: 65 | const float mask_tile_size_x = get_resized_mask_tile_size( 66 | output_size, output_size * mask_resize_viewport_scale, false).x; 67 | OUT.bloom_sigma_runtime = get_min_sigma_to_blur_triad( 68 | mask_tile_size_x / mask_triads_per_tile, bloom_diff_thresh); 69 | } 70 | 71 | 72 | /////////////////////////////// FRAGMENT SHADER ////////////////////////////// 73 | 74 | float4 PS_Bloom_Vertical(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in out_vertex_p9 VAR) : SV_Target 75 | { 76 | // Blur the brightpass horizontally with a 9/17/25/43x blur: 77 | const float bloom_sigma = get_final_bloom_sigma(VAR.bloom_sigma_runtime); 78 | const float3 color = tex2DblurNfast(BRIGHTPASS, VAR.tex_uv, 79 | VAR.bloom_dxdy, bloom_sigma); 80 | // Encode and output the blurred image: 81 | return encode_output(float4(color, 1.0)); 82 | } 83 | 84 | -------------------------------------------------------------------------------- /reshade/Shaders/crt-royale/lib/helper-functions-and-macros.fxh: -------------------------------------------------------------------------------- 1 | #ifndef _HELPER_FUNCTIONS_AND_MACROS_H 2 | #define _HELPER_FUNCTIONS_AND_MACROS_H 3 | 4 | ///////////////////////////////// MIT LICENSE //////////////////////////////// 5 | 6 | // Copyright (C) 2020 Alex Gunter 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal in the Software without restriction, including without limitation the 11 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12 | // sell copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24 | // IN THE SOFTWARE. 25 | 26 | 27 | float4 tex2D_nograd(sampler2D tex, float2 tex_coords) 28 | { 29 | return tex2Dlod(tex, float4(tex_coords, 0, 0), 0.0); 30 | } 31 | 32 | // ReShade 4 does not permit the use of functions or the ternary operator 33 | // outside of a function definition. This is a problem for this port 34 | // because the original crt-royale shader makes heavy use of these 35 | // constructs at the root level. 36 | 37 | // These preprocessor definitions are a workaround for this limitation. 38 | // Note that they are strictly intended for defining complex global 39 | // constants. I doubt they're more performant than the built-in 40 | // equivalents, so I recommend using the built-ins whenever you can. 41 | 42 | 43 | #define macro_sign(c) -((int) ((c) != 0)) * -((int) ((c) > 0)) 44 | #define macro_abs(c) (c) * macro_sign(c) 45 | 46 | #define macro_min(c, d) (c) * ((int) ((c) <= (d))) + (d) * ((int) ((c) > (d))) 47 | #define macro_max(c, d) (c) * ((int) ((c) >= (d))) + (d) * ((int) ((c) < (d))) 48 | #define macro_clamp(c, l, u) macro_min(macro_max(c, l), u) 49 | 50 | #define macro_ceil(c) (float) ((int) (c) + (int) (((int) (c)) < (c))) 51 | 52 | #define macro_cond(c, a, b) float(c) * (a) + float(!(c)) * (b) 53 | 54 | 55 | 56 | //////////////////////// COMMON MATHEMATICAL CONSTANTS /////////////////////// 57 | 58 | static const float pi = 3.141592653589; 59 | // We often want to find the location of the previous texel, e.g.: 60 | // const float2 curr_texel = uv * texture_size; 61 | // const float2 prev_texel = floor(curr_texel - float2(0.5)) + float2(0.5); 62 | // const float2 prev_texel_uv = prev_texel / texture_size; 63 | // However, many GPU drivers round incorrectly around exact texel locations. 64 | // We need to subtract a little less than 0.5 before flooring, and some GPU's 65 | // require this value to be farther from 0.5 than others; define it here. 66 | // const float2 prev_texel = 67 | // floor(curr_texel - float2(under_half)) + float2(0.5); 68 | static const float under_half = 0.4995; 69 | 70 | // Avoid dividing by zero; using a macro overloads for float, float2, etc.: 71 | #define FIX_ZERO(c) (macro_max(macro_abs(c), 0.0000152587890625)) // 2^-16 72 | 73 | // #define fmod(x, y) ((x) - (y) * floor((x)/(y) + FIX_ZERO(0.0))) 74 | #define fmod(x, y) (frac((x) / (y)) * (y)) 75 | 76 | #endif // _HELPER_FUNCTIONS_AND_MACROS_H -------------------------------------------------------------------------------- /reshade/Shaders/crt/crt-royale/include/helper-functions-and-macros.fxh: -------------------------------------------------------------------------------- 1 | #ifndef _HELPER_FUNCTIONS_AND_MACROS_H 2 | #define _HELPER_FUNCTIONS_AND_MACROS_H 3 | 4 | ///////////////////////////////// MIT LICENSE //////////////////////////////// 5 | 6 | // Copyright (C) 2020 Alex Gunter 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal in the Software without restriction, including without limitation the 11 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12 | // sell copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24 | // IN THE SOFTWARE. 25 | 26 | 27 | float4 tex2D_nograd(sampler2D tex, float2 tex_coords) 28 | { 29 | return tex2Dlod(tex, float4(tex_coords, 0, 0), 0.0); 30 | } 31 | 32 | // ReShade 4 does not permit the use of functions or the ternary operator 33 | // outside of a function definition. This is a problem for this port 34 | // because the original crt-royale shader makes heavy use of these 35 | // constructs at the root level. 36 | 37 | // These preprocessor definitions are a workaround for this limitation. 38 | // Note that they are strictly intended for defining complex global 39 | // constants. I doubt they're more performant than the built-in 40 | // equivalents, so I recommend using the built-ins whenever you can. 41 | 42 | 43 | #define macro_sign(c) -((int) ((c) != 0)) * -((int) ((c) > 0)) 44 | #define macro_abs(c) (c) * macro_sign(c) 45 | 46 | #define macro_min(c, d) (c) * ((int) ((c) <= (d))) + (d) * ((int) ((c) > (d))) 47 | #define macro_max(c, d) (c) * ((int) ((c) >= (d))) + (d) * ((int) ((c) < (d))) 48 | #define macro_clamp(c, l, u) macro_min(macro_max(c, l), u) 49 | 50 | #define macro_ceil(c) (float) ((int) (c) + (int) (((int) (c)) < (c))) 51 | 52 | #define macro_cond(c, a, b) float(c) * (a) + float(!(c)) * (b) 53 | 54 | 55 | 56 | //////////////////////// COMMON MATHEMATICAL CONSTANTS /////////////////////// 57 | 58 | static const float pi = 3.141592653589; 59 | // We often want to find the location of the previous texel, e.g.: 60 | // const float2 curr_texel = uv * texture_size; 61 | // const float2 prev_texel = floor(curr_texel - float2(0.5)) + float2(0.5); 62 | // const float2 prev_texel_uv = prev_texel / texture_size; 63 | // However, many GPU drivers round incorrectly around exact texel locations. 64 | // We need to subtract a little less than 0.5 before flooring, and some GPU's 65 | // require this value to be farther from 0.5 than others; define it here. 66 | // const float2 prev_texel = 67 | // floor(curr_texel - float2(under_half)) + float2(0.5); 68 | static const float under_half = 0.4995; 69 | 70 | // Avoid dividing by zero; using a macro overloads for float, float2, etc.: 71 | #define FIX_ZERO(c) (macro_max(macro_abs(c), 0.0000152587890625)) // 2^-16 72 | 73 | // #define fmod(x, y) ((x) - (y) * floor((x)/(y) + FIX_ZERO(0.0))) 74 | #define fmod(x, y) (frac((x) / (y)) * (y)) 75 | 76 | #endif // _HELPER_FUNCTIONS_AND_MACROS_H -------------------------------------------------------------------------------- /reshade/Shaders/anti-aliasing/aa-shader-4.0.fx: -------------------------------------------------------------------------------- 1 | #include "ReShade.fxh" 2 | 3 | /* 4 | Copyright (C) 2016 guest(r) - guest.r@gmail.com 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | */ 20 | 21 | uniform float2 NormalizedNativePixelSize < source = "normalized_native_pixel_size"; >; 22 | 23 | sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=CLAMP;AddressV=CLAMP;AddressW=CLAMP;MagFilter=POINT;MinFilter=POINT;}; 24 | 25 | static const float3 dt = float3(1.0,1.0,1.0); 26 | 27 | float3 texture2d(sampler2D tex, float2 coord, float4 yx) { 28 | 29 | float3 s00 = tex2D(tex, coord + yx.zw).xyz; 30 | float3 s20 = tex2D(tex, coord + yx.xw).xyz; 31 | float3 s22 = tex2D(tex, coord + yx.xy).xyz; 32 | float3 s02 = tex2D(tex, coord + yx.zy).xyz; 33 | 34 | float m1=dot(abs(s00-s22),dt)+0.001; 35 | float m2=dot(abs(s02-s20),dt)+0.001; 36 | 37 | return 0.5*(m2*(s00+s22)+m1*(s02+s20))/(m1+m2); 38 | } 39 | 40 | 41 | 42 | float4 PS_aa_shader_40(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD0) : SV_Target 43 | { 44 | // Calculating texel coordinates 45 | float2 size = 4.0 / NormalizedNativePixelSize; 46 | float2 inv_size = 1.0 / size; 47 | 48 | float4 yx = float4(inv_size, -inv_size); 49 | 50 | float2 OGL2Pos = vTexCoord * size; 51 | 52 | float2 fp = frac(OGL2Pos); 53 | float2 dx = float2(inv_size.x,0.0); 54 | float2 dy = float2(0.0, inv_size.y); 55 | float2 g1 = float2(inv_size.x,inv_size.y); 56 | float2 g2 = float2(-inv_size.x,inv_size.y); 57 | 58 | float2 pC4 = floor(OGL2Pos) * 1.0001 * inv_size; 59 | 60 | // Reading the texels 61 | float3 C1 = texture2d(sBackBuffer, pC4 - dy, yx); 62 | float3 C0 = texture2d(sBackBuffer, pC4 - g1, yx); 63 | float3 C2 = texture2d(sBackBuffer, pC4 - g2, yx); 64 | float3 C3 = texture2d(sBackBuffer, pC4 - dx, yx); 65 | float3 C4 = texture2d(sBackBuffer, pC4 , yx); 66 | float3 C5 = texture2d(sBackBuffer, pC4 + dx, yx); 67 | float3 C6 = texture2d(sBackBuffer, pC4 + g2, yx); 68 | float3 C7 = texture2d(sBackBuffer, pC4 + dy, yx); 69 | float3 C8 = texture2d(sBackBuffer, pC4 + g1, yx); 70 | 71 | float3 ul, ur, dl, dr; 72 | float m1, m2; 73 | 74 | m1 = dot(abs(C0-C4),dt)+0.001; 75 | m2 = dot(abs(C1-C3),dt)+0.001; 76 | ul = (m2*(C0+C4)+m1*(C1+C3))/(m1+m2); 77 | 78 | m1 = dot(abs(C1-C5),dt)+0.001; 79 | m2 = dot(abs(C2-C4),dt)+0.001; 80 | ur = (m2*(C1+C5)+m1*(C2+C4))/(m1+m2); 81 | 82 | m1 = dot(abs(C3-C7),dt)+0.001; 83 | m2 = dot(abs(C6-C4),dt)+0.001; 84 | dl = (m2*(C3+C7)+m1*(C6+C4))/(m1+m2); 85 | 86 | m1 = dot(abs(C4-C8),dt)+0.001; 87 | m2 = dot(abs(C5-C7),dt)+0.001; 88 | dr = (m2*(C4+C8)+m1*(C5+C7))/(m1+m2); 89 | 90 | float3 c11 = 0.5*((dr*fp.x+dl*(1-fp.x))*fp.y+(ur*fp.x+ul*(1-fp.x))*(1-fp.y) ); 91 | 92 | return float4(c11, 1.0); 93 | } 94 | 95 | 96 | 97 | technique aa_shader_40 98 | { 99 | pass 100 | { 101 | VertexShader = PostProcessVS; 102 | PixelShader = PS_aa_shader_40; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /reshade/Shaders/blur/g-sharp2-resampler.fx: -------------------------------------------------------------------------------- 1 | #include "ReShade.fxh" 2 | 3 | 4 | /* 5 | G-sharp resampler 2.0 - dynamic range (upscaler, downsampler) 6 | 7 | Copyright (C) 2024 guest(r) 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 2 12 | of the License, or (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 | 23 | */ 24 | 25 | 26 | 27 | uniform float GSHARP0 < 28 | ui_type = "drag"; 29 | ui_min = 0.75; 30 | ui_max = 8.0; 31 | ui_step = 0.05; 32 | ui_label = "Filter Range"; 33 | > = 2.45; 34 | 35 | uniform float GBOOST < 36 | ui_type = "drag"; 37 | ui_min = 1.0; 38 | ui_max = 2.5; 39 | ui_step = 0.05; 40 | ui_label = "Filter Boost (same range, speedup)"; 41 | > = 1.75; 42 | 43 | uniform float GMAXSHARP < 44 | ui_type = "drag"; 45 | ui_min = 0.0; 46 | ui_max = 0.25; 47 | ui_step = 0.01; 48 | ui_label = "Filter Sharpness"; 49 | > = 0.1; 50 | 51 | uniform float GPAR < 52 | ui_type = "drag"; 53 | ui_min = 0.0; 54 | ui_max = 1.0; 55 | ui_step = 0.10; 56 | ui_label = "Anti-Ringing"; 57 | > = 0.50; 58 | 59 | 60 | uniform float2 NormalizedNativePixelSize < source = "normalized_native_pixel_size"; >; 61 | uniform float2 NormalizedInternalPixelSize < source = "normalized_internal_pixel_size"; >; 62 | 63 | sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=CLAMP;AddressV=CLAMP;AddressW=CLAMP;MagFilter=POINT;MinFilter=POINT;}; 64 | 65 | #define GMAXSHARP (0.25*GBOOST*GBOOST*GMAXSHARP) 66 | 67 | float smothstep(float x) 68 | { 69 | return exp(-2.33*x*x); 70 | } 71 | 72 | float getw(float x) 73 | { 74 | float z = x/GBOOST; 75 | float y = smothstep(z); 76 | return max(y*y - GMAXSHARP, lerp(-GMAXSHARP, 0.0, x-1.0)); 77 | } 78 | 79 | 80 | float4 PS_GSHARP2(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD0) : SV_Target 81 | { 82 | float2 texCoord = vTexCoord; 83 | float4 SourceSize = float4(1.0 / NormalizedInternalPixelSize, NormalizedInternalPixelSize); 84 | 85 | float2 pos = vTexCoord * SourceSize.xy-0.5; 86 | float2 f = -frac(pos); 87 | float2 tex = floor(pos)*SourceSize.zw + 0.5*SourceSize.zw; 88 | float3 color = 0.0.xxx; 89 | float2 dx = float2(SourceSize.z, 0.0); 90 | float2 dy = float2(0.0, SourceSize.w); 91 | 92 | float w, fp; 93 | float wsum = 0.0; 94 | float3 pixel; 95 | float3 cmax = 0.0.xxx; 96 | float3 cmin = 1.0.xxx; 97 | float FPR = GSHARP0; 98 | float FPR2 = 2.0*FPR; 99 | float FPR3 = FPR2*FPR2; 100 | float LOOPSIZE = ceil(FPR2); 101 | float y = -LOOPSIZE+1.0; 102 | float x = 0.0; 103 | 104 | do 105 | { 106 | x = -LOOPSIZE + 1.0; 107 | 108 | do 109 | { 110 | fp = dot(float2(x+f.x,y+f.y),float2(x+f.x,y+f.y)); 111 | if (fp >= FPR3) w = 0.0; 112 | else 113 | { 114 | pixel = tex2D(sBackBuffer, tex + x*dx + y*dy).rgb; 115 | fp = sqrt(fp)/FPR; 116 | w = getw(fp); 117 | if (w >= 0.0) { cmin = min(cmin, pixel); cmax = max(cmax, pixel); } 118 | color = color + w * pixel; 119 | wsum = wsum + w; 120 | } 121 | x = x + 1.0; 122 | 123 | } while (x <= LOOPSIZE); 124 | 125 | y = y + 1.0; 126 | 127 | } while (y <= LOOPSIZE); 128 | 129 | color = color / wsum; 130 | 131 | color = lerp(clamp(color, 0.0, 1.0), clamp(color, cmin, cmax), GPAR); 132 | 133 | return float4(color, 1.0); 134 | } 135 | 136 | 137 | 138 | technique GSHARP2 139 | { 140 | pass 141 | { 142 | VertexShader = PostProcessVS; 143 | PixelShader = PS_GSHARP2; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /reshade/Shaders/crt-royale/shaders/brightpass.fxh: -------------------------------------------------------------------------------- 1 | #ifndef _BRIGHTPASS_H 2 | #define _BRIGHTPASS_H 3 | 4 | ///////////////////////////// GPL LICENSE NOTICE ///////////////////////////// 5 | 6 | // crt-royale: A full-featured CRT shader, with cheese. 7 | // Copyright (C) 2014 TroggleMonkey 8 | // 9 | // crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade. 10 | // Copyright (C) 2020 Alex Gunter 11 | // 12 | // This program is free software; you can redistribute it and/or modify it 13 | // under the terms of the GNU General Public License as published by the Free 14 | // Software Foundation; either version 2 of the License, or any later version. 15 | // 16 | // This program is distributed in the hope that it will be useful, but WITHOUT 17 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 18 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 19 | // more details. 20 | // 21 | // You should have received a copy of the GNU General Public License along with 22 | // this program; if not, write to the Free Software Foundation, Inc., 59 Temple 23 | // Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | 26 | #include "../lib/user-settings.fxh" 27 | #include "../lib/derived-settings-and-constants.fxh" 28 | #include "../lib/bind-shader-params.fxh" 29 | #include "../lib/gamma-management.fxh" 30 | #include "../lib/phosphor-mask-calculations.fxh" 31 | #include "../lib/scanline-functions.fxh" 32 | #include "../lib/bloom-functions.fxh" 33 | #include "../lib/blur-functions.fxh" 34 | 35 | 36 | void brightpassVS( 37 | in uint id : SV_VertexID, 38 | 39 | out float4 position : SV_Position, 40 | out float2 texcoord : TEXCOORD0, 41 | out float bloom_sigma_runtime : TEXCOORD1 42 | ) { 43 | PostProcessVS(id, position, texcoord); 44 | 45 | bloom_sigma_runtime = get_min_sigma_to_blur_triad(calc_triad_size().x, bloom_diff_thresh_); 46 | } 47 | 48 | void brightpassPS( 49 | in float4 pos : SV_Position, 50 | in float2 texcoord : TEXCOORD0, 51 | in float bloom_sigma_runtime : TEXCOORD1, 52 | 53 | out float4 color : SV_Target 54 | ) { 55 | // Sample the masked scanlines: 56 | const float3 intensity_dim = tex2D_linearize(samplerMaskedScanlines, texcoord, get_intermediate_gamma()).rgb; 57 | // Get the full intensity, including auto-undimming, and mask compensation: 58 | const float mask_amplify = get_mask_amplify(); 59 | const float3 intensity = intensity_dim * rcp(levels_autodim_temp) * mask_amplify * levels_contrast; 60 | 61 | // Sample BLOOM_APPROX to estimate what a straight blur of masked scanlines 62 | // would look like, so we can estimate how much energy we'll receive from 63 | // blooming neighbors: 64 | const float3 phosphor_blur_approx = levels_contrast * tex2D_linearize(samplerBloomApproxHoriz, texcoord, get_intermediate_gamma()).rgb; 65 | 66 | // Compute the blur weight for the center texel and the maximum energy we 67 | // expect to receive from neighbors: 68 | const float bloom_sigma = get_final_bloom_sigma(bloom_sigma_runtime); 69 | const float center_weight = get_center_weight(bloom_sigma); 70 | const float3 max_area_contribution_approx = 71 | max(float3(0.0, 0.0, 0.0), phosphor_blur_approx - center_weight * intensity); 72 | // Assume neighbors will blur 100% of their intensity (blur_ratio = 1.0), 73 | // because it actually gets better results (on top of being very simple), 74 | // but adjust all intensities for the user's desired underestimate factor: 75 | const float3 area_contrib_underestimate = bloom_underestimate_levels * max_area_contribution_approx; 76 | const float3 intensity_underestimate = bloom_underestimate_levels * intensity; 77 | // Calculate the blur_ratio, the ratio of intensity we want to blur: 78 | const float3 blur_ratio_temp = 79 | ((float3(1.0, 1.0, 1.0) - area_contrib_underestimate) / 80 | intensity_underestimate - float3(1.0, 1.0, 1.0)) / (center_weight - 1.0); 81 | const float3 blur_ratio = saturate(blur_ratio_temp); 82 | // Calculate the brightpass based on the auto-dimmed, unamplified, masked 83 | // scanlines, encode if necessary, and return! 84 | const float3 brightpass = intensity_dim * 85 | lerp(blur_ratio, float3(1.0, 1.0, 1.0), bloom_excess); 86 | 87 | color = encode_output(float4(brightpass, 1.0), get_intermediate_gamma()); 88 | } 89 | 90 | #endif // _BRIGHTPASS_H -------------------------------------------------------------------------------- /reshade/Shaders/crt/crt-royale/src/blur9fast-vertical.fxh: -------------------------------------------------------------------------------- 1 | ///////////////////////////////// MIT LICENSE //////////////////////////////// 2 | 3 | // Copyright (C) 2014 TroggleMonkey 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to 7 | // deal in the Software without restriction, including without limitation the 8 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | // sell copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | // IN THE SOFTWARE. 22 | 23 | 24 | ///////////////////////////// SETTINGS MANAGEMENT //////////////////////////// 25 | 26 | // PASS SETTINGS: 27 | // gamma-management.h needs to know what kind of pipeline we're using and 28 | // what pass this is in that pipeline. This will become obsolete if/when we 29 | // can #define things like this in the .cgp preset file. 30 | //#define GAMMA_ENCODE_EVERY_FBO 31 | //#define FIRST_PASS 32 | //#define LAST_PASS 33 | //#define SIMULATE_CRT_ON_LCD 34 | //#define SIMULATE_GBA_ON_LCD 35 | //#define SIMULATE_LCD_ON_CRT 36 | //#define SIMULATE_GBA_ON_CRT 37 | 38 | 39 | ////////////////////////////////// INCLUDES ////////////////////////////////// 40 | 41 | #include "../include/gamma-management.fxh" 42 | #include "../include/blur-functions.fxh" 43 | 44 | ///////////////////////////////// STRUCTURES ///////////////////////////////// 45 | 46 | struct out_vertex_p3 47 | { 48 | float2 blur_dxdy : TEXCOORD1; 49 | }; 50 | 51 | 52 | //////////////////////////////// VERTEX SHADER /////////////////////////////// 53 | 54 | 55 | // Vertex shader generating a triangle covering the entire screen 56 | void VS_Blur9Fast_Vertical(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out out_vertex_p3 OUT) 57 | { 58 | texcoord.x = (id == 2) ? 2.0 : 0.0; 59 | texcoord.y = (id == 1) ? 2.0 : 0.0; 60 | position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 61 | /* 62 | float2 texture_size = 1.0/NormalizedNativePixelSize; 63 | float2 output_size = (ViewportSize*BufferToViewportRatio); 64 | float2 video_size = 1.0/NormalizedNativePixelSize; 65 | */ 66 | // float2 texture_size = float2(320.0, 240.0); 67 | float2 texture_size = BLUR9FAST_VERTICAL_texture_size; 68 | float2 output_size = VIEWPORT_SIZE; 69 | // float2 output_size = VIEWPORT_SIZE/4.0; 70 | // float2 output_size = VIEWPORT_SIZE*NormalizedNativePixelSize/float2(320.0, 240.0); 71 | // float2 output_size = 1.0/NormalizedNativePixelSize; 72 | 73 | // Get the uv sample distance between output pixels. Blurs are not generic 74 | // Gaussian resizers, and correct blurs require: 75 | // 1.) IN.output_size == IN.video_size * 2^m, where m is an integer <= 0. 76 | // 2.) mipmap_inputN = "true" for this pass in .cgp preset if m != 0 77 | // 3.) filter_linearN = "true" except for 1x scale nearest neighbor blurs 78 | // Gaussian resizers would upsize using the distance between input texels 79 | // (not output pixels), but we avoid this and consistently blur at the 80 | // destination size. Otherwise, combining statically calculated weights 81 | // with bilinear sample exploitation would result in terrible artifacts. 82 | const float2 dxdy_scale = video_size/output_size; 83 | const float2 dxdy = dxdy_scale/texture_size; 84 | // This blur is vertical-only, so zero out the horizontal offset: 85 | OUT.blur_dxdy = float2(0.0, dxdy.y); 86 | } 87 | 88 | /////////////////////////////// FRAGMENT SHADER ////////////////////////////// 89 | 90 | float4 PS_Blur9Fast_Vertical(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in out_vertex_p3 VAR) : SV_Target 91 | { 92 | float3 color = tex2Dblur9fast(BLOOM_APPROX, vTexCoord, VAR.blur_dxdy); 93 | // Encode and output the blurred image: 94 | return encode_output(float4(color, 1.0)); 95 | } 96 | -------------------------------------------------------------------------------- /reshade/Shaders/crt/crt-royale/src/blur9fast-horizontal.fxh: -------------------------------------------------------------------------------- 1 | ///////////////////////////////// MIT LICENSE //////////////////////////////// 2 | 3 | // Copyright (C) 2014 TroggleMonkey 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to 7 | // deal in the Software without restriction, including without limitation the 8 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 | // sell copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 | // IN THE SOFTWARE. 22 | 23 | 24 | ///////////////////////////// SETTINGS MANAGEMENT //////////////////////////// 25 | 26 | // PASS SETTINGS: 27 | // gamma-management.h needs to know what kind of pipeline we're using and 28 | // what pass this is in that pipeline. This will become obsolete if/when we 29 | // can #define things like this in the .cgp preset file. 30 | //#define GAMMA_ENCODE_EVERY_FBO 31 | //#define FIRST_PASS 32 | //#define LAST_PASS 33 | //#define SIMULATE_CRT_ON_LCD 34 | //#define SIMULATE_GBA_ON_LCD 35 | //#define SIMULATE_LCD_ON_CRT 36 | //#define SIMULATE_GBA_ON_CRT 37 | 38 | 39 | ////////////////////////////////// INCLUDES ////////////////////////////////// 40 | 41 | // #included by vertex shader: 42 | #include "../include/gamma-management.fxh" 43 | #include "../include/blur-functions.fxh" 44 | 45 | ///////////////////////////////// STRUCTURES ///////////////////////////////// 46 | 47 | struct out_vertex_p4 48 | { 49 | float2 blur_dxdy : TEXCOORD1; 50 | }; 51 | 52 | 53 | //////////////////////////////// VERTEX SHADER /////////////////////////////// 54 | 55 | 56 | // Vertex shader generating a triangle covering the entire screen 57 | void VS_Blur9Fast_Horizontal(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out out_vertex_p4 OUT) 58 | { 59 | texcoord.x = (id == 2) ? 2.0 : 0.0; 60 | texcoord.y = (id == 1) ? 2.0 : 0.0; 61 | position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 62 | 63 | /* float2 texture_size = 1.0/NormalizedNativePixelSize; 64 | float2 output_size = (ViewportSize*BufferToViewportRatio); 65 | float2 video_size = 1.0/NormalizedNativePixelSize; 66 | */ 67 | // float2 texture_size = float2(320.0, 240.0); 68 | float2 texture_size = HALATION_BLUR_texture_size; 69 | float2 output_size = VIEWPORT_SIZE; 70 | // float2 output_size = VIEWPORT_SIZE*NormalizedNativePixelSize/float2(320.0, 240.0); 71 | // float2 output_size = float2(320.0, 240.0); 72 | // float2 output_size = 1.0/NormalizedNativePixelSize; 73 | 74 | // Get the uv sample distance between output pixels. Blurs are not generic 75 | // Gaussian resizers, and correct blurs require: 76 | // 1.) IN.output_size == IN.video_size * 2^m, where m is an integer <= 0. 77 | // 2.) mipmap_inputN = "true" for this pass in .cgp preset if m != 0 78 | // 3.) filter_linearN = "true" except for 1x scale nearest neighbor blurs 79 | // Gaussian resizers would upsize using the distance between input texels 80 | // (not output pixels), but we avoid this and consistently blur at the 81 | // destination size. Otherwise, combining statically calculated weights 82 | // with bilinear sample exploitation would result in terrible artifacts. 83 | const float2 dxdy_scale = video_size/output_size; 84 | const float2 dxdy = dxdy_scale/texture_size; 85 | // This blur is horizontal-only, so zero out the vertical offset: 86 | OUT.blur_dxdy = float2(dxdy.x, 0.0); 87 | } 88 | 89 | /////////////////////////////// FRAGMENT SHADER ////////////////////////////// 90 | 91 | float4 PS_Blur9Fast_Horizontal(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in out_vertex_p4 VAR) : SV_Target 92 | { 93 | float3 color = tex2Dblur9fast(BLUR9FAST_VERTICAL, vTexCoord, VAR.blur_dxdy); 94 | // Encode and output the blurred image: 95 | return encode_output(float4(color, 1.0)); 96 | } 97 | 98 | -------------------------------------------------------------------------------- /reshade/Shaders/blur/g-sharp2-resampler-fast.fx: -------------------------------------------------------------------------------- 1 | #include "ReShade.fxh" 2 | 3 | 4 | /* 5 | G-sharp resampler 2.0 - dynamic range (upscaler, downsampler) 6 | 7 | Copyright (C) 2024 guest(r) 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 2 12 | of the License, or (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 | 23 | */ 24 | 25 | 26 | 27 | uniform float GSHARP0 < 28 | ui_type = "drag"; 29 | ui_min = 0.75; 30 | ui_max = 8.0; 31 | ui_step = 0.05; 32 | ui_label = "Filter Range"; 33 | > = 2.45; 34 | 35 | uniform float GBOOST < 36 | ui_type = "drag"; 37 | ui_min = 1.0; 38 | ui_max = 2.5; 39 | ui_step = 0.05; 40 | ui_label = "Filter Boost (same range, speedup)"; 41 | > = 1.75; 42 | 43 | uniform float GMAXSHARP < 44 | ui_type = "drag"; 45 | ui_min = 0.0; 46 | ui_max = 0.25; 47 | ui_step = 0.01; 48 | ui_label = "Filter Sharpness"; 49 | > = 0.1; 50 | 51 | uniform float GPAR < 52 | ui_type = "drag"; 53 | ui_min = 0.0; 54 | ui_max = 1.0; 55 | ui_step = 0.10; 56 | ui_label = "Anti-Ringing"; 57 | > = 0.50; 58 | 59 | 60 | uniform float2 NormalizedNativePixelSize < source = "normalized_native_pixel_size"; >; 61 | uniform float2 NormalizedInternalPixelSize < source = "normalized_internal_pixel_size"; >; 62 | uniform float2 BufferToViewportRatio < source = "buffer_to_viewport_ratio"; >; 63 | uniform float2 ViewportSize < source = "viewportsize"; >; 64 | 65 | sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=CLAMP;AddressV=CLAMP;AddressW=CLAMP;MagFilter=POINT;MinFilter=POINT;}; 66 | 67 | texture2D tGSHARP2_H{Width=BUFFER_WIDTH;Height=BUFFER_HEIGHT;Format=RGBA8;}; 68 | sampler2D sGSHARP2_H{Texture=tGSHARP2_H;AddressU=CLAMP;AddressV=CLAMP;AddressW=CLAMP;MagFilter=POINT;MinFilter=POINT;}; 69 | 70 | #define GMAXSHARP (0.25*GBOOST*GBOOST*GMAXSHARP) 71 | 72 | float smothstep(float x) 73 | { 74 | return exp(-2.33*x*x); 75 | } 76 | 77 | float getw(float x) 78 | { 79 | float z = x/GBOOST; 80 | float y = smothstep(z); 81 | return max(y*y - GMAXSHARP, lerp(-GMAXSHARP, 0.0, x-1.0)); 82 | } 83 | 84 | float3 gsharp2(float2 tex, float2 dx, float f, sampler2D Source) 85 | { 86 | float3 color = 0.0.xxx; 87 | 88 | float w, fp; 89 | float wsum = 0.0; 90 | float3 pixel; 91 | float3 cmax = 0.0.xxx; 92 | float3 cmin = 1.0.xxx; 93 | float FPR = GSHARP0; 94 | float FPR2 = 2.0*FPR; 95 | float FPR3 = FPR2*FPR2; 96 | float LOOPSIZE = ceil(FPR2); 97 | float x = -LOOPSIZE+1.0; 98 | 99 | do 100 | { 101 | fp = min(abs(x+f),FPR2); 102 | pixel = tex2D(Source, tex + x*dx).rgb; 103 | fp = fp/FPR; 104 | w = getw(fp); 105 | if (w > 0.0) { cmin = min(cmin, pixel); cmax = max(cmax, pixel); } 106 | color = color + w * pixel; 107 | wsum = wsum + w; 108 | 109 | x = x + 1.0; 110 | 111 | } while (x <= LOOPSIZE); 112 | 113 | color = color / wsum; 114 | 115 | return lerp(clamp(color, 0.0, 1.0), clamp(color, cmin, cmax), GPAR); 116 | } 117 | 118 | float4 PS_GSHARP2_H(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD0) : SV_Target 119 | { 120 | float4 SourceSize = float4(1.0 / NormalizedInternalPixelSize, NormalizedInternalPixelSize); 121 | 122 | float2 pos = vTexCoord * SourceSize.xy-0.5; 123 | float f = -frac(pos.x); 124 | float2 tex = (floor(pos) + 0.5)*SourceSize.zw; 125 | float3 color; 126 | float2 dx = float2(SourceSize.z, 0.0); 127 | 128 | color = gsharp2(tex, dx, f, sBackBuffer); 129 | 130 | return float4(color, 1.0); 131 | } 132 | 133 | float4 PS_GSHARP2_V(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD0) : SV_Target 134 | { 135 | float4 SourceSize = float4((ViewportSize.x*BufferToViewportRatio.x), 1.0/NormalizedInternalPixelSize.y, 1.0/(ViewportSize.x*BufferToViewportRatio.x), NormalizedInternalPixelSize.y); 136 | 137 | float2 pos = vTexCoord * SourceSize.xy-0.5; 138 | float f = -frac(pos.y); 139 | float2 tex = (floor(pos) + 0.5)*SourceSize.zw; 140 | float3 color; 141 | float2 dy = float2(0.0, SourceSize.w); 142 | 143 | color = gsharp2(tex, dy, f, sGSHARP2_H); 144 | 145 | return float4(color, 1.0); 146 | } 147 | 148 | 149 | 150 | technique GSHARP2 151 | { 152 | pass 153 | { 154 | VertexShader = PostProcessVS; 155 | PixelShader = PS_GSHARP2_H; 156 | RenderTarget = tGSHARP2_H; 157 | } 158 | pass 159 | { 160 | VertexShader = PostProcessVS; 161 | PixelShader = PS_GSHARP2_V; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /reshade/Shaders/crt/crt-royale/src/crt-royale-first-pass-linearize-crt-gamma-bob-fields.fxh: -------------------------------------------------------------------------------- 1 | ///////////////////////////// GPL LICENSE NOTICE ///////////////////////////// 2 | 3 | // crt-royale: A full-featured CRT shader, with cheese. 4 | // Copyright (C) 2014 TroggleMonkey 5 | // 6 | // This program is free software; you can redistribute it and/or modify it 7 | // under the terms of the GNU General Public License as published by the Free 8 | // Software Foundation; either version 2 of the License, or any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, but WITHOUT 11 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 | // more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along with 16 | // this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | // Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | 20 | ///////////////////////////// SETTINGS MANAGEMENT //////////////////////////// 21 | 22 | // PASS SETTINGS: 23 | // gamma-management.h needs to know what kind of pipeline we're using and 24 | // what pass this is in that pipeline. This will become obsolete if/when we 25 | // can #define things like this in the .cgp preset file. 26 | #define FIRST_PASS 27 | #define SIMULATE_CRT_ON_LCD 28 | 29 | 30 | ////////////////////////////////// INCLUDES ////////////////////////////////// 31 | 32 | #include "../include/user-settings.fxh" 33 | #include "../include/bind-shader-params.fxh" 34 | #include "../include/gamma-management.fxh" 35 | #include "../include/scanline-functions.fxh" 36 | 37 | 38 | ///////////////////////////////// STRUCTURES ///////////////////////////////// 39 | 40 | struct out_vertex 41 | { 42 | float2 tex_uv : TEXCOORD1; 43 | float2 uv_step : TEXCOORD2; 44 | float interlaced : TEXCOORD3; 45 | }; 46 | 47 | //////////////////////////////// VERTEX SHADER /////////////////////////////// 48 | 49 | // Vertex shader generating a triangle covering the entire screen 50 | void VS_Linearize(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out out_vertex OUT) 51 | { 52 | texcoord.x = (id == 2) ? 2.0 : 0.0; 53 | texcoord.y = (id == 1) ? 2.0 : 0.0; 54 | position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 55 | 56 | OUT.tex_uv = texcoord; 57 | // OUT.tex_uv = (floor(texcoord / NormalizedNativePixelSize)+float2(0.5,0.5)) * NormalizedNativePixelSize; 58 | // Save the uv distance between texels: 59 | OUT.uv_step = NormalizedNativePixelSize; 60 | 61 | // Detect interlacing: 1.0 = true, 0.0 = false. 62 | OUT.interlaced = is_interlaced(1.0/NormalizedNativePixelSize.y); 63 | } 64 | 65 | 66 | /////////////////////////////// FRAGMENT SHADER ////////////////////////////// 67 | 68 | sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=BORDER;AddressV=BORDER;AddressW=BORDER;MagFilter=POINT;MinFilter=POINT;}; 69 | 70 | #define input_texture sBackBuffer 71 | 72 | float4 PS_Linearize(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in out_vertex VAR) : SV_Target 73 | { 74 | // Linearize the input based on CRT gamma and bob interlaced fields. 75 | // Bobbing ensures we can immediately blur without getting artifacts. 76 | // Note: TFF/BFF won't matter for sources that double-weave or similar. 77 | // VAR.tex_uv = (floor(VAR.tex_uv / NormalizedNativePixelSize)+float2(0.5,0.5)) * NormalizedNativePixelSize; 78 | 79 | if(interlace_detect) 80 | { 81 | // Sample the current line and an average of the previous/next line; 82 | // tex2D_linearize will decode CRT gamma. Don't bother branching: 83 | const float2 tex_uv = VAR.tex_uv; 84 | const float2 v_step = float2(0.0, VAR.uv_step.y); 85 | const float3 curr_line = tex2D_linearize_first( 86 | input_texture, tex_uv).rgb; 87 | const float3 last_line = tex2D_linearize_first( 88 | input_texture, tex_uv - v_step).rgb; 89 | const float3 next_line = tex2D_linearize_first( 90 | input_texture, tex_uv + v_step).rgb; 91 | const float3 interpolated_line = 0.5 * (last_line + next_line); 92 | // If we're interlacing, determine which field curr_line is in: 93 | const float modulus = VAR.interlaced + 1.0; 94 | const float field_offset = 95 | fmod(FrameCount + float(interlace_bff), modulus); 96 | const float curr_line_texel = tex_uv.y / NormalizedNativePixelSize.y; 97 | // Use under_half to fix a rounding bug around exact texel locations. 98 | const float line_num_last = floor(curr_line_texel - under_half); 99 | const float wrong_field = fmod(line_num_last + field_offset, modulus); 100 | // Select the correct color, and output the result: 101 | const float3 color = lerp(curr_line, interpolated_line, wrong_field); 102 | return encode_output(float4(color, 1.0)); 103 | } 104 | else 105 | { 106 | return encode_output(tex2D_linearize_first(input_texture, VAR.tex_uv)); 107 | } 108 | } 109 | 110 | -------------------------------------------------------------------------------- /dolphinfx/interpolation/JINC2.glsl: -------------------------------------------------------------------------------- 1 | 2 | // Hyllian's jinc windowed-jinc 2-lobe with anti-ringing Shader 3 | 4 | // Copyright (C) 2011-2024 Hyllian - sergiogdb@gmail.com 5 | 6 | // This program is free software; you can redistribute it and/or 7 | // modify it under the terms of the GNU General Public License 8 | // as published by the Free Software Foundation; either version 2 9 | // of the License, or (at your option) any later version. 10 | 11 | // This program is distributed in the hope that it will be useful, 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | // GNU General Public License for more details. 15 | 16 | // You should have received a copy of the GNU General Public License 17 | // along with this program; if not, write to the Free Software 18 | // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | /* 21 | [configuration] 22 | 23 | [OptionRangeFloat] 24 | GUIName = Window Sinc Param 25 | OptionName = JINC2_WINDOW_SINC 26 | MinValue = 0.0 27 | MaxValue = 1.0 28 | StepAmount = 0.01 29 | DefaultValue = 0.50 30 | 31 | [OptionRangeFloat] 32 | GUIName = Sinc Param 33 | OptionName = JINC2_SINC 34 | MinValue = 0.0 35 | MaxValue = 1.0 36 | StepAmount = 0.01 37 | DefaultValue = 0.88 38 | 39 | [OptionRangeFloat] 40 | GUIName = Anti-ringing Strength 41 | OptionName = JINC2_AR_STRENGTH 42 | MinValue = 0.0 43 | MaxValue = 1.0 44 | StepAmount = 0.1 45 | DefaultValue = 0.5 46 | 47 | [/configuration] 48 | */ 49 | 50 | #define halfpi 1.5707963267948966192313216916398 51 | #define pi 3.1415926535897932384626433832795 52 | #define wa (JINC2_WINDOW_SINC*pi) 53 | #define wb (JINC2_SINC*pi) 54 | 55 | // Calculates the distance between two points 56 | float d(vec2 pt1, vec2 pt2) 57 | { 58 | vec2 v = pt2 - pt1; 59 | return sqrt(dot(v,v)); 60 | } 61 | 62 | vec3 min4(vec3 a, vec3 b, vec3 c, vec3 d) 63 | { 64 | return min(a, min(b, min(c, d))); 65 | } 66 | 67 | vec3 max4(vec3 a, vec3 b, vec3 c, vec3 d) 68 | { 69 | return max(a, max(b, max(c, d))); 70 | } 71 | 72 | vec4 resampler(vec4 x) 73 | { 74 | vec4 res; 75 | res.x = (x.x==0.0) ? wa*wb : sin(x.x*wa)*sin(x.x*wb)/(x.x*x.x); 76 | res.y = (x.y==0.0) ? wa*wb : sin(x.y*wa)*sin(x.y*wb)/(x.y*x.y); 77 | res.z = (x.z==0.0) ? wa*wb : sin(x.z*wa)*sin(x.z*wb)/(x.z*x.z); 78 | res.w = (x.w==0.0) ? wa*wb : sin(x.w*wa)*sin(x.w*wb)/(x.w*x.w); 79 | return res; 80 | } 81 | 82 | void main() 83 | { 84 | vec2 SourceSize = 1.0 / GetInvNativePixelSize(); 85 | vec2 invSourceSize = 1.0 / SourceSize; 86 | vec2 vTexCoord = GetCoordinates(); 87 | 88 | vec3 color; 89 | mat4x4 weights; 90 | 91 | vec2 dx = vec2(1.0, 0.0); 92 | vec2 dy = vec2(0.0, 1.0); 93 | 94 | vec2 pc = vTexCoord*SourceSize; 95 | 96 | vec2 tc = (floor(pc-vec2(0.5,0.5))+vec2(0.5,0.5)); 97 | 98 | weights[0] = resampler(vec4(d(pc, tc -dx -dy), d(pc, tc -dy), d(pc, tc +dx -dy), d(pc, tc+2.0*dx -dy))); 99 | weights[1] = resampler(vec4(d(pc, tc -dx ), d(pc, tc ), d(pc, tc +dx ), d(pc, tc+2.0*dx ))); 100 | weights[2] = resampler(vec4(d(pc, tc -dx +dy), d(pc, tc +dy), d(pc, tc +dx +dy), d(pc, tc+2.0*dx +dy))); 101 | weights[3] = resampler(vec4(d(pc, tc -dx+2.0*dy), d(pc, tc +2.0*dy), d(pc, tc +dx+2.0*dy), d(pc, tc+2.0*dx+2.0*dy))); 102 | 103 | dx = dx * invSourceSize; 104 | dy = dy * invSourceSize; 105 | tc = tc * invSourceSize; 106 | 107 | // reading the texels 108 | 109 | vec3 c00 = SampleLocation(tc -dx -dy).xyz; 110 | vec3 c10 = SampleLocation(tc -dy).xyz; 111 | vec3 c20 = SampleLocation(tc +dx -dy).xyz; 112 | vec3 c30 = SampleLocation(tc+2.0*dx -dy).xyz; 113 | vec3 c01 = SampleLocation(tc -dx ).xyz; 114 | vec3 c11 = SampleLocation(tc ).xyz; 115 | vec3 c21 = SampleLocation(tc +dx ).xyz; 116 | vec3 c31 = SampleLocation(tc+2.0*dx ).xyz; 117 | vec3 c02 = SampleLocation(tc -dx +dy).xyz; 118 | vec3 c12 = SampleLocation(tc +dy).xyz; 119 | vec3 c22 = SampleLocation(tc +dx +dy).xyz; 120 | vec3 c32 = SampleLocation(tc+2.0*dx +dy).xyz; 121 | vec3 c03 = SampleLocation(tc -dx+2.0*dy).xyz; 122 | vec3 c13 = SampleLocation(tc +2.0*dy).xyz; 123 | vec3 c23 = SampleLocation(tc +dx+2.0*dy).xyz; 124 | vec3 c33 = SampleLocation(tc+2.0*dx+2.0*dy).xyz; 125 | 126 | // Get min/max samples 127 | vec3 min_sample = min4(c11, c21, c12, c22); 128 | vec3 max_sample = max4(c11, c21, c12, c22); 129 | 130 | color = mat4x3(c00, c10, c20, c30) * weights[0]; 131 | color+= mat4x3(c01, c11, c21, c31) * weights[1]; 132 | color+= mat4x3(c02, c12, c22, c32) * weights[2]; 133 | color+= mat4x3(c03, c13, c23, c33) * weights[3]; 134 | color = color/(dot(weights * vec4(1.0), vec4(1.0))); 135 | 136 | // Anti-ringing 137 | vec3 aux = color; 138 | color = clamp(color, min_sample, max_sample); 139 | 140 | color = mix(aux, color, JINC2_AR_STRENGTH); 141 | 142 | // final sum and weight normalization 143 | SetOutput(vec4(color, 1.0)); 144 | } 145 | -------------------------------------------------------------------------------- /reshade/Shaders/interpolation/lanczos3.fx: -------------------------------------------------------------------------------- 1 | #include "ReShade.fxh" 2 | 3 | /* 4 | Lanczos3 - Multipass code by Hyllian 2022. 5 | 6 | */ 7 | 8 | 9 | /* 10 | Copyright (C) 2010 Team XBMC 11 | http://www.xbmc.org 12 | Copyright (C) 2011 Stefanos A. 13 | http://www.opentk.com 14 | 15 | This Program is free software; you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as published by 17 | the Free Software Foundation; either version 2, or (at your option) 18 | any later version. 19 | 20 | This Program is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with XBMC; see the file COPYING. If not, write to 27 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 28 | http://www.gnu.org/copyleft/gpl.html 29 | */ 30 | 31 | uniform float L3_PRESCALE < 32 | ui_type = "drag"; 33 | ui_min = 1.0; 34 | ui_max = 8.0; 35 | ui_step = 1.0; 36 | ui_label = "Prescale factor"; 37 | > = 1.0; 38 | 39 | 40 | uniform bool LANCZOS3_ANTI_RINGING < 41 | ui_type = "radio"; 42 | ui_label = "Lanczos3 Anti-Ringing"; 43 | > = true; 44 | 45 | uniform float2 NormalizedNativePixelSize < source = "normalized_native_pixel_size"; >; 46 | uniform float BufferWidth < source = "bufferwidth"; >; 47 | 48 | texture2D tLanczos3_P0{Width=BUFFER_WIDTH;Height=BUFFER_HEIGHT;Format=RGBA8;}; 49 | sampler2D sLanczos3_P0{Texture=tLanczos3_P0;AddressU=CLAMP;AddressV=CLAMP;AddressW=CLAMP;MagFilter=POINT;MinFilter=POINT;}; 50 | 51 | 52 | #define AR_STRENGTH 1.0 53 | #define FIX(c) (max(abs(c),1e-5)) 54 | #define PI 3.1415926535897932384626433832795 55 | #define radius 3.0 56 | 57 | float3 weight3(float x) 58 | { 59 | float3 Sampling = FIX(2.0 * PI * float3(x - 1.5, x - 0.5, x + 0.5)); 60 | 61 | // Lanczos3. Note: we normalize outside this function, so no point in multiplying by radius. 62 | return sin(Sampling) * sin(Sampling / radius) / (Sampling * Sampling); 63 | } 64 | 65 | float3 lanczos3ar(float fp, float3 C0, float3 C1, float3 C2, float3 C3, float3 C4, float3 C5) 66 | { 67 | float3 w1 = weight3(0.5 - fp * 0.5); 68 | float3 w2 = weight3(1.0 - fp * 0.5); 69 | 70 | float sum = dot(w1, 1.0.xxx) + dot(w2, 1.0.xxx); 71 | w1 /= sum; 72 | w2 /= sum; 73 | 74 | float3 color = mul(w1, float3x3( C0, C2, C4 )) + mul(w2, float3x3( C1, C3, C5)); 75 | 76 | // Anti-ringing 77 | if (LANCZOS3_ANTI_RINGING == true) 78 | { 79 | float3 aux = color; 80 | float3 min_sample = min(min(C1, C2), min(C3, C4)); 81 | float3 max_sample = max(max(C1, C2), max(C3, C4)); 82 | color = clamp(color, min_sample, max_sample); 83 | color = lerp(aux, color, AR_STRENGTH*step(0.0, (C1-C2)*(C3-C4))); 84 | } 85 | 86 | return color; 87 | } 88 | 89 | 90 | 91 | float4 PS_Lanczos3_X(float4 vpos: SV_Position, float2 uv_tx : TEXCOORD) : SV_Target 92 | { 93 | // Both dimensions are unfiltered, so it looks for lores pixels. 94 | float2 ps = NormalizedNativePixelSize/L3_PRESCALE; 95 | float2 pos = uv_tx.xy/ps - float2(0.5, 0.0); 96 | float2 tc = (floor(pos) + 0.5.xx) * ps; 97 | float2 fp = frac(pos); 98 | 99 | float3 C0 = tex2D(ReShade::BackBuffer, tc + ps*float2(-2.0, 0.0)).rgb; 100 | float3 C1 = tex2D(ReShade::BackBuffer, tc + ps*float2(-1.0, 0.0)).rgb; 101 | float3 C2 = tex2D(ReShade::BackBuffer, tc + ps*float2( 0.0, 0.0)).rgb; 102 | float3 C3 = tex2D(ReShade::BackBuffer, tc + ps*float2( 1.0, 0.0)).rgb; 103 | float3 C4 = tex2D(ReShade::BackBuffer, tc + ps*float2( 2.0, 0.0)).rgb; 104 | float3 C5 = tex2D(ReShade::BackBuffer, tc + ps*float2( 3.0, 0.0)).rgb; 105 | 106 | float3 color = lanczos3ar(fp.x, C0, C1, C2, C3, C4, C5); 107 | 108 | return float4(color, 1.0); 109 | } 110 | 111 | 112 | float4 PS_Lanczos3_Y(float4 vpos: SV_Position, float2 uv_tx : TEXCOORD) : SV_Target 113 | { 114 | // One must be careful here. Horizontal dimension is already filtered, so it looks for x in hires. 115 | float2 ps = float2(1.0/BufferWidth, NormalizedNativePixelSize.y/L3_PRESCALE); 116 | float2 pos = uv_tx.xy/ps - float2(0.0, 0.5); 117 | float2 tc = (floor(pos) + 0.5.xx) * ps; 118 | float2 fp = frac(pos); 119 | 120 | float3 C0 = tex2D(sLanczos3_P0, tc + ps*float2(0.0, -2.0)).rgb; 121 | float3 C1 = tex2D(sLanczos3_P0, tc + ps*float2(0.0, -1.0)).rgb; 122 | float3 C2 = tex2D(sLanczos3_P0, tc + ps*float2(0.0, 0.0)).rgb; 123 | float3 C3 = tex2D(sLanczos3_P0, tc + ps*float2(0.0, 1.0)).rgb; 124 | float3 C4 = tex2D(sLanczos3_P0, tc + ps*float2(0.0, 2.0)).rgb; 125 | float3 C5 = tex2D(sLanczos3_P0, tc + ps*float2(0.0, 3.0)).rgb; 126 | 127 | float3 color = lanczos3ar(fp.y, C0, C1, C2, C3, C4, C5); 128 | 129 | return float4(color, 1.0); 130 | } 131 | 132 | 133 | technique Lanczos3 134 | { 135 | pass 136 | { 137 | VertexShader = PostProcessVS; 138 | PixelShader = PS_Lanczos3_X; 139 | RenderTarget = tLanczos3_P0; 140 | } 141 | pass 142 | { 143 | VertexShader = PostProcessVS; 144 | PixelShader = PS_Lanczos3_Y; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /reshade/Shaders/denoisers/bilateral.fx: -------------------------------------------------------------------------------- 1 | #include "ReShade.fxh" 2 | 3 | /* 4 | Bilateral - Smart 5 | 6 | Copyright (C) 2024 guest(r) 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | */ 23 | 24 | 25 | uniform float FRANGE < 26 | ui_type = "drag"; 27 | ui_min = 1.0; 28 | ui_max = 10.0; 29 | ui_step = 1.0; 30 | ui_label = "Filter Range"; 31 | > = 5.0; 32 | 33 | uniform float FBSMOOTH < 34 | ui_type = "drag"; 35 | ui_min = 0.05; 36 | ui_max = 1.0; 37 | ui_step = 0.025; 38 | ui_label = "Filter Base Smoothing"; 39 | > = 0.3; 40 | 41 | uniform float FSIGMA < 42 | ui_type = "drag"; 43 | ui_min = 0.15; 44 | ui_max = 1.5; 45 | ui_step = 0.05; 46 | ui_label = "Filter Strength"; 47 | > = 1.0; 48 | 49 | uniform float2 NormalizedNativePixelSize < source = "normalized_native_pixel_size"; >; 50 | uniform float2 BufferToViewportRatio < source = "buffer_to_viewport_ratio"; >; 51 | uniform float2 ViewportSize < source = "viewportsize"; >; 52 | 53 | sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=CLAMP;AddressV=CLAMP;AddressW=CLAMP;MagFilter=POINT;MinFilter=POINT;}; 54 | 55 | texture2D tBilateral_P0{Width=BUFFER_WIDTH;Height=BUFFER_HEIGHT;Format=RGBA8;}; 56 | sampler2D sBilateral_P0{Texture=tBilateral_P0;AddressU=CLAMP;AddressV=CLAMP;AddressW=CLAMP;MagFilter=POINT;MinFilter=POINT;}; 57 | 58 | #define FSIGMA1 (1.0/FSIGMA) 59 | 60 | #define COMPAT_TEXTURE(c,d) tex2D(c,d) 61 | 62 | float wt(float3 A, float3 B) 63 | { 64 | return clamp(FBSMOOTH - 2.33*dot(abs(A-B),1.0.xxx)/(dot(A+B,1.0.xxx)+1.0), 0.0, 0.25); 65 | } 66 | 67 | 68 | float getw(float x, float3 c, float3 p) 69 | { 70 | float y = pow(max(1.0-x,0.0), FSIGMA1); 71 | float d = wt(c,p); 72 | return y*d; 73 | } 74 | 75 | 76 | 77 | float4 PS_Bilateral_X(float4 position: SV_Position, float2 vTexCoord : TEXCOORD) : SV_Target 78 | { 79 | float4 SourceSize = float4((ViewportSize*BufferToViewportRatio), 1.0/(ViewportSize*BufferToViewportRatio)); 80 | // float4 SourceSize = float4(1.0/NormalizedNativePixelSize, NormalizedNativePixelSize); 81 | float2 pos = vTexCoord * SourceSize.xy; 82 | float f = 0.5-frac(pos.x); 83 | float2 tex = floor(pos)*SourceSize.zw + 0.5*SourceSize.zw; 84 | float2 dx = float2(SourceSize.z, 0.0); 85 | 86 | float w, fp; 87 | float wsum = 0.0; 88 | float3 pixel; 89 | float FPR = FRANGE; 90 | float FPR1 = 1.0/FPR; 91 | float LOOPSIZE = FPR; 92 | float x = -FPR; 93 | 94 | float3 comp = COMPAT_TEXTURE(sBackBuffer, tex).rgb; 95 | float3 color = 0.0.xxx; 96 | 97 | do 98 | { 99 | pixel = COMPAT_TEXTURE(sBackBuffer, tex + x*dx).rgb; 100 | fp = min(abs(x+f),FPR)*FPR1; 101 | w = getw(fp,comp,pixel); 102 | color = color + w * pixel; 103 | wsum = wsum + w; 104 | 105 | x = x + 1.0; 106 | 107 | } while (x <= LOOPSIZE); 108 | 109 | color = color / wsum; 110 | 111 | return float4(color, 1.0); 112 | } 113 | 114 | 115 | float4 PS_Bilateral_Y(float4 position: SV_Position, float2 vTexCoord : TEXCOORD) : SV_Target 116 | { 117 | float4 SourceSize = float4((ViewportSize*BufferToViewportRatio), 1.0/(ViewportSize*BufferToViewportRatio)); 118 | float2 pos = vTexCoord * SourceSize.xy; 119 | float f = 0.5-frac(pos.y); 120 | float2 tex = floor(pos)*SourceSize.zw + 0.5*SourceSize.zw; 121 | float2 dy = float2(0.0, SourceSize.w); 122 | 123 | float w, fp; 124 | float wsum = 0.0; 125 | float3 pixel; 126 | float FPR = FRANGE; 127 | float FPR1 = 1.0/FPR; 128 | float LOOPSIZE = FPR; 129 | float y = -FPR; 130 | 131 | float3 comp = COMPAT_TEXTURE(sBilateral_P0, tex).rgb; 132 | float3 color = 0.0.xxx; 133 | 134 | do 135 | { 136 | pixel = COMPAT_TEXTURE(sBilateral_P0, tex + y*dy).rgb; 137 | fp = min(abs(y+f),FPR)*FPR1; 138 | w = getw(fp,comp,pixel); 139 | color = color + w * pixel; 140 | wsum = wsum + w; 141 | 142 | y = y + 1.0; 143 | 144 | } while (y <= LOOPSIZE); 145 | 146 | color = color / wsum; 147 | 148 | return float4(color, 1.0); 149 | } 150 | 151 | technique Bilateral 152 | { 153 | 154 | pass 155 | { 156 | VertexShader = PostProcessVS; 157 | PixelShader = PS_Bilateral_X; 158 | RenderTarget = tBilateral_P0; 159 | } 160 | pass 161 | { 162 | VertexShader = PostProcessVS; 163 | PixelShader = PS_Bilateral_Y; 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /reshade/Shaders/misc/deblur-luma.fx: -------------------------------------------------------------------------------- 1 | #include "ReShade.fxh" 2 | 3 | /* 4 | Deblur-Luma Shader 5 | 6 | Copyright (C) 2005 - 2024 guest(r) - guest.r@gmail.com 7 | 8 | Luma adaptation by Hyllian 9 | 10 | This program is free software; you can redistribute it and/or 11 | modify it under the terms of the GNU General Public License 12 | as published by the Free Software Foundation; either version 2 13 | of the License, or (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program; if not, write to the Free Software 22 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 | */ 24 | 25 | uniform float OFFSET < 26 | ui_type = "drag"; 27 | ui_min = 0.25; 28 | ui_max = 4.0; 29 | ui_step = 0.25; 30 | ui_label = "Deblur offset"; 31 | > = 2.0; 32 | 33 | uniform float DEBLUR < 34 | ui_type = "drag"; 35 | ui_min = 1.0; 36 | ui_max = 7.0; 37 | ui_step = 0.25; 38 | ui_label = "Deblur str."; 39 | > = 1.75; 40 | 41 | uniform float SMART < 42 | ui_type = "drag"; 43 | ui_min = 0.0; 44 | ui_max = 1.0; 45 | ui_step = 0.05; 46 | ui_label = "Smart deblur"; 47 | > = 1.0; 48 | 49 | uniform float2 ViewportSize < source = "viewportsize"; >; 50 | 51 | 52 | static const float3 luma = float3(0.299,0.587,0.114); 53 | static const float4 res = float4(0.0001, 0.0001, 0.0001, 0.0001); 54 | static const float4 uno = float4(1.,1.,1.,1.); 55 | 56 | 57 | float min8(float4 a4, float4 b4) 58 | { 59 | float4 ab4 = min(a4, b4); float2 ab2 = min(ab4.xy, ab4.zw); return min(ab2.x, ab2.y); 60 | } 61 | 62 | float max8(float4 a4, float4 b4) 63 | { 64 | float4 ab4 = max(a4, b4); float2 ab2 = max(ab4.xy, ab4.zw); return max(ab2.x, ab2.y); 65 | } 66 | 67 | 68 | struct ST_VertexOut 69 | { 70 | float4 t1 : TEXCOORD1; 71 | float4 t2 : TEXCOORD2; 72 | float4 t3 : TEXCOORD3; 73 | }; 74 | 75 | 76 | // Vertex shader generating a triangle covering the entire screen 77 | void VS_Deblur_Luma(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out ST_VertexOut vVARS) 78 | { 79 | texcoord.x = (id == 2) ? 2.0 : 0.0; 80 | texcoord.y = (id == 1) ? 2.0 : 0.0; 81 | position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 82 | 83 | float dx = OFFSET/ViewportSize.x; 84 | float dy = OFFSET/ViewportSize.y; 85 | 86 | vVARS.t1 = texcoord.xxxy + float4( -dx, 0.0, dx, -dy); // c00 c10 c20 87 | vVARS.t2 = texcoord.xxxy + float4( -dx, 0.0, dx, 0.0); // c01 c11 c21 88 | vVARS.t3 = texcoord.xxxy + float4( -dx, 0.0, dx, dy); // c02 c12 c22 89 | } 90 | 91 | 92 | float4 PS_Deblur_Luma(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in ST_VertexOut vVARS) : SV_Target 93 | { 94 | 95 | float3 c11 = tex2D(ReShade::BackBuffer, vVARS.t2.yw).xyz; 96 | float3 c00 = tex2D(ReShade::BackBuffer, vVARS.t1.xw).xyz; 97 | float3 c20 = tex2D(ReShade::BackBuffer, vVARS.t1.zw).xyz; 98 | float3 c22 = tex2D(ReShade::BackBuffer, vVARS.t3.zw).xyz; 99 | float3 c02 = tex2D(ReShade::BackBuffer, vVARS.t3.xw).xyz; 100 | float3 c10 = tex2D(ReShade::BackBuffer, vVARS.t1.yw).xyz; 101 | float3 c21 = tex2D(ReShade::BackBuffer, vVARS.t2.zw).xyz; 102 | float3 c12 = tex2D(ReShade::BackBuffer, vVARS.t3.yw).xyz; 103 | float3 c01 = tex2D(ReShade::BackBuffer, vVARS.t2.xw).xyz; 104 | 105 | float4x3 chv = float4x3(c10, c01, c21, c12); 106 | float4x3 cdi = float4x3(c00, c02, c20, c22); 107 | 108 | float4 CHV = mul(chv, luma); 109 | float4 CDI = mul(cdi, luma); 110 | float C11 = dot(c11, luma); 111 | 112 | float mn1 = min8(CHV, CDI); 113 | float mx1 = max8(CHV, CDI); 114 | 115 | float2 mnmx = float2(min(C11, mn1), max(C11, mx1)); 116 | 117 | float2 dif = abs(float2(C11, C11) - mnmx) + res.xy; 118 | 119 | dif = pow(dif, float2(DEBLUR, DEBLUR)); 120 | 121 | float D11 = dot(dif, mnmx.yx)/(dif.x + dif.y); 122 | 123 | float k11 = 1.0/(abs(C11 - D11) + res.x); 124 | 125 | float4 khv = float4(1.0/(abs(CHV-float4(D11, D11, D11, D11)) + res)); 126 | float4 kdi = float4(1.0/(abs(CDI-float4(D11, D11, D11, D11)) + res)); 127 | 128 | float avg = (dot(khv + kdi, uno) + k11)/10.0; 129 | 130 | khv = max(khv-float4(avg, avg, avg, avg), float4(0.0, 0.0, 0.0, 0.0)); 131 | kdi = max(kdi-float4(avg, avg, avg, avg), float4(0.0, 0.0, 0.0, 0.0)); 132 | k11 = max(k11-avg, 0.0); 133 | 134 | float3 d11 = (mul(khv, chv) + mul(kdi, cdi) + (k11 + res.x)*c11) / (dot(khv + kdi, uno) + k11 + res.x); 135 | 136 | float contrast = mnmx.y - mnmx.x; 137 | c11 = lerp(c11, d11, clamp(1.75*contrast-0.125, 0.0, 1.0)); 138 | c11 = lerp(d11, c11, SMART); 139 | 140 | return float4(c11, 1.0); 141 | } 142 | 143 | 144 | technique Deblur_Luma 145 | { 146 | pass 147 | { 148 | VertexShader = VS_Deblur_Luma; 149 | PixelShader = PS_Deblur_Luma; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /dolphinfx/crt/ZFAST-CRT-COMPOSITE.glsl: -------------------------------------------------------------------------------- 1 | // zfast_crt - A very simple CRT shader. 2 | 3 | // Copyright (C) 2017 Greg Hogan (SoltanGris42) 4 | // edited by metallic 77. 5 | // ported to slang by gregoricavichioli & hunterk. 6 | // ported to dolphinfx by Hyllian. 7 | 8 | // This program is free software; you can redistribute it and/or modify it 9 | // under the terms of the GNU General Public License as published by the Free 10 | // Software Foundation; either version 2 of the License, or (at your option) 11 | // any later version. 12 | 13 | 14 | /* 15 | [configuration] 16 | 17 | [OptionRangeFloat] 18 | GUIName = Curvature 19 | OptionName = Curvature 20 | MinValue = 0.0 21 | MaxValue = 1.0 22 | StepAmount = 1.0 23 | DefaultValue = 1.0 24 | 25 | [OptionRangeFloat] 26 | GUIName = Convergence X-Axis 27 | OptionName = blurx 28 | MinValue = -1.0 29 | MaxValue = 2.0 30 | StepAmount = 0.05 31 | DefaultValue = 0.85 32 | 33 | [OptionRangeFloat] 34 | GUIName = Convergence Y-Axis 35 | OptionName = blury 36 | MinValue = -1.0 37 | MaxValue = 1.0 38 | StepAmount = 0.05 39 | DefaultValue = -0.10 40 | 41 | [OptionRangeFloat] 42 | GUIName = Scanline Amount (Low) 43 | OptionName = HIGHSCANAMOUNT1 44 | MinValue = 0.0 45 | MaxValue = 1.0 46 | StepAmount = 0.05 47 | DefaultValue = 0.4 48 | 49 | [OptionRangeFloat] 50 | GUIName = Scanline Amount (High) 51 | OptionName = HIGHSCANAMOUNT2 52 | MinValue = 0.0 53 | MaxValue = 1.0 54 | StepAmount = 0.05 55 | DefaultValue = 0.3 56 | 57 | [OptionRangeFloat] 58 | GUIName = Mask Type 59 | OptionName = TYPE 60 | MinValue = 0.0 61 | MaxValue = 1.0 62 | StepAmount = 1.0 63 | DefaultValue = 0.0 64 | 65 | [OptionRangeFloat] 66 | GUIName = Mask Effect Amount 67 | OptionName = MASK_DARK 68 | MinValue = 0.0 69 | MaxValue = 1.0 70 | StepAmount = 0.05 71 | DefaultValue = 0.3 72 | 73 | [OptionRangeFloat] 74 | GUIName = Mask/Scanline Fade 75 | OptionName = MASK_FADE 76 | MinValue = 0.0 77 | MaxValue = 1.0 78 | StepAmount = 0.05 79 | DefaultValue = 0.7 80 | 81 | [OptionRangeFloat] 82 | GUIName = Saturation 83 | OptionName = sat 84 | MinValue = 0.0 85 | MaxValue = 3.0 86 | StepAmount = 0.05 87 | DefaultValue = 1.0 88 | 89 | [OptionRangeFloat] 90 | GUIName = Flicker 91 | OptionName = FLICK 92 | MinValue = 0.0 93 | MaxValue = 50.0 94 | StepAmount = 1.0 95 | DefaultValue = 10.0 96 | 97 | [/configuration] 98 | */ 99 | 100 | #define pi 3.14159 101 | 102 | #define blur_y GetOption(blury)/(SourceSize.y*2.0) 103 | #define blur_x GetOption(blurx)/(SourceSize.x*2.0) 104 | #define iTimer (float(GetTime())*2.0) 105 | #define flicker GetOption(FLICK)/1000.0 106 | 107 | // Distortion of scanlines, and end of screen alpha. 108 | vec2 Warp(vec2 pos) 109 | { 110 | pos = pos*2.0-1.0; 111 | pos *= vec2(1.0 + (pos.y*pos.y)*0.03, 1.0 + (pos.x*pos.x)*0.05); 112 | 113 | return pos*0.5 + 0.5; 114 | } 115 | 116 | 117 | void main() 118 | { 119 | vec2 vTexCoord = GetCoordinates(); 120 | vec2 texSize = 1.0 / GetInvNativePixelSize(); 121 | vec4 SourceSize = vec4(texSize, 1.0 / texSize); 122 | 123 | float maskFade = 0.3333*GetOption(MASK_FADE); 124 | float omega = 2.0*pi*SourceSize.y; 125 | 126 | vec2 pos,corn; 127 | if (GetOption(Curvature) == 1.0) 128 | { 129 | pos = Warp(vTexCoord.xy); 130 | corn = min(pos,vec2(1.0)-pos); // This is used to mask the rounded 131 | corn.x = 0.00001/corn.x; // corners later on 132 | 133 | } 134 | 135 | else pos = vTexCoord; 136 | float OGL2Pos = pos.y*SourceSize.y; 137 | float cent = floor(OGL2Pos)+0.5; 138 | float ycoord = cent*SourceSize.w; 139 | ycoord = mix(pos.y,ycoord,0.6); 140 | pos = vec2(pos.x,ycoord); 141 | 142 | 143 | vec3 sample1 = sin(iTimer)*flicker + SampleLocation(vec2(pos.x + blur_x, pos.y - blur_y)).rgb; 144 | vec3 sample2 = 0.5*SampleLocation(pos).rgb; 145 | vec3 sample3 = sin(iTimer)*flicker + SampleLocation(vec2(pos.x - blur_x, pos.y + blur_y)).rgb; 146 | 147 | vec3 colour = vec3 (sample1.r*0.5 + sample2.r, 148 | sample1.g*0.25 + sample2.g + sample3.g*0.25, 149 | sample2.b + sample3.b*0.5); 150 | 151 | vec3 interl = colour; 152 | vec3 lumweight=vec3(0.22,0.71,0.07); 153 | float lumsat = dot(colour,lumweight); 154 | 155 | vec3 graycolour = vec3(lumsat); 156 | colour = vec3(mix(graycolour,colour.rgb,sat)); 157 | 158 | float SCANAMOUNT = mix(GetOption(HIGHSCANAMOUNT1),GetOption(HIGHSCANAMOUNT2),max(max(colour.r,colour.g),colour.b)); 159 | 160 | 161 | if (SourceSize.y > 400.0) { 162 | colour ; 163 | } 164 | else { 165 | colour *= SCANAMOUNT * sin(fract(OGL2Pos)*3.14159)+1.0-SCANAMOUNT; 166 | colour *= SCANAMOUNT * sin(fract(1.0-OGL2Pos)*3.14159)+1.0-SCANAMOUNT; 167 | colour *= SCANAMOUNT * sin(fract(1.0+OGL2Pos)*3.14159)+1.0-SCANAMOUNT; 168 | } 169 | 170 | float steps; if (GetOption(TYPE) == 0.0) steps = 0.5; else steps = 0.3333; 171 | float whichmask = fract(vTexCoord.x*GetWindowSize().x*steps); 172 | float mask = 1.0 + float(whichmask < steps) * (-GetOption(MASK_DARK)); 173 | 174 | colour.rgb = mix(mask*colour, colour, dot(colour.rgb,vec3(maskFade))); 175 | 176 | if (GetOption(Curvature) == 1.0 && corn.y < corn.x || GetOption(Curvature) == 1.0 && corn.x < 0.00001 ) 177 | colour = vec3(0.0); 178 | 179 | SetOutput(vec4(colour.rgb, 1.0)); 180 | } 181 | -------------------------------------------------------------------------------- /reshade/Shaders/crt/crt-geo-zfast.fx: -------------------------------------------------------------------------------- 1 | #include "ReShade.fxh" 2 | 3 | /* 4 | zfast_crt_geo - A simple, fast CRT shader. 5 | 6 | Copyright (C) 2017 Greg Hogan (SoltanGris42) 7 | Copyright (C) 2023 Jose Linares (Dogway) 8 | 9 | This program is free software; you can redistribute it and/or modify it 10 | under the terms of the GNU General Public License as published by the Free 11 | Software Foundation; either version 2 of the License, or (at your option) 12 | any later version. 13 | 14 | 15 | Notes: This shader does scaling with a weighted linear filter 16 | based on the algorithm by Iñigo Quilez here: 17 | https://iquilezles.org/articles/texture/ 18 | but modified to be somewhat sharper. Then a scanline effect that varies 19 | based on pixel brightness is applied along with a monochrome aperture mask. 20 | This shader runs at ~60fps on the Chromecast HD (10GFlops) on a 1080p display. 21 | (https://forums.libretro.com/t/android-googletv-compatible-shaders-nitpicky) 22 | 23 | Dogway: I modified zfast_crt.glsl shader to include screen curvature, 24 | vignetting, round corners and phosphor*temperature. Horizontal pixel is left out 25 | from the Quilez' algo (read above) to provide a more S-Video like horizontal blur. 26 | The scanlines and mask are also now performed in the recommended linear light. 27 | For this to run smoothly on GPU deprived platforms like the Chromecast and 28 | older consoles, I had to remove several parameters and hardcode them into the shader. 29 | Another POV is to run the shader on handhelds like the Switch or SteamDeck so they consume less battery. 30 | 31 | */ 32 | 33 | 34 | uniform float SCANLINE_WEIGHT < 35 | ui_type = "drag"; 36 | ui_min = 0.0; 37 | ui_max = 15.0; 38 | ui_step = 0.5; 39 | ui_label = "Scanline Amount"; 40 | > = 7.0; 41 | 42 | uniform float MASK_DARK < 43 | ui_type = "drag"; 44 | ui_min = 0.0; 45 | ui_max = 1.0; 46 | ui_step = 0.05; 47 | ui_label = "Mask Effect Amount"; 48 | > = 0.5; 49 | 50 | uniform float2 NormalizedNativePixelSize < source = "normalized_native_pixel_size"; >; 51 | uniform float BufferWidth < source = "bufferwidth"; >; 52 | uniform float BufferHeight < source = "bufferheight"; >; 53 | 54 | sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=CLAMP;AddressV=CLAMP;AddressW=CLAMP;MagFilter=LINEAR;MinFilter=LINEAR;}; 55 | 56 | struct ST_VertexOut 57 | { 58 | float2 invDims : TEXCOORD1; 59 | }; 60 | 61 | // Vertex shader generating a triangle covering the entire screen 62 | void VS_CRT_Geo_zFast(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out ST_VertexOut vVARS) 63 | { 64 | texcoord.x = (id == 2) ? 2.0 : 0.0; 65 | texcoord.y = (id == 1) ? 2.0 : 0.0; 66 | position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 67 | 68 | vVARS.invDims = NormalizedNativePixelSize; 69 | } 70 | 71 | 72 | #define MSCL (BufferHeight > 1499.0 ? 0.3333 : 0.5) 73 | // This compensates the scanline+mask embedded gamma from the beam dynamics 74 | #define pwr ((1.0/((-0.0325*SCANLINE_WEIGHT+1.0)*(-0.311*MASK_DARK+1.0))-1.2).xxx) 75 | 76 | 77 | 78 | // NTSC-J (D93) -> Rec709 D65 Joint Matrix (with D93 simulation) 79 | // This is compensated for a linearization hack (RGB*RGB and then sqrt()) 80 | static const float3x3 P22D93 = float3x3( 81 | 1.00000, 0.00000, -0.06173, 82 | 0.07111, 0.96887, -0.01136, 83 | 0.00000, 0.08197, 1.07280); 84 | 85 | 86 | // Returns gamma corrected output, compensated for scanline+mask embedded gamma 87 | float3 inv_gamma(float3 col, float3 power) 88 | { 89 | float3 cir = col-1.0; 90 | cir *= cir; 91 | col = lerp(sqrt(col),sqrt(1.0-cir),power); 92 | return col; 93 | } 94 | 95 | float2 Warp(float2 pos) 96 | { 97 | pos = pos*2.0-1.0; 98 | pos *= float2(1.0 + (pos.y*pos.y)*0.0276, 1.0 + (pos.x*pos.x)*0.0414); 99 | return pos*0.5 + 0.5; 100 | } 101 | 102 | 103 | float4 PS_CRT_Geo_zFast(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD0, in ST_VertexOut vVARS) : SV_Target 104 | { 105 | float2 pos = vTexCoord; 106 | float2 xy = Warp(pos); 107 | 108 | float2 corn = min(xy,1.0-xy); // This is used to mask the rounded 109 | corn.x = 0.0001/corn.x; // corners later on 110 | 111 | pos *= (1.0 - pos.xy); 112 | float vig = pos.x * pos.y * 46.0; 113 | vig = min(sqrt(vig), 1.0); 114 | 115 | 116 | // Of all the pixels that are mapped onto the texel we are 117 | // currently rendering, which pixel are we currently rendering? 118 | float ratio_scale = xy.y / NormalizedNativePixelSize.y - 0.5; 119 | // Snap to the center of the underlying texel. 120 | float i = floor(ratio_scale) + 0.5; 121 | 122 | // This is just like "Quilez Scaling" but sharper 123 | float f = ratio_scale - i; 124 | float Y = f*f; 125 | float p = (i + 4.0*Y*f)*vVARS.invDims.y; 126 | 127 | float whichmask = floor(vTexCoord.x*BufferWidth)*(-MSCL); 128 | float mask = 1.0 + float(frac(whichmask) < MSCL)*(-MASK_DARK); 129 | float3 colour = tex2D(sBackBuffer, float2(xy.x,p)).rgb; 130 | 131 | colour = max(mul(P22D93 * vig, colour*colour), 0.0.xxx); 132 | 133 | float scanLineWeight = (1.5 - SCANLINE_WEIGHT*(Y - Y*Y)); 134 | 135 | if (corn.y <= corn.x || corn.x < 0.0001 ) 136 | colour = 0.0.xxx; 137 | 138 | return float4(inv_gamma(colour.rgb*lerp(scanLineWeight*mask, 1.0, colour.r*0.26667+colour.g*0.26667+colour.b*0.26667),pwr),1.0); 139 | } 140 | 141 | 142 | 143 | technique CRT_Geo_zFast 144 | { 145 | pass 146 | { 147 | VertexShader = VS_CRT_Geo_zFast; 148 | PixelShader = PS_CRT_Geo_zFast; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /reshade/Shaders/crt-royale/shaders/deinterlace.fxh: -------------------------------------------------------------------------------- 1 | #ifndef _DEINTERLACE_H 2 | #define _DEINTERLACE_H 3 | 4 | ///////////////////////////////// MIT LICENSE //////////////////////////////// 5 | 6 | // Copyright (C) 2020 Alex Gunter 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal in the Software without restriction, including without limitation the 11 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12 | // sell copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24 | // IN THE SOFTWARE. 25 | 26 | 27 | #include "../lib/user-settings.fxh" 28 | #include "../lib/derived-settings-and-constants.fxh" 29 | #include "../lib/bind-shader-params.fxh" 30 | #include "../lib/gamma-management.fxh" 31 | #include "../lib/scanline-functions.fxh" 32 | 33 | 34 | 35 | void freezeFrameVS( 36 | in uint id : SV_VertexID, 37 | 38 | out float4 position : SV_Position, 39 | out float2 texcoord : TEXCOORD0 40 | ) { 41 | float use_deinterlacing_tex = enable_interlacing && ( 42 | scanline_deinterlacing_mode == 2 || scanline_deinterlacing_mode == 3 43 | ); 44 | 45 | texcoord.x = (id == 2) ? use_deinterlacing_tex*2.0 : 0.0; 46 | texcoord.y = (id == 1) ? 2.0 : 0.0; 47 | position = float4(texcoord * float2(2, -2) + float2(-1, 1), 0, 1); 48 | } 49 | 50 | void freezeFramePS( 51 | in float4 pos : SV_Position, 52 | in float2 texcoord : TEXCOORD0, 53 | 54 | out float4 color : SV_Target 55 | ) { 56 | color = tex2D(samplerBeamConvergence, texcoord); 57 | } 58 | 59 | 60 | void deinterlaceVS( 61 | in uint id : SV_VertexID, 62 | 63 | out float4 position : SV_Position, 64 | out float2 texcoord : TEXCOORD0, 65 | out float2 v_step : TEXCOORD1 66 | ) { 67 | freezeFrameVS(id, position, texcoord); 68 | 69 | v_step = float2(0.0, scanline_thickness * rcp(TEX_FREEZEFRAME_HEIGHT)); 70 | } 71 | 72 | 73 | void deinterlacePS( 74 | in float4 pos : SV_Position, 75 | in float2 texcoord : TEXCOORD0, 76 | in float2 v_step : TEXCOORD1, 77 | 78 | out float4 color : SV_Target 79 | ) { 80 | // float2 scanline_offset_norm; 81 | // float triangle_wave_freq; 82 | // bool field_parity; 83 | // bool wrong_field; 84 | // calc_wrong_field(texcoord, scanline_offset_norm, triangle_wave_freq, field_parity, wrong_field); 85 | 86 | float2 rotated_coord = lerp(texcoord.yx, texcoord, geom_rotation_mode == 0 || geom_rotation_mode == 2); 87 | float scale = lerp(CONTENT_WIDTH, CONTENT_HEIGHT, geom_rotation_mode == 0 || geom_rotation_mode == 2); 88 | 89 | InterpolationFieldData interpolation_data = calc_interpolation_field_data(rotated_coord, scale); 90 | 91 | // TODO: add scanline_parity to calc_wrong_field() 92 | 93 | // Weaving 94 | // Sample texcoord from this frame and the previous frame 95 | // If we're in the correct field, use the current sample 96 | // If we're in the wrong field, average the current and prev samples 97 | // In this case, we're probably averaging a color with 0 and producing a brightness of 0.5. 98 | [branch] 99 | if (enable_interlacing && scanline_deinterlacing_mode == 2) { 100 | // const float cur_scanline_idx = get_curr_scanline_idx(texcoord.y, content_size.y); 101 | // const float wrong_field = curr_line_is_wrong_field(cur_scanline_idx); 102 | 103 | const float4 cur_line_color = tex2D_nograd(samplerBeamConvergence, texcoord); 104 | const float4 cur_line_prev_color = tex2D_nograd(samplerFreezeFrame, texcoord); 105 | 106 | const float4 avg_color = (cur_line_color + cur_line_prev_color) / 2.0; 107 | 108 | // Multiply by 1.5, so each pair of scanlines has total brightness 2 109 | const float4 raw_out_color = lerp(1.5*cur_line_color, avg_color, interpolation_data.wrong_field); 110 | color = encode_output(raw_out_color, deinterlacing_blend_gamma); 111 | } 112 | // Blended Weaving 113 | // Sample texcoord from this frame 114 | // From the previous frame, sample the current scanline's sibling 115 | // Do this by shifting up or down by a line 116 | // If we're in the correct field, use the current sample 117 | // If we're in the wrong field, average the current and prev samples 118 | // In this case, we're averaging two fully illuminated colors 119 | else if (enable_interlacing && scanline_deinterlacing_mode == 3) { 120 | const float2 raw_offset = lerp(1, -1, interpolation_data.scanline_parity) * v_step; 121 | const float2 curr_offset = lerp(0, raw_offset, interpolation_data.wrong_field); 122 | const float2 prev_offset = lerp(raw_offset, 0, interpolation_data.wrong_field); 123 | 124 | const float4 cur_line_color = tex2D_nograd(samplerBeamConvergence, texcoord + curr_offset); 125 | const float4 prev_line_color = tex2D_nograd(samplerFreezeFrame, texcoord + prev_offset); 126 | 127 | const float4 avg_color = (cur_line_color + prev_line_color) / 2.0; 128 | const float4 raw_out_color = lerp(cur_line_color, avg_color, interpolation_data.wrong_field); 129 | color = encode_output(raw_out_color, deinterlacing_blend_gamma); 130 | } 131 | // No temporal blending 132 | else { 133 | color = tex2D_nograd(samplerBeamConvergence, texcoord); 134 | } 135 | } 136 | 137 | #endif // _DEINTERLACE_H -------------------------------------------------------------------------------- /reshade/Shaders/crt/crt-royale/src/crt-royale-bloom-horizontal-reconstitute.fxh: -------------------------------------------------------------------------------- 1 | ///////////////////////////// GPL LICENSE NOTICE ///////////////////////////// 2 | 3 | // crt-royale: A full-featured CRT shader, with cheese. 4 | // Copyright (C) 2014 TroggleMonkey 5 | // 6 | // This program is free software; you can redistribute it and/or modify it 7 | // under the terms of the GNU General Public License as published by the Free 8 | // Software Foundation; either version 2 of the License, or any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, but WITHOUT 11 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 | // more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along with 16 | // this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | // Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | 20 | ///////////////////////////// SETTINGS MANAGEMENT //////////////////////////// 21 | 22 | #include "../include/user-settings.fxh" 23 | #include "../include/derived-settings-and-constants.fxh" 24 | #include "../include/bind-shader-params.fxh" 25 | 26 | ////////////////////////////////// INCLUDES ////////////////////////////////// 27 | 28 | #include "../include/gamma-management.fxh" 29 | #include "../include/bloom-functions.fxh" 30 | #include "../include/phosphor-mask-resizing.fxh" 31 | #include "../include/scanline-functions.fxh" 32 | 33 | ///////////////////////////////// STRUCTURES ///////////////////////////////// 34 | 35 | struct out_vertex_p10 36 | { 37 | float2 video_uv : TEXCOORD1; 38 | float2 bloom_dxdy : TEXCOORD2; 39 | float bloom_sigma_runtime : TEXCOORD3; 40 | float2 sinangle : TEXCOORD4; 41 | float2 cosangle : TEXCOORD5; 42 | float3 stretch : TEXCOORD6; 43 | }; 44 | 45 | 46 | //////////////////////////////// VERTEX SHADER /////////////////////////////// 47 | 48 | // Vertex shader generating a triangle covering the entire screen 49 | void VS_Bloom_Horizontal(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out out_vertex_p10 OUT) 50 | { 51 | texcoord.x = (id == 2) ? 2.0 : 0.0; 52 | texcoord.y = (id == 1) ? 2.0 : 0.0; 53 | position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 54 | 55 | float2 texture_size = BLOOM_HORIZONTAL_texture_size; 56 | float2 output_size = VIEWPORT_SIZE; 57 | 58 | // Screen centering 59 | texcoord = texcoord - float2(centerx,centery)/100.0; 60 | 61 | float2 tex_uv = texcoord; 62 | 63 | // Our various input textures use different coords: 64 | const float2 video_uv = tex_uv * texture_size/video_size; 65 | OUT.video_uv = video_uv; 66 | 67 | // We're horizontally blurring the bloom input (vertically blurred 68 | // brightpass). Get the uv distance between output pixels / input texels 69 | // in the horizontal direction (this pass must NOT resize): 70 | OUT.bloom_dxdy = float2(1.0/texture_size.x, 0.0); 71 | 72 | // Calculate a runtime bloom_sigma in case it's needed: 73 | const float mask_tile_size_x = get_resized_mask_tile_size( 74 | output_size, output_size * mask_resize_viewport_scale, false).x; 75 | OUT.bloom_sigma_runtime = get_min_sigma_to_blur_triad( 76 | mask_tile_size_x / mask_triads_per_tile, bloom_diff_thresh); 77 | 78 | // Precalculate a bunch of useful values we'll need in the fragment 79 | // shader. 80 | OUT.sinangle = sin(float2(geom_x_tilt, geom_y_tilt)); 81 | OUT.cosangle = cos(float2(geom_x_tilt, geom_y_tilt)); 82 | OUT.stretch = maxscale(OUT.sinangle, OUT.cosangle); 83 | } 84 | 85 | 86 | /////////////////////////////// FRAGMENT SHADER ////////////////////////////// 87 | 88 | float4 PS_Bloom_Horizontal(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in out_vertex_p10 VAR) : SV_Target 89 | { 90 | VAR.video_uv = (geom_curvature == true) ? transform(VAR.video_uv, VAR.sinangle, VAR.cosangle, VAR.stretch) : VAR.video_uv; 91 | 92 | float cval = corner((VAR.video_uv-0.5.xx) * BufferToViewportRatio + 0.5.xx); 93 | 94 | // Blur the vertically blurred brightpass horizontally by 9/17/25/43x: 95 | const float bloom_sigma = get_final_bloom_sigma(VAR.bloom_sigma_runtime); 96 | const float3 blurred_brightpass = tex2DblurNfast(BLOOM_VERTICAL, 97 | VAR.video_uv, VAR.bloom_dxdy, bloom_sigma); 98 | 99 | // Sample the masked scanlines. Alpha contains the auto-dim factor: 100 | const float3 intensity_dim = 101 | tex2D_linearize(MASKED_SCANLINES, VAR.video_uv).rgb; 102 | const float auto_dim_factor = levels_autodim_temp; 103 | const float undim_factor = 1.0/auto_dim_factor; 104 | 105 | // Calculate the mask dimpass, add it to the blurred brightpass, and 106 | // undim (from scanline auto-dim) and amplify (from mask dim) the result: 107 | const float mask_amplify = get_mask_amplify(); 108 | const float3 brightpass = tex2D_linearize(BRIGHTPASS, 109 | VAR.video_uv).rgb; 110 | const float3 dimpass = intensity_dim - brightpass; 111 | const float3 phosphor_bloom = (dimpass + blurred_brightpass) * 112 | mask_amplify * undim_factor * levels_contrast; 113 | 114 | // Sample the halation texture, and let some light bleed into refractive 115 | // diffusion. Conceptually this occurs before the phosphor bloom, but 116 | // adding it in earlier passes causes black crush in the diffusion colors. 117 | const float3 diffusion_color = levels_contrast * tex2D_linearize( 118 | HALATION_BLUR, VAR.video_uv).rgb; 119 | float3 final_bloom = lerp(phosphor_bloom, 120 | diffusion_color, diffusion_weight); 121 | 122 | final_bloom = (geom_curvature == true) ? final_bloom * cval.xxx : final_bloom; 123 | 124 | final_bloom = pow(final_bloom.rgb, 1.0/get_output_gamma()); 125 | 126 | // Encode and output the bloomed image: 127 | return encode_output(float4(final_bloom, 1.0)); 128 | } 129 | 130 | -------------------------------------------------------------------------------- /reshade/Shaders/crt-royale/shaders/blurring.fxh: -------------------------------------------------------------------------------- 1 | #ifndef _BLURRING_H 2 | #define _BLURRING_H 3 | 4 | ///////////////////////////// GPL LICENSE NOTICE ///////////////////////////// 5 | 6 | // crt-royale: A full-featured CRT shader, with cheese. 7 | // Copyright (C) 2014 TroggleMonkey 8 | // 9 | // crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade. 10 | // Copyright (C) 2020 Alex Gunter 11 | // 12 | // This program is free software; you can redistribute it and/or modify it 13 | // under the terms of the GNU General Public License as published by the Free 14 | // Software Foundation; either version 2 of the License, or any later version. 15 | // 16 | // This program is distributed in the hope that it will be useful, but WITHOUT 17 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 18 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 19 | // more details. 20 | // 21 | // You should have received a copy of the GNU General Public License along with 22 | // this program; if not, write to the Free Software Foundation, Inc., 59 Temple 23 | // Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | 26 | 27 | ///////////////////////////////// MIT LICENSE //////////////////////////////// 28 | 29 | // Copyright (C) 2014 TroggleMonkey 30 | // 31 | // Permission is hereby granted, free of charge, to any person obtaining a copy 32 | // of this software and associated documentation files (the "Software"), to 33 | // deal in the Software without restriction, including without limitation the 34 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 35 | // sell copies of the Software, and to permit persons to whom the Software is 36 | // furnished to do so, subject to the following conditions: 37 | // 38 | // The above copyright notice and this permission notice shall be included in 39 | // all copies or substantial portions of the Software. 40 | // 41 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 44 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 46 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 47 | // IN THE SOFTWARE. 48 | 49 | 50 | #include "../lib/gamma-management.fxh" 51 | #include "../lib/blur-functions.fxh" 52 | 53 | #include "shared-objects.fxh" 54 | 55 | 56 | void blurHorizontalVS( 57 | in uint id : SV_VertexID, 58 | 59 | out float4 position : SV_Position, 60 | out float2 texcoord : TEXCOORD0, 61 | out float2 blur_dxdy : TEXCOORD1 62 | ) { 63 | PostProcessVS(id, position, texcoord); 64 | 65 | // Get the uv sample distance between output pixels. Blurs are not generic 66 | // Gaussian resizers, and correct blurs require: 67 | // 1.) OutputSize == InputSize * 2^m, where m is an integer <= 0. 68 | // 2.) mipmap_inputN = "true" for this pass in the preset if m != 0 69 | // 3.) filter_linearN = "true" except for 1x scale nearest neighbor blurs 70 | // Gaussian resizers would upsize using the distance between input texels 71 | // (not output pixels), but we avoid this and consistently blur at the 72 | // destination size. Otherwise, combining statically calculated weights 73 | // with bilinear sample exploitation would result in terrible artifacts. 74 | static const float2 output_size = TEX_BLURHORIZONTAL_SIZE; 75 | static const float2 dxdy = 1.0 / output_size; 76 | // This blur is vertical-only, so zero out the horizontal offset: 77 | blur_dxdy = float2(dxdy.x, 0.0); 78 | } 79 | 80 | void blurHorizontalPS( 81 | in float4 pos : SV_Position, 82 | in float2 texcoord : TEXCOORD0, 83 | in float2 blur_dxdy : TEXCOORD1, 84 | 85 | out float4 color : SV_Target 86 | ) { 87 | static const float3 blur_color = tex2Dblur9fast(samplerBlurVertical, texcoord, blur_dxdy, get_intermediate_gamma()); 88 | // Encode and output the blurred image: 89 | // color = encode_output(float4(blur_color, 1.0), 1.0); 90 | color = encode_output(float4(blur_color, 1.0), get_intermediate_gamma()); 91 | } 92 | 93 | 94 | void blurVerticalVS( 95 | in uint id : SV_VertexID, 96 | 97 | out float4 position : SV_Position, 98 | out float2 texcoord : TEXCOORD0, 99 | out float2 blur_dxdy : TEXCOORD1 100 | ) { 101 | PostProcessVS(id, position, texcoord); 102 | 103 | // Get the uv sample distance between output pixels. Blurs are not generic 104 | // Gaussian resizers, and correct blurs require: 105 | // 1.) OutputSize == InputSize * 2^m, where m is an integer <= 0. 106 | // 2.) mipmap_inputN = "true" for this pass in the preset if m != 0 107 | // 3.) filter_linearN = "true" except for 1x scale nearest neighbor blurs 108 | // Gaussian resizers would upsize using the distance between input texels 109 | // (not output pixels), but we avoid this and consistently blur at the 110 | // destination size. Otherwise, combining statically calculated weights 111 | // with bilinear sample exploitation would result in terrible artifacts. 112 | static const float2 output_size = TEX_BLURVERTICAL_SIZE; 113 | static const float2 dxdy = 1.0 / output_size; 114 | // This blur is vertical-only, so zero out the horizontal offset: 115 | blur_dxdy = float2(0.0, dxdy.y); 116 | } 117 | 118 | void blurVerticalPS( 119 | in float4 pos : SV_Position, 120 | in float2 texcoord : TEXCOORD0, 121 | in float2 blur_dxdy : TEXCOORD1, 122 | 123 | out float4 color : SV_Target 124 | ) { 125 | static const float3 blur_color = tex2Dblur9fast(samplerBloomApproxHoriz, texcoord, blur_dxdy, get_intermediate_gamma()); 126 | // Encode and output the blurred image: 127 | // color = encode_output(float4(blur_color, 1.0), 1.0); 128 | color = encode_output(float4(blur_color, 1.0), get_intermediate_gamma()); 129 | } 130 | 131 | #endif // _BLURRING_H -------------------------------------------------------------------------------- /reshade/Shaders/crt-royale/shaders/bloom.fxh: -------------------------------------------------------------------------------- 1 | #ifndef _BLOOM_H 2 | #define _BLOOM_H 3 | 4 | ///////////////////////////// GPL LICENSE NOTICE ///////////////////////////// 5 | 6 | // crt-royale: A full-featured CRT shader, with cheese. 7 | // Copyright (C) 2014 TroggleMonkey 8 | // 9 | // crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade. 10 | // Copyright (C) 2020 Alex Gunter 11 | // 12 | // This program is free software; you can redistribute it and/or modify it 13 | // under the terms of the GNU General Public License as published by the Free 14 | // Software Foundation; either version 2 of the License, or any later version. 15 | // 16 | // This program is distributed in the hope that it will be useful, but WITHOUT 17 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 18 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 19 | // more details. 20 | // 21 | // You should have received a copy of the GNU General Public License along with 22 | // this program; if not, write to the Free Software Foundation, Inc., 59 Temple 23 | // Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | #include "../lib/user-settings.fxh" 26 | #include "../lib/derived-settings-and-constants.fxh" 27 | #include "../lib/bind-shader-params.fxh" 28 | #include "../lib/gamma-management.fxh" 29 | #include "../lib/downsampling-functions.fxh" 30 | #include "../lib/blur-functions.fxh" 31 | #include "../lib/bloom-functions.fxh" 32 | 33 | #include "shared-objects.fxh" 34 | 35 | 36 | void approximateBloomVertPS( 37 | in float4 pos : SV_Position, 38 | in float2 texcoord : TEXCOORD0, 39 | 40 | out float4 color : SV_Target 41 | ) { 42 | const float2 delta_uv = blur_radius * float2(0.0, rcp(TEX_BEAMCONVERGENCE_HEIGHT)); 43 | 44 | color = float4(opaque_linear_downsample( 45 | samplerBeamConvergence, texcoord, 46 | uint((bloomapprox_downsizing_factor - 1)/2), 47 | delta_uv 48 | ), 1); 49 | } 50 | 51 | void approximateBloomHorizPS( 52 | in float4 pos : SV_Position, 53 | in float2 texcoord : TEXCOORD0, 54 | 55 | out float4 color : SV_Target 56 | ) { 57 | const float2 delta_uv = blur_radius * float2(rcp(TEX_BEAMCONVERGENCE_WIDTH), 0.0); 58 | 59 | color = float4(opaque_linear_downsample( 60 | samplerBloomApproxVert, texcoord, 61 | uint((bloomapprox_downsizing_factor - 1)/2), 62 | delta_uv 63 | ), 1); 64 | } 65 | 66 | 67 | void bloomHorizontalVS( 68 | in uint id : SV_VertexID, 69 | 70 | out float4 position : SV_Position, 71 | out float2 texcoord : TEXCOORD0, 72 | out float bloom_sigma_runtime : TEXCOORD1 73 | ) { 74 | PostProcessVS(id, position, texcoord); 75 | 76 | bloom_sigma_runtime = get_min_sigma_to_blur_triad(calc_triad_size().x, bloom_diff_thresh_); 77 | } 78 | 79 | void bloomHorizontalPS( 80 | in float4 pos : SV_Position, 81 | in float2 texcoord : TEXCOORD0, 82 | in float bloom_sigma_runtime : TEXCOORD1, 83 | 84 | out float4 color : SV_Target 85 | ) { 86 | const float2 bloom_dxdy = float2(rcp(TEX_BLOOMVERTICAL_WIDTH), 0); 87 | 88 | // Blur the vertically blurred brightpass horizontally by 9/17/25/43x: 89 | const float bloom_sigma = get_final_bloom_sigma(bloom_sigma_runtime); 90 | const float3 blurred_brightpass = tex2DblurNfast(samplerBloomVertical, 91 | texcoord, bloom_dxdy, bloom_sigma, get_intermediate_gamma()); 92 | 93 | // Sample the masked scanlines. Alpha contains the auto-dim factor: 94 | const float3 intensity_dim = tex2D_linearize(samplerMaskedScanlines, texcoord, get_intermediate_gamma()).rgb; 95 | const float auto_dim_factor = levels_autodim_temp; 96 | const float undim_factor = 1.0/auto_dim_factor; 97 | 98 | // Calculate the mask dimpass, add it to the blurred brightpass, and 99 | // undim (from scanline auto-dim) and amplify (from mask dim) the result: 100 | const float mask_amplify = get_mask_amplify(); 101 | const float3 brightpass = tex2D_linearize(samplerBrightpass, texcoord, get_intermediate_gamma()).rgb; 102 | const float3 dimpass = intensity_dim - brightpass; 103 | const float3 phosphor_bloom = (dimpass + blurred_brightpass) * 104 | mask_amplify * undim_factor * levels_contrast; 105 | 106 | // Sample the halation texture, and let some light bleed into refractive 107 | // diffusion. Conceptually this occurs before the phosphor bloom, but 108 | // adding it in earlier passes causes black crush in the diffusion colors. 109 | const float3 raw_diffusion_color = tex2D_linearize(samplerBlurHorizontal, texcoord, get_intermediate_gamma()).rgb; 110 | const float3 raw_halation_color = dot(raw_diffusion_color, float3(1, 1, 1)) / 3.0; 111 | const float3 diffusion_color = levels_contrast * lerp(raw_diffusion_color, raw_halation_color, halation_weight); 112 | const float3 final_bloom = lerp(phosphor_bloom, diffusion_color, diffusion_weight); 113 | 114 | // Encode and output the bloomed image: 115 | color = encode_output(float4(final_bloom, 1.0), get_intermediate_gamma()); 116 | } 117 | 118 | 119 | void bloomVerticalVS( 120 | in uint id : SV_VertexID, 121 | 122 | out float4 position : SV_Position, 123 | out float2 texcoord : TEXCOORD0, 124 | out float bloom_sigma_runtime : TEXCOORD1 125 | ) { 126 | PostProcessVS(id, position, texcoord); 127 | 128 | bloom_sigma_runtime = get_min_sigma_to_blur_triad(calc_triad_size().x, bloom_diff_thresh_); 129 | } 130 | 131 | void bloomVerticalPS( 132 | in float4 pos : SV_Position, 133 | in float2 texcoord : TEXCOORD0, 134 | in float bloom_sigma_runtime : TEXCOORD1, 135 | 136 | out float4 color : SV_Target 137 | ) { 138 | const float2 bloom_dxdy = float2(0, rcp(TEX_BLOOMVERTICAL_HEIGHT)); 139 | 140 | // Blur the brightpass horizontally with a 9/17/25/43x blur: 141 | const float bloom_sigma = get_final_bloom_sigma(bloom_sigma_runtime); 142 | const float3 color3 = tex2DblurNfast(samplerBrightpass, texcoord, 143 | bloom_dxdy, bloom_sigma, get_intermediate_gamma()); 144 | 145 | // Encode and output the blurred image: 146 | color = encode_output(float4(color3, 1.0), get_intermediate_gamma()); 147 | } 148 | 149 | #endif // _BLOOM_H -------------------------------------------------------------------------------- /reshade/Shaders/crt/crt-royale/src/crt-royale-mask-resize-horizontal.fxh: -------------------------------------------------------------------------------- 1 | ///////////////////////////// GPL LICENSE NOTICE ///////////////////////////// 2 | 3 | // crt-royale: A full-featured CRT shader, with cheese. 4 | // Copyright (C) 2014 TroggleMonkey 5 | // 6 | // This program is free software; you can redistribute it and/or modify it 7 | // under the terms of the GNU General Public License as published by the Free 8 | // Software Foundation; either version 2 of the License, or any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, but WITHOUT 11 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 | // more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along with 16 | // this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | // Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | 20 | ///////////////////////////// SETTINGS MANAGEMENT //////////////////////////// 21 | 22 | #include "../include/user-settings.fxh" 23 | #include "../include/derived-settings-and-constants.fxh" 24 | #include "../include/bind-shader-params.fxh" 25 | 26 | 27 | ////////////////////////////////// INCLUDES ////////////////////////////////// 28 | 29 | #include "../include/phosphor-mask-resizing.fxh" 30 | 31 | 32 | ///////////////////////////////// STRUCTURES ///////////////////////////////// 33 | 34 | struct out_vertex_p6 35 | { 36 | float2 src_tex_uv_wrap : TEXCOORD1; 37 | float2 tile_uv_wrap : TEXCOORD2; 38 | float2 resize_magnification_scale : TEXCOORD3; 39 | float2 src_dxdy : TEXCOORD4; 40 | float2 tile_size_uv : TEXCOORD5; 41 | float2 input_tiles_per_texture : TEXCOORD6; 42 | }; 43 | 44 | 45 | //////////////////////////////// VERTEX SHADER /////////////////////////////// 46 | 47 | // Vertex shader generating a triangle covering the entire screen 48 | void VS_Mask_Resize_Horizontal(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out out_vertex_p6 OUT) 49 | { 50 | texcoord.x = (id == 2) ? 2.0 : 0.0; 51 | texcoord.y = (id == 1) ? 2.0 : 0.0; 52 | position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 53 | 54 | float2 tex_uv = texcoord; 55 | 56 | float2 texture_size = MASK_RESIZE_texture_size; 57 | float2 output_size = 0.0625*(VIEWPORT_SIZE); 58 | 59 | // First estimate the viewport size (the user will get the wrong number of 60 | // triads if it's wrong and mask_specify_num_triads is 1.0/true). 61 | const float2 estimated_viewport_size = 62 | output_size / mask_resize_viewport_scale; 63 | // Find the final size of our resized phosphor mask tiles. We probably 64 | // estimated the viewport size and MASK_RESIZE output size differently last 65 | // pass, so do not swear they were the same. ;) 66 | const float2 mask_resize_tile_size = get_resized_mask_tile_size( 67 | estimated_viewport_size, output_size, false); 68 | 69 | // We'll render resized tiles until filling the output FBO or meeting a 70 | // limit, so compute [wrapped] tile uv coords based on the output uv coords 71 | // and the number of tiles that will fit in the FBO. 72 | const float2 output_tiles_this_pass = output_size / mask_resize_tile_size; 73 | const float2 output_video_uv = tex_uv * texture_size / video_size; 74 | const float2 tile_uv_wrap = output_video_uv * output_tiles_this_pass; 75 | 76 | // Get the texel size of an input tile and related values: 77 | const float2 input_tile_size = float2(min( 78 | mask_resize_src_lut_size.x, video_size.x), mask_resize_tile_size.y); 79 | const float2 tile_size_uv = input_tile_size / texture_size; 80 | const float2 input_tiles_per_texture = texture_size / input_tile_size; 81 | 82 | // Derive [wrapped] texture uv coords from [wrapped] tile uv coords and 83 | // the tile size in uv coords, and save frac() for the fragment shader. 84 | const float2 src_tex_uv_wrap = tile_uv_wrap * tile_size_uv; 85 | 86 | // Output the values we need, including the magnification scale and step: 87 | OUT.tile_uv_wrap = tile_uv_wrap; 88 | OUT.src_tex_uv_wrap = src_tex_uv_wrap; 89 | OUT.resize_magnification_scale = mask_resize_tile_size / input_tile_size; 90 | OUT.src_dxdy = float2(1.0/texture_size.x, 0.0); 91 | OUT.tile_size_uv = tile_size_uv; 92 | OUT.input_tiles_per_texture = input_tiles_per_texture; 93 | } 94 | 95 | 96 | /////////////////////////////// FRAGMENT SHADER ////////////////////////////// 97 | 98 | float4 PS_Mask_Resize_Horizontal(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in out_vertex_p6 VAR) : SV_Target 99 | { 100 | // The input contains one mask tile horizontally and a number vertically. 101 | // Resize the tile horizontally to its final screen size and repeat it 102 | // until drawing at least mask_resize_num_tiles, leaving it unchanged 103 | // vertically. Lanczos-resizing the phosphor mask achieves much sharper 104 | // results than mipmapping, outputting >= mask_resize_num_tiles makes for 105 | // easier tiled sampling later. 106 | #ifdef PHOSPHOR_MASK_MANUALLY_RESIZE 107 | // Discard unneeded fragments in case our profile allows real branches. 108 | float2 texture_size = MASK_RESIZE_texture_size; 109 | const float2 tile_uv_wrap = VAR.tile_uv_wrap; 110 | if(get_mask_sample_mode() < 0.5 && 111 | max(tile_uv_wrap.x, tile_uv_wrap.y) <= mask_resize_num_tiles) 112 | { 113 | const float src_dx = VAR.src_dxdy.x; 114 | const float2 src_tex_uv = frac(VAR.src_tex_uv_wrap); 115 | const float3 pixel_color = downsample_horizontal_sinc_tiled(MASK_RESIZE_VERTICAL, 116 | src_tex_uv, texture_size, VAR.src_dxdy.x, 117 | VAR.resize_magnification_scale.x, VAR.tile_size_uv.x); 118 | // The input LUT was linear RGB, and so is our output: 119 | return float4(pixel_color, 1.0); 120 | } 121 | else 122 | { 123 | discard; 124 | } 125 | #else 126 | discard; 127 | return 1.0.xxxx; 128 | #endif 129 | } 130 | 131 | -------------------------------------------------------------------------------- /dolphinfx/celshading.glsl: -------------------------------------------------------------------------------- 1 | /*===============================================================================*\ 2 | |######################## [Dolphin FX Suite 2.20] #######################| 3 | |########################## By Asmodean ##########################| 4 | || || 5 | || This program is free software; you can redistribute it and/or || 6 | || modify it under the terms of the GNU General Public License || 7 | || as published by the Free Software Foundation; either version 2 || 8 | || of the License, or (at your option) any later version. || 9 | || || 10 | || This program is distributed in the hope that it will be useful, || 11 | || but WITHOUT ANY WARRANTY; without even the implied warranty of || 12 | || MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the || 13 | || GNU General Public License for more details. (C)2015 || 14 | || || 15 | |#################################################################################| 16 | \*===============================================================================*/ 17 | 18 | // Sourced from https://raw.githubusercontent.com/Asmodean-/dolphin/89d640cd557189bb5f921fc219150c74c39bdc55/Data/Sys/Shaders/DolphinFX.glsl with modifications. 19 | 20 | /* 21 | [configuration] 22 | 23 | [OptionRangeFloat] 24 | GUIName = EdgeStrength 25 | OptionName = A_EDGE_STRENGTH 26 | MinValue = 0.00 27 | MaxValue = 4.00 28 | StepAmount = 0.01 29 | DefaultValue = 1.00 30 | 31 | [OptionRangeFloat] 32 | GUIName = EdgeFilter 33 | OptionName = B_EDGE_FILTER 34 | MinValue = 0.25 35 | MaxValue = 1.00 36 | StepAmount = 0.01 37 | DefaultValue = 0.60 38 | 39 | [OptionRangeFloat] 40 | GUIName = EdgeThickness 41 | OptionName = C_EDGE_THICKNESS 42 | MinValue = 0.25 43 | MaxValue = 2.00 44 | StepAmount = 0.01 45 | DefaultValue = 1.00 46 | 47 | [OptionRangeInteger] 48 | GUIName = PaletteType 49 | OptionName = D_PALETTE_TYPE 50 | MinValue = 0 51 | MaxValue = 2 52 | StepAmount = 1 53 | DefaultValue = 1 54 | 55 | [OptionRangeInteger] 56 | GUIName = UseYuvLuma 57 | OptionName = E_YUV_LUMA 58 | MinValue = 0 59 | MaxValue = 1 60 | StepAmount = 1 61 | DefaultValue = 0 62 | 63 | [OptionRangeInteger] 64 | GUIName = ColourRounding 65 | OptionName = G_COLOR_ROUNDING 66 | MinValue = 0 67 | MaxValue = 1 68 | StepAmount = 1 69 | DefaultValue = 1 70 | 71 | [/configuration] 72 | */ 73 | 74 | //Average relative luminance 75 | CONSTANT float3 lumCoeff = float3(0.2126729, 0.7151522, 0.0721750); 76 | float AvgLuminance(float3 color) 77 | { 78 | return sqrt( 79 | (color.x * color.x * lumCoeff.x) + 80 | (color.y * color.y * lumCoeff.y) + 81 | (color.z * color.z * lumCoeff.z)); 82 | } 83 | 84 | float3 YUVtoRGB(float3 YUV) 85 | { 86 | const float3x3 m = float3x3( 87 | 1.000, 0.000, 1.28033, 88 | 1.000,-0.21482,-0.38059, 89 | 1.000, 2.12798, 0.000 ); 90 | 91 | return mul(m, YUV); 92 | } 93 | 94 | float3 RGBtoYUV(float3 RGB) 95 | { 96 | const float3x3 m = float3x3( 97 | 0.2126, 0.7152, 0.0722, 98 | -0.09991,-0.33609, 0.436, 99 | 0.615, -0.55861, -0.05639 ); 100 | 101 | return mul(m, RGB); 102 | } 103 | 104 | void main() 105 | { 106 | float4 color = Sample(); 107 | float2 texcoord = GetCoordinates(); 108 | float2 pixelSize = GetInvResolution(); 109 | float2 texSize = GetResolution(); 110 | 111 | float3 yuv; 112 | float3 sum = color.rgb; 113 | 114 | const int NUM = 9; 115 | const float2 RoundingOffset = float2(0.25, 0.25); 116 | const float3 thresholds = float3(9.0, 8.0, 6.0); 117 | 118 | float lum[NUM]; 119 | float3 col[NUM]; 120 | float2 set[NUM] = BEGIN_ARRAY(float2, NUM) 121 | float2(-0.0078125, -0.0078125), 122 | float2(0.00, -0.0078125), 123 | float2(0.0078125, -0.0078125), 124 | float2(-0.0078125, 0.00), 125 | float2(0.00, 0.00), 126 | float2(0.0078125, 0.00), 127 | float2(-0.0078125, 0.0078125), 128 | float2(0.00, 0.0078125), 129 | float2(0.0078125, 0.0078125) END_ARRAY; 130 | 131 | for (int i = 0; i < NUM; i++) 132 | { 133 | col[i] = SampleLocation(texcoord + set[i] * RoundingOffset).rgb; 134 | 135 | if (GetOption(G_COLOR_ROUNDING) == 1) { 136 | col[i].r = round(col[i].r * thresholds.r) / thresholds.r; 137 | col[i].g = round(col[i].g * thresholds.g) / thresholds.g; 138 | col[i].b = round(col[i].b * thresholds.b) / thresholds.b; } 139 | 140 | lum[i] = AvgLuminance(col[i].xyz); 141 | yuv = RGBtoYUV(col[i]); 142 | 143 | if (GetOption(E_YUV_LUMA) == 0) 144 | { yuv.r = round(yuv.r * thresholds.r) / thresholds.r; } 145 | else 146 | { yuv.r = saturate(round(yuv.r * lum[i]) / thresholds.r + lum[i]); } 147 | 148 | yuv = YUVtoRGB(yuv); 149 | sum += yuv; 150 | } 151 | 152 | float3 shadedColor = (sum / NUM); 153 | float2 pixel = float2((1.0/texSize.x) * GetOption(C_EDGE_THICKNESS), 154 | (1.0/texSize.y) * GetOption(C_EDGE_THICKNESS)); 155 | 156 | float edgeX = dot(SampleLocation(texcoord + pixel).rgb, lumCoeff); 157 | edgeX = dot(float4(SampleLocation(texcoord - pixel).rgb, edgeX), float4(lumCoeff, -1.0)); 158 | 159 | float edgeY = dot(SampleLocation(texcoord + float2(pixel.x, -pixel.y)).rgb, lumCoeff); 160 | edgeY = dot(float4(SampleLocation(texcoord + float2(-pixel.x, pixel.y)).rgb, edgeY), float4(lumCoeff, -1.0)); 161 | 162 | float edge = dot(float2(edgeX, edgeY), float2(edgeX, edgeY)); 163 | 164 | if (GetOption(D_PALETTE_TYPE) == 0) 165 | { color.rgb = lerp(color.rgb, color.rgb + pow(edge, GetOption(B_EDGE_FILTER)) * -GetOption(A_EDGE_STRENGTH), GetOption(A_EDGE_STRENGTH)); } 166 | else if (GetOption(D_PALETTE_TYPE) == 1) 167 | { color.rgb = lerp(color.rgb + pow(edge, GetOption(B_EDGE_FILTER)) * -GetOption(A_EDGE_STRENGTH), shadedColor, 0.25); } 168 | else if (GetOption(D_PALETTE_TYPE) == 2) 169 | { color.rgb = lerp(shadedColor + edge * -GetOption(A_EDGE_STRENGTH), pow(edge, GetOption(B_EDGE_FILTER)) * -GetOption(A_EDGE_STRENGTH) + color.rgb, 0.50); } 170 | 171 | color.a = AvgLuminance(color.rgb); 172 | 173 | SetOutput(saturate(color)); 174 | } 175 | -------------------------------------------------------------------------------- /reshade/Shaders/crt/crt-royale/src/crt-royale-brightpass.fxh: -------------------------------------------------------------------------------- 1 | ///////////////////////////// GPL LICENSE NOTICE ///////////////////////////// 2 | 3 | // crt-royale: A full-featured CRT shader, with cheese. 4 | // Copyright (C) 2014 TroggleMonkey 5 | // 6 | // This program is free software; you can redistribute it and/or modify it 7 | // under the terms of the GNU General Public License as published by the Free 8 | // Software Foundation; either version 2 of the License, or any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, but WITHOUT 11 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 | // more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along with 16 | // this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | // Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | 20 | ///////////////////////////// SETTINGS MANAGEMENT //////////////////////////// 21 | 22 | #include "../include/user-settings.fxh" 23 | #include "../include/derived-settings-and-constants.fxh" 24 | #include "../include/bind-shader-params.fxh" 25 | 26 | ////////////////////////////////// INCLUDES ////////////////////////////////// 27 | 28 | #include "../include/gamma-management.fxh" 29 | #include "../include/blur-functions.fxh" 30 | #include "../include/phosphor-mask-resizing.fxh" 31 | #include "../include/scanline-functions.fxh" 32 | #include "../include/bloom-functions.fxh" 33 | 34 | ///////////////////////////////// STRUCTURES ///////////////////////////////// 35 | 36 | struct out_vertex_p8 37 | { 38 | float2 video_uv : TEXCOORD1; 39 | float2 scanline_tex_uv : TEXCOORD2; 40 | float2 blur3x3_tex_uv : TEXCOORD3; 41 | float bloom_sigma_runtime : TEXCOORD4; 42 | }; 43 | 44 | 45 | //////////////////////////////// VERTEX SHADER /////////////////////////////// 46 | 47 | // Vertex shader generating a triangle covering the entire screen 48 | void VS_Brightpass(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out out_vertex_p8 OUT) 49 | { 50 | texcoord.x = (id == 2) ? 2.0 : 0.0; 51 | texcoord.y = (id == 1) ? 2.0 : 0.0; 52 | position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 53 | 54 | float2 tex_uv = texcoord; 55 | 56 | float2 texture_size = BRIGHTPASS_texture_size; 57 | float2 output_size = VIEWPORT_SIZE; 58 | 59 | // Our various input textures use different coords: 60 | const float2 video_uv = tex_uv * texture_size/video_size; 61 | OUT.video_uv = video_uv; 62 | OUT.scanline_tex_uv = video_uv * MASKED_SCANLINES_video_size / 63 | MASKED_SCANLINES_texture_size; 64 | OUT.blur3x3_tex_uv = video_uv * BLOOM_APPROX_video_size / BLOOM_APPROX_texture_size; 65 | 66 | // Calculate a runtime bloom_sigma in case it's needed: 67 | const float mask_tile_size_x = get_resized_mask_tile_size( 68 | output_size, output_size * mask_resize_viewport_scale, false).x; 69 | OUT.bloom_sigma_runtime = get_min_sigma_to_blur_triad( 70 | mask_tile_size_x / mask_triads_per_tile, bloom_diff_thresh); 71 | } 72 | 73 | 74 | /////////////////////////////// FRAGMENT SHADER ////////////////////////////// 75 | 76 | float4 PS_Brightpass(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in out_vertex_p8 VAR) : SV_Target 77 | { 78 | // Sample the masked scanlines: 79 | const float3 intensity_dim = 80 | tex2D_linearize(MASKED_SCANLINES, VAR.scanline_tex_uv).rgb; 81 | // Get the full intensity, including auto-undimming, and mask compensation: 82 | const float auto_dim_factor = levels_autodim_temp; 83 | const float undim_factor = 1.0/auto_dim_factor; 84 | const float mask_amplify = get_mask_amplify(); 85 | const float3 intensity = intensity_dim * undim_factor * mask_amplify * 86 | levels_contrast; 87 | 88 | // Sample BLOOM_APPROX to estimate what a straight blur of masked scanlines 89 | // would look like, so we can estimate how much energy we'll receive from 90 | // blooming neighbors: 91 | const float3 phosphor_blur_approx = levels_contrast * tex2D_linearize( 92 | BLOOM_APPROX, VAR.blur3x3_tex_uv).rgb; 93 | 94 | // Compute the blur weight for the center texel and the maximum energy we 95 | // expect to receive from neighbors: 96 | const float bloom_sigma = get_final_bloom_sigma(VAR.bloom_sigma_runtime); 97 | const float center_weight = get_center_weight(bloom_sigma); 98 | const float3 max_area_contribution_approx = 99 | max(0.0.xxx, phosphor_blur_approx - center_weight * intensity); 100 | // Assume neighbors will blur 100% of their intensity (blur_ratio = 1.0), 101 | // because it actually gets better results (on top of being very simple), 102 | // but adjust all intensities for the user's desired underestimate factor: 103 | const float3 area_contrib_underestimate = 104 | bloom_underestimate_levels * max_area_contribution_approx; 105 | const float3 intensity_underestimate = 106 | bloom_underestimate_levels * intensity; 107 | // Calculate the blur_ratio, the ratio of intensity we want to blur: 108 | #ifdef BRIGHTPASS_AREA_BASED 109 | // This area-based version changes blur_ratio more smoothly and blurs 110 | // more, clipping less but offering less phosphor differentiation: 111 | const float3 phosphor_blur_underestimate = bloom_underestimate_levels * 112 | phosphor_blur_approx; 113 | const float3 soft_intensity = max(intensity_underestimate, 114 | phosphor_blur_underestimate * mask_amplify); 115 | const float3 blur_ratio_temp = 116 | ((1.0.xxx - area_contrib_underestimate) / 117 | soft_intensity - 1.0.xxx) / (center_weight - 1.0); 118 | #else 119 | const float3 blur_ratio_temp = 120 | ((1.0.xxx - area_contrib_underestimate) / 121 | intensity_underestimate - 1.0.xxx) / (center_weight - 1.0); 122 | #endif 123 | const float3 blur_ratio = clamp(blur_ratio_temp, 0.0, 1.0); 124 | // Calculate the brightpass based on the auto-dimmed, unamplified, masked 125 | // scanlines, encode if necessary, and return! 126 | const float3 brightpass = intensity_dim * 127 | lerp(blur_ratio, 1.0.xxx, bloom_excess); 128 | return encode_output(float4(brightpass, 1.0)); 129 | } 130 | 131 | -------------------------------------------------------------------------------- /reshade/Shaders/misc/include/geom.fxh: -------------------------------------------------------------------------------- 1 | #ifndef GEOM_PARAMS_H 2 | #define GEOM_PARAMS_H 3 | 4 | /* 5 | Geom Shader - a modified CRT-Geom without CRT features made to be appended/integrated 6 | into any other shaders and provide curvature/warping/oversampling features. 7 | 8 | Adapted by Hyllian (2024). 9 | */ 10 | 11 | 12 | /* 13 | CRT-interlaced 14 | 15 | Copyright (C) 2010-2012 cgwg, Themaister and DOLLS 16 | 17 | This program is free software; you can redistribute it and/or modify it 18 | under the terms of the GNU General Public License as published by the Free 19 | Software Foundation; either version 2 of the License, or (at your option) 20 | any later version. 21 | 22 | (cgwg gave their consent to have the original version of this shader 23 | distributed under the GPL in this message: 24 | 25 | http://board.byuu.org/viewtopic.php?p=26075#p26075 26 | 27 | "Feel free to distribute my shaders under the GPL. After all, the 28 | barrel distortion code was taken from the Curvature shader, which is 29 | under the GPL." 30 | ) 31 | This shader variant is pre-configured with screen curvature 32 | */ 33 | 34 | 35 | uniform bool geom_curvature < 36 | ui_type = "radio"; 37 | ui_category = "Geom Curvature"; 38 | ui_label = "Geom Curvature Toggle"; 39 | > = 0.0; 40 | 41 | uniform float geom_R < 42 | ui_type = "drag"; 43 | ui_min = 0.1; 44 | ui_max = 10.0; 45 | ui_step = 0.1; 46 | ui_category = "Geom Curvature"; 47 | ui_label = "Geom Curvature Radius"; 48 | > = 2.0; 49 | 50 | uniform float geom_d < 51 | ui_type = "drag"; 52 | ui_min = 0.1; 53 | ui_max = 3.0; 54 | ui_step = 0.1; 55 | ui_category = "Geom Curvature"; 56 | ui_label = "Geom Distance"; 57 | > = 1.5; 58 | 59 | uniform bool geom_invert_aspect < 60 | ui_type = "radio"; 61 | ui_category = "Geom Curvature"; 62 | ui_label = "Geom Curvature Aspect Inversion"; 63 | > = 0.0; 64 | 65 | uniform float geom_cornersize < 66 | ui_type = "drag"; 67 | ui_min = 0.001; 68 | ui_max = 1.0; 69 | ui_step = 0.005; 70 | ui_category = "Geom Curvature"; 71 | ui_label = "Geom Corner Size"; 72 | > = 0.03; 73 | 74 | uniform float geom_cornersmooth < 75 | ui_type = "drag"; 76 | ui_min = 80.0; 77 | ui_max = 2000.0; 78 | ui_step = 100.0; 79 | ui_category = "Geom Curvature"; 80 | ui_label = "Geom Corner Smoothness"; 81 | > = 1000.0; 82 | 83 | uniform float geom_x_tilt < 84 | ui_type = "drag"; 85 | ui_min = -1.0; 86 | ui_max = 1.0; 87 | ui_step = 0.05; 88 | ui_category = "Geom Curvature"; 89 | ui_label = "Geom Horizontal Tilt"; 90 | > = 0.0; 91 | 92 | uniform float geom_y_tilt < 93 | ui_type = "drag"; 94 | ui_min = -1.0; 95 | ui_max = 1.0; 96 | ui_step = 0.05; 97 | ui_category = "Geom Curvature"; 98 | ui_label = "Geom Vertical Tilt"; 99 | > = 0.0; 100 | 101 | uniform float geom_overscan_x < 102 | ui_type = "drag"; 103 | ui_min = -125.0; 104 | ui_max = 125.0; 105 | ui_step = 0.5; 106 | ui_category = "Geom Curvature"; 107 | ui_label = "Geom Horiz. Overscan %"; 108 | > = 100.0; 109 | 110 | uniform float geom_overscan_y < 111 | ui_type = "drag"; 112 | ui_min = -125.0; 113 | ui_max = 125.0; 114 | ui_step = 0.5; 115 | ui_category = "Geom Curvature"; 116 | ui_label = "Geom Vert. Overscan %"; 117 | > = 100.0; 118 | 119 | uniform float centerx < 120 | ui_type = "drag"; 121 | ui_min = -100.0; 122 | ui_max = 100.0; 123 | ui_step = 0.1; 124 | ui_category = "Geom Curvature"; 125 | ui_label = "Image Center X"; 126 | > = 0.00; 127 | 128 | uniform float centery < 129 | ui_type = "drag"; 130 | ui_min = -100.0; 131 | ui_max = 100.0; 132 | ui_step = 0.1; 133 | ui_category = "Geom Curvature"; 134 | ui_label = "Image Center Y"; 135 | > = 0.00; 136 | 137 | 138 | 139 | // Macros. 140 | #define FIX(c) max(abs(c), 1e-5); 141 | 142 | // aspect ratio 143 | #define aspect (geom_invert_aspect==true?float2(ViewportHeight/ViewportWidth,1.0):float2(1.0,ViewportHeight/ViewportWidth)) 144 | 145 | 146 | float intersect(float2 xy, float2 sinangle, float2 cosangle) 147 | { 148 | float A = dot(xy,xy) + geom_d*geom_d; 149 | float B, C; 150 | 151 | B = 2.0*(geom_R*(dot(xy,sinangle) - geom_d*cosangle.x*cosangle.y) - geom_d*geom_d); 152 | C = geom_d*geom_d + 2.0*geom_R*geom_d*cosangle.x*cosangle.y; 153 | 154 | return (-B-sqrt(B*B - 4.0*A*C))/(2.0*A); 155 | } 156 | 157 | float2 bkwtrans(float2 xy, float2 sinangle, float2 cosangle) 158 | { 159 | float c = intersect(xy, sinangle, cosangle); 160 | float2 point = (c.xx*xy + geom_R.xx*sinangle) / geom_R.xx; 161 | float2 poc = point/cosangle; 162 | float2 tang = sinangle/cosangle; 163 | 164 | float A = dot(tang, tang) + 1.0; 165 | float B = -2.0*dot(poc, tang); 166 | float C = dot(poc, poc) - 1.0; 167 | 168 | float a = (-B + sqrt(B*B - 4.0*A*C)) / (2.0*A); 169 | float2 uv = (point - a*sinangle) / cosangle; 170 | float r = FIX(geom_R*acos(a)); 171 | 172 | return uv*r/sin(r/geom_R); 173 | } 174 | 175 | float2 fwtrans(float2 uv, float2 sinangle, float2 cosangle) 176 | { 177 | float r = FIX(sqrt(dot(uv, uv))); 178 | uv *= sin(r/geom_R)/r; 179 | float x = 1.0 - cos(r/geom_R); 180 | float D; 181 | 182 | D = geom_d/geom_R + x*cosangle.x*cosangle.y + dot(uv,sinangle); 183 | 184 | return geom_d*(uv*cosangle - x*sinangle)/D; 185 | } 186 | 187 | float3 maxscale(float2 sinangle, float2 cosangle) 188 | { 189 | float2 c = bkwtrans(-geom_R * sinangle / (1.0 + geom_R/geom_d*cosangle.x*cosangle.y), sinangle, cosangle); 190 | float2 a = 0.5.xx*aspect; 191 | 192 | float2 lo = float2(fwtrans(float2(-a.x, c.y), sinangle, cosangle).x, 193 | fwtrans(float2( c.x, -a.y), sinangle, cosangle).y)/aspect; 194 | float2 hi = float2(fwtrans(float2(+a.x, c.y), sinangle, cosangle).x, 195 | fwtrans(float2( c.x, +a.y), sinangle, cosangle).y)/aspect; 196 | 197 | return float3((hi+lo)*aspect*0.5,max(hi.x-lo.x, hi.y-lo.y)); 198 | } 199 | 200 | float2 transform(float2 coord, float2 sinangle, float2 cosangle, float3 stretch) 201 | { 202 | coord = (coord - 0.5.xx)*aspect*stretch.z + stretch.xy; 203 | 204 | return (bkwtrans(coord, sinangle, cosangle) / 205 | float2(geom_overscan_x / 100.0, geom_overscan_y / 100.0)/aspect + 0.5.xx); 206 | } 207 | 208 | 209 | float corner(float2 coord) 210 | { 211 | coord = min(coord, 1.0.xx - coord) * aspect; 212 | float2 cdist = geom_cornersize.xx; 213 | coord = (cdist - min(coord, cdist)); 214 | float dist = sqrt(dot(coord, coord)); 215 | 216 | return clamp((cdist.x - dist)*geom_cornersmooth, 0.0, 1.0); 217 | } 218 | 219 | float fwidth(float value) 220 | { 221 | return abs(ddx(value)) + abs(ddy(value)); 222 | } 223 | 224 | #endif // GEOM_PARAMS_H 225 | -------------------------------------------------------------------------------- /reshade/Shaders/crt-royale.fx: -------------------------------------------------------------------------------- 1 | #include "ReShade.fxh" 2 | 3 | ///////////////////////////// GPL LICENSE NOTICE ///////////////////////////// 4 | 5 | // crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade. 6 | // Copyright (C) 2020 Alex Gunter 7 | // 8 | // This program is free software; you can redistribute it and/or modify it 9 | // under the terms of the GNU General Public License as published by the Free 10 | // Software Foundation; either version 2 of the License, or any later version. 11 | // 12 | // This program is distributed in the hope that it will be useful, but WITHOUT 13 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 | // more details. 16 | // 17 | // You should have received a copy of the GNU General Public License along with 18 | // this program; if not, write to the Free Software Foundation, Inc., 59 Temple 19 | // Place, Suite 330, Boston, MA 02111-1307 USA 20 | 21 | // Enable or disable the shader 22 | #ifndef CONTENT_BOX_VISIBLE 23 | #define CONTENT_BOX_VISIBLE 0 24 | #endif 25 | 26 | #include "crt-royale/shaders/content-box.fxh" 27 | 28 | #if !CONTENT_BOX_VISIBLE 29 | #include "crt-royale/shaders/input-blurring.fxh" 30 | #include "crt-royale/shaders/electron-beams.fxh" 31 | #include "crt-royale/shaders/blurring.fxh" 32 | #include "crt-royale/shaders/deinterlace.fxh" 33 | #include "crt-royale/shaders/phosphor-mask.fxh" 34 | #include "crt-royale/shaders/brightpass.fxh" 35 | #include "crt-royale/shaders/bloom.fxh" 36 | #include "crt-royale/shaders/geometry-aa-last-pass.fxh" 37 | #endif 38 | 39 | 40 | technique CRT_Royale 41 | { 42 | // Toggle the content box to help users configure it 43 | #if CONTENT_BOX_VISIBLE 44 | pass contentBoxPass 45 | { 46 | // content-box.fxh 47 | // Draw a box that displays the crop we'll perform. 48 | VertexShader = PostProcessVS; 49 | PixelShader = contentBoxPixelShader; 50 | } 51 | #else 52 | #if ENABLE_PREBLUR 53 | pass PreblurVert 54 | { 55 | // input-blurring.fxh 56 | // Optionally blur the input buffer a little 57 | VertexShader = contentCropVS; 58 | PixelShader = preblurVertPS; 59 | 60 | RenderTarget = texPreblurVert; 61 | 62 | PrimitiveTopology = TRIANGLESTRIP; 63 | VertexCount = 4; 64 | } 65 | pass PreblurHoriz 66 | { 67 | // input-blurring.fxh 68 | VertexShader = PostProcessVS; 69 | PixelShader = preblurHorizPS; 70 | 71 | RenderTarget = texPreblurHoriz; 72 | } 73 | #endif 74 | pass beamDistPass 75 | { 76 | // electron-beams.fxh 77 | // Simulate emission of the interlaced video as electron beams. 78 | VertexShader = calculateBeamDistsVS; 79 | PixelShader = calculateBeamDistsPS; 80 | 81 | RenderTarget = texBeamDist; 82 | 83 | // This lets us improve performance by only computing the mask every k frames 84 | ClearRenderTargets = false; 85 | } 86 | pass electronBeamPass 87 | { 88 | // electron-beams.fxh 89 | // Simulate emission of the interlaced video as electron beams. 90 | VertexShader = simulateEletronBeamsVS; 91 | PixelShader = simulateEletronBeamsPS; 92 | 93 | RenderTarget = texElectronBeams; 94 | 95 | // If the preblur passes are disabled, we have to crop in this pass 96 | #if !ENABLE_PREBLUR 97 | PrimitiveTopology = TRIANGLESTRIP; 98 | VertexCount = 4; 99 | #endif 100 | } 101 | pass beamConvergencePass 102 | { 103 | // electron-beams.fxh 104 | // Simulate beam convergence miscalibration 105 | // Not to be confused with beam purity 106 | VertexShader = beamConvergenceVS; 107 | PixelShader = beamConvergencePS; 108 | 109 | RenderTarget = texBeamConvergence; 110 | } 111 | pass bloomApproxPassVert 112 | { 113 | // bloom.fxh 114 | VertexShader = PostProcessVS; 115 | PixelShader = approximateBloomVertPS; 116 | 117 | RenderTarget = texBloomApproxVert; 118 | } 119 | pass bloomApproxPassHoriz 120 | { 121 | // bloom.fxh 122 | VertexShader = PostProcessVS; 123 | PixelShader = approximateBloomHorizPS; 124 | 125 | RenderTarget = texBloomApproxHoriz; 126 | } 127 | pass blurVerticalPass 128 | { 129 | // blurring.fxh 130 | // Vertically blur the approx bloom 131 | VertexShader = blurVerticalVS; 132 | PixelShader = blurVerticalPS; 133 | 134 | RenderTarget = texBlurVertical; 135 | } 136 | pass blurHorizontalPass 137 | { 138 | // blurring.fxh 139 | // Horizontally blur the approx bloom 140 | VertexShader = blurHorizontalVS; 141 | PixelShader = blurHorizontalPS; 142 | 143 | RenderTarget = texBlurHorizontal; 144 | } 145 | pass deinterlacePass 146 | { 147 | // deinterlace.fxh 148 | // Optionally deinterlace the video if interlacing is enabled. 149 | // Can help approximate the original crt-royale's appearance 150 | // without some issues like image retention. 151 | VertexShader = deinterlaceVS; 152 | PixelShader = deinterlacePS; 153 | 154 | RenderTarget = texDeinterlace; 155 | } 156 | pass freezeFramePass 157 | { 158 | // deinterlace.fxh 159 | // Capture the current frame, so we can use it in the next 160 | // frame's deinterlacing pass. 161 | VertexShader = freezeFrameVS; 162 | PixelShader = freezeFramePS; 163 | 164 | RenderTarget = texFreezeFrame; 165 | 166 | // Explicitly disable clearing render targets 167 | // scanlineBlendPass will not work properly if this ever defaults to true 168 | ClearRenderTargets = false; 169 | } 170 | pass generatePhosphorMask 171 | { 172 | // phosphor-mask.fxh 173 | VertexShader = generatePhosphorMaskVS; 174 | PixelShader = generatePhosphorMaskPS; 175 | 176 | RenderTarget = texPhosphorMask; 177 | 178 | // This lets us improve performance by only computing the mask every k frames 179 | ClearRenderTargets = false; 180 | 181 | PrimitiveTopology = TRIANGLESTRIP; 182 | VertexCount = 4; 183 | } 184 | pass applyPhosphormask 185 | { 186 | // phosphor-mask.fxh 187 | // Tile the scaled phosphor mask and apply it to 188 | // the deinterlaced image. 189 | VertexShader = PostProcessVS; 190 | PixelShader = applyComputedPhosphorMaskPS; 191 | 192 | RenderTarget = texMaskedScanlines; 193 | // RenderTarget = texGeometry; 194 | } 195 | pass brightpassPass 196 | { 197 | // brightpass.fxh 198 | // Apply a brightpass filter for the bloom effect 199 | VertexShader = brightpassVS; 200 | PixelShader = brightpassPS; 201 | 202 | RenderTarget = texBrightpass; 203 | } 204 | pass bloomVerticalPass 205 | { 206 | // bloom.fxh 207 | // Blur vertically for the bloom effect 208 | VertexShader = bloomVerticalVS; 209 | PixelShader = bloomVerticalPS; 210 | 211 | RenderTarget = texBloomVertical; 212 | } 213 | pass bloomHorizontalPass 214 | { 215 | // bloom.fxh 216 | // Blur horizontally for the bloom effect. 217 | // Also apply various color changes and effects. 218 | VertexShader = bloomHorizontalVS; 219 | PixelShader = bloomHorizontalPS; 220 | 221 | RenderTarget = texBloomHorizontal; 222 | } 223 | pass geometryPass 224 | { 225 | // geometry-aa-last-pass.fxh 226 | // Apply screen geometry and anti-aliasing. 227 | VertexShader = geometryVS; 228 | PixelShader = geometryPS; 229 | 230 | RenderTarget = texGeometry; 231 | } 232 | pass uncropPass 233 | { 234 | // content-box.fxh 235 | // Uncrop the video, so we draw the game's content 236 | // in the same position it started in. 237 | VertexShader = contentUncropVS; 238 | PixelShader = uncropContentPixelShader; 239 | 240 | PrimitiveTopology = TRIANGLESTRIP; 241 | VertexCount = 4; 242 | } 243 | #endif 244 | } -------------------------------------------------------------------------------- /reshade/Shaders/crt/crt-royale/src/crt-royale-mask-resize-vertical.fxh: -------------------------------------------------------------------------------- 1 | ///////////////////////////// GPL LICENSE NOTICE ///////////////////////////// 2 | 3 | // crt-royale: A full-featured CRT shader, with cheese. 4 | // Copyright (C) 2014 TroggleMonkey 5 | // 6 | // This program is free software; you can redistribute it and/or modify it 7 | // under the terms of the GNU General Public License as published by the Free 8 | // Software Foundation; either version 2 of the License, or any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, but WITHOUT 11 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 | // more details. 14 | // 15 | // You should have received a copy of the GNU General Public License along with 16 | // this program; if not, write to the Free Software Foundation, Inc., 59 Temple 17 | // Place, Suite 330, Boston, MA 02111-1307 USA 18 | 19 | 20 | ///////////////////////////// SETTINGS MANAGEMENT //////////////////////////// 21 | 22 | #include "../include/user-settings.fxh" 23 | #include "../include/derived-settings-and-constants.fxh" 24 | #include "../include/bind-shader-params.fxh" 25 | 26 | 27 | ////////////////////////////////// INCLUDES ////////////////////////////////// 28 | 29 | #include "../include/phosphor-mask-resizing.fxh" 30 | 31 | 32 | ///////////////////////////////// STRUCTURES ///////////////////////////////// 33 | 34 | struct out_vertex_p5 35 | { 36 | float2 src_tex_uv_wrap : TEXCOORD1; 37 | float2 resize_magnification_scale : TEXCOORD2; 38 | }; 39 | 40 | 41 | //////////////////////////////// VERTEX SHADER /////////////////////////////// 42 | 43 | // Vertex shader generating a triangle covering the entire screen 44 | void VS_Mask_Resize_Vertical(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out out_vertex_p5 OUT) 45 | { 46 | texcoord.x = (id == 2) ? 2.0 : 0.0; 47 | texcoord.y = (id == 1) ? 2.0 : 0.0; 48 | position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 49 | 50 | float2 tex_uv = texcoord; 51 | 52 | float2 texture_size = MASK_RESIZE_VERT_texture_size; 53 | float2 output_size = float2(64.0, 0.0625*((VIEWPORT_SIZE).y)); 54 | 55 | // First estimate the viewport size (the user will get the wrong number of 56 | // triads if it's wrong and mask_specify_num_triads is 1.0/true). 57 | const float viewport_y = output_size.y / mask_resize_viewport_scale.y; 58 | // Now get aspect_ratio from texture_size. 59 | // const float aspect_ratio = geom_aspect_ratio_x / geom_aspect_ratio_y; 60 | const float aspect_ratio = texture_size.x / texture_size.y; 61 | const float2 estimated_viewport_size = 62 | float2(viewport_y * aspect_ratio, viewport_y); 63 | // Estimate the output size of MASK_RESIZE (the next pass). The estimated 64 | // x component shouldn't matter, because we're not using the x result, and 65 | // we're not swearing it's correct (if we did, the x result would influence 66 | // the y result to maintain the tile aspect ratio). 67 | const float2 estimated_mask_resize_output_size = 68 | float2(output_size.y * aspect_ratio, output_size.y); 69 | // Find the final intended [y] size of our resized phosphor mask tiles, 70 | // then the tile size for the current pass (resize y only): 71 | const float2 mask_resize_tile_size = get_resized_mask_tile_size( 72 | estimated_viewport_size, estimated_mask_resize_output_size, false); 73 | const float2 pass_output_tile_size = float2(min( 74 | mask_resize_src_lut_size.x, output_size.x), mask_resize_tile_size.y); 75 | 76 | // We'll render resized tiles until filling the output FBO or meeting a 77 | // limit, so compute [wrapped] tile uv coords based on the output uv coords 78 | // and the number of tiles that will fit in the FBO. 79 | const float2 output_tiles_this_pass = output_size / pass_output_tile_size; 80 | const float2 output_video_uv = tex_uv * texture_size / video_size; 81 | const float2 tile_uv_wrap = output_video_uv * output_tiles_this_pass; 82 | 83 | // The input LUT is just a single mask tile, so texture uv coords are the 84 | // same as tile uv coords (save frac() for the fragment shader). The 85 | // magnification scale is also straightforward: 86 | OUT.src_tex_uv_wrap = tile_uv_wrap; 87 | OUT.resize_magnification_scale = 88 | pass_output_tile_size / mask_resize_src_lut_size; 89 | } 90 | 91 | 92 | /////////////////////////////// FRAGMENT SHADER ////////////////////////////// 93 | 94 | float4 PS_Mask_Resize_Vertical(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in out_vertex_p5 VAR) : SV_Target 95 | { 96 | // Resize the input phosphor mask tile to the final vertical size it will 97 | // appear on screen. Keep 1x horizontal size if possible (IN.output_size 98 | // >= mask_resize_src_lut_size), and otherwise linearly sample horizontally 99 | // to fit exactly one tile. Lanczos-resizing the phosphor mask achieves 100 | // much sharper results than mipmapping, and vertically resizing first 101 | // minimizes the total number of taps required. We output a number of 102 | // resized tiles >= mask_resize_num_tiles for easier tiled sampling later. 103 | #ifdef PHOSPHOR_MASK_MANUALLY_RESIZE 104 | // Discard unneeded fragments in case our profile allows real branches. 105 | const float2 tile_uv_wrap = VAR.src_tex_uv_wrap; 106 | if(get_mask_sample_mode() < 0.5 && 107 | tile_uv_wrap.y <= mask_resize_num_tiles) 108 | { 109 | static const float src_dy = 1.0/mask_resize_src_lut_size.y; 110 | const float2 src_tex_uv = frac(VAR.src_tex_uv_wrap); 111 | float3 pixel_color; 112 | // If mask_type is static, this branch will be resolved statically. 113 | #ifdef PHOSPHOR_MASK_RESIZE_MIPMAPPED_LUT 114 | if(mask_type < 0.5) 115 | { 116 | pixel_color = downsample_vertical_sinc_tiled( 117 | mask_grille_texture_large, src_tex_uv, mask_resize_src_lut_size, 118 | src_dy, VAR.resize_magnification_scale.y, 1.0); 119 | } 120 | else if(mask_type < 1.5) 121 | { 122 | pixel_color = downsample_vertical_sinc_tiled( 123 | mask_slot_texture_large, src_tex_uv, mask_resize_src_lut_size, 124 | src_dy, VAR.resize_magnification_scale.y, 1.0); 125 | } 126 | else 127 | { 128 | pixel_color = downsample_vertical_sinc_tiled( 129 | mask_shadow_texture_large, src_tex_uv, mask_resize_src_lut_size, 130 | src_dy, VAR.resize_magnification_scale.y, 1.0); 131 | } 132 | #else 133 | if(mask_type < 0.5) 134 | { 135 | pixel_color = downsample_vertical_sinc_tiled( 136 | mask_grille_texture_small, src_tex_uv, mask_resize_src_lut_size, 137 | src_dy, VAR.resize_magnification_scale.y, 1.0); 138 | } 139 | else if(mask_type < 1.5) 140 | { 141 | pixel_color = downsample_vertical_sinc_tiled( 142 | mask_slot_texture_small, src_tex_uv, mask_resize_src_lut_size, 143 | src_dy, VAR.resize_magnification_scale.y, 1.0); 144 | } 145 | else 146 | { 147 | pixel_color = downsample_vertical_sinc_tiled( 148 | mask_shadow_texture_small, src_tex_uv, mask_resize_src_lut_size, 149 | src_dy, VAR.resize_magnification_scale.y, 1.0); 150 | } 151 | #endif 152 | // The input LUT was linear RGB, and so is our output: 153 | return float4(pixel_color, 1.0); 154 | } 155 | else 156 | { 157 | discard; 158 | } 159 | #else 160 | discard; 161 | return 1.0.xxxx; 162 | #endif 163 | } 164 | 165 | -------------------------------------------------------------------------------- /dolphinfx/crt/CRT-EASYMODE.glsl: -------------------------------------------------------------------------------- 1 | // CRT Shader by EasyMode 2 | // License: GPL 3 | 4 | // A flat CRT shader ideally for 1080p or higher displays. 5 | 6 | // Recommended Settings: 7 | 8 | // Video 9 | // - Aspect Ratio: 4:3 10 | // - Integer Scale: Off 11 | 12 | // Shader 13 | // - Filter: Nearest 14 | // - Scale: Don't Care 15 | 16 | // Example RGB Mask Parameter Settings: 17 | 18 | // Aperture Grille (Default) 19 | // - Dot Width: 1 20 | // - Dot Height: 1 21 | // - Stagger: 0 22 | 23 | // Lottes' Shadow Mask 24 | // - Dot Width: 2 25 | // - Dot Height: 1 26 | // - Stagger: 3 27 | 28 | 29 | /* 30 | [configuration] 31 | 32 | [OptionRangeFloat] 33 | GUIName = Sharpness Horizontal 34 | OptionName = SHARPNESS_H 35 | MinValue = 0.0 36 | MaxValue = 1.0 37 | StepAmount = 0.05 38 | DefaultValue = 0.5 39 | 40 | [OptionRangeFloat] 41 | GUIName = Sharpness Vertical 42 | OptionName = SHARPNESS_V 43 | MinValue = 0.0 44 | MaxValue = 1.0 45 | StepAmount = 0.05 46 | DefaultValue = 1.0 47 | 48 | [OptionRangeFloat] 49 | GUIName = Mask Strength 50 | OptionName = MASK_STRENGTH 51 | MinValue = 0.0 52 | MaxValue = 1.0 53 | StepAmount = 0.01 54 | DefaultValue = 0.3 55 | 56 | [OptionRangeFloat] 57 | GUIName = Mask Dot Width 58 | OptionName = MASK_DOT_WIDTH 59 | MinValue = 1.0 60 | MaxValue = 100.0 61 | StepAmount = 1.0 62 | DefaultValue = 1.0 63 | 64 | [OptionRangeFloat] 65 | GUIName = Mask Dot Height 66 | OptionName = MASK_DOT_HEIGHT 67 | MinValue = 1.0 68 | MaxValue = 100.0 69 | StepAmount = 1.0 70 | DefaultValue = 1.0 71 | 72 | [OptionRangeFloat] 73 | GUIName = Mask Stagger 74 | OptionName = MASK_STAGGER 75 | MinValue = 0.0 76 | MaxValue = 100.0 77 | StepAmount = 1.0 78 | DefaultValue = 0.0 79 | 80 | [OptionRangeFloat] 81 | GUIName = Mask Size 82 | OptionName = MASK_SIZE 83 | MinValue = 1.0 84 | MaxValue = 100.0 85 | StepAmount = 1.0 86 | DefaultValue = 1.0 87 | 88 | [OptionRangeFloat] 89 | GUIName = Scanline Strength 90 | OptionName = SCANLINE_STRENGTH 91 | MinValue = 0.0 92 | MaxValue = 1.0 93 | StepAmount = 0.05 94 | DefaultValue = 1.0 95 | 96 | [OptionRangeFloat] 97 | GUIName = Scanline Beam Width Min. 98 | OptionName = SCANLINE_BEAM_WIDTH_MIN 99 | MinValue = 0.5 100 | MaxValue = 5.0 101 | StepAmount = 0.5 102 | DefaultValue = 1.5 103 | 104 | [OptionRangeFloat] 105 | GUIName = Scanline Beam Width Max. 106 | OptionName = SCANLINE_BEAM_WIDTH_MAX 107 | MinValue = 0.5 108 | MaxValue = 5.0 109 | StepAmount = 0.5 110 | DefaultValue = 1.5 111 | 112 | [OptionRangeFloat] 113 | GUIName = Scanline Brightness Min. 114 | OptionName = SCANLINE_BRIGHT_MIN 115 | MinValue = 0.0 116 | MaxValue = 1.0 117 | StepAmount = 0.05 118 | DefaultValue = 0.35 119 | 120 | [OptionRangeFloat] 121 | GUIName = Scanline Brightness Max. 122 | OptionName = SCANLINE_BRIGHT_MAX 123 | MinValue = 0.0 124 | MaxValue = 1.0 125 | StepAmount = 0.05 126 | DefaultValue = 0.65 127 | 128 | [OptionRangeFloat] 129 | GUIName = Scanline Cutoff 130 | OptionName = SCANLINE_CUTOFF 131 | MinValue = 1.0 132 | MaxValue = 1000.0 133 | StepAmount = 1.0 134 | DefaultValue = 400.0 135 | 136 | [OptionRangeFloat] 137 | GUIName = Gamma Input 138 | OptionName = GAMMA_INPUT 139 | MinValue = 0.1 140 | MaxValue = 5.0 141 | StepAmount = 0.1 142 | DefaultValue = 2.0 143 | 144 | [OptionRangeFloat] 145 | GUIName = Gamma Output 146 | OptionName = GAMMA_OUTPUT 147 | MinValue = 0.1 148 | MaxValue = 5.0 149 | StepAmount = 0.1 150 | DefaultValue = 1.8 151 | 152 | [OptionRangeFloat] 153 | GUIName = Brightness Boost 154 | OptionName = BRIGHT_BOOST 155 | MinValue = 1.0 156 | MaxValue = 2.0 157 | StepAmount = 0.01 158 | DefaultValue = 1.2 159 | 160 | [OptionRangeFloat] 161 | GUIName = Dilation 162 | OptionName = DILATION 163 | MinValue = 0.0 164 | MaxValue = 1.0 165 | StepAmount = 1.0 166 | DefaultValue = 1.0 167 | 168 | [/configuration] 169 | */ 170 | 171 | #define FIX(c) max(abs(c), 1e-5) 172 | #define PI 3.141592653589 173 | 174 | #define TEX2D(c) dilate(SampleLocation(c)) 175 | 176 | // Set to 0 to use linear filter and gain speed 177 | #define ENABLE_LANCZOS 1 178 | 179 | vec4 dilate(vec4 col) 180 | { 181 | vec4 x = mix(vec4(1.0), col, GetOption(DILATION)); 182 | 183 | return col * x; 184 | } 185 | 186 | float curve_distance(float x, float sharp) 187 | { 188 | 189 | /* 190 | apply half-circle s-curve to distance for sharper (more pixelated) interpolation 191 | single line formula for Graph Toy: 192 | 0.5 - sqrt(0.25 - (x - step(0.5, x)) * (x - step(0.5, x))) * sign(0.5 - x) 193 | */ 194 | 195 | float x_step = step(0.5, x); 196 | float curve = 0.5 - sqrt(0.25 - (x - x_step) * (x - x_step)) * sign(0.5 - x); 197 | 198 | return mix(x, curve, sharp); 199 | } 200 | 201 | mat4x4 get_color_matrix(vec2 co, vec2 dx) 202 | { 203 | return mat4x4(TEX2D(co - dx), TEX2D(co), TEX2D(co + dx), TEX2D(co + 2.0 * dx)); 204 | } 205 | 206 | vec3 filter_lanczos(vec4 coeffs, mat4x4 color_matrix) 207 | { 208 | vec4 col = color_matrix * coeffs; 209 | vec4 sample_min = min(color_matrix[1], color_matrix[2]); 210 | vec4 sample_max = max(color_matrix[1], color_matrix[2]); 211 | 212 | col = clamp(col, sample_min, sample_max); 213 | 214 | return col.rgb; 215 | } 216 | 217 | void main() 218 | { 219 | vec2 vTexCoord = GetCoordinates(); 220 | vec2 nativeSize = 1.0 / GetInvNativePixelSize(); 221 | vec4 SourceSize = vec4(nativeSize, 1.0/nativeSize); 222 | 223 | vec2 dx = vec2(SourceSize.z, 0.0); 224 | vec2 dy = vec2(0.0, SourceSize.w); 225 | vec2 pix_co = vTexCoord * SourceSize.xy - vec2(0.5, 0.5); 226 | vec2 tex_co = (floor(pix_co) + vec2(0.5, 0.5)) * SourceSize.zw; 227 | vec2 dist = fract(pix_co); 228 | float curve_x; 229 | vec3 col, col2; 230 | 231 | #if ENABLE_LANCZOS 232 | curve_x = curve_distance(dist.x, GetOption(SHARPNESS_H) * GetOption(SHARPNESS_H)); 233 | 234 | vec4 coeffs = PI * vec4(1.0 + curve_x, curve_x, 1.0 - curve_x, 2.0 - curve_x); 235 | 236 | coeffs = FIX(coeffs); 237 | coeffs = 2.0 * sin(coeffs) * sin(coeffs * 0.5) / (coeffs * coeffs); 238 | coeffs /= dot(coeffs, vec4(1.0)); 239 | 240 | col = filter_lanczos(coeffs, get_color_matrix(tex_co, dx)); 241 | col2 = filter_lanczos(coeffs, get_color_matrix(tex_co + dy, dx)); 242 | #else 243 | curve_x = curve_distance(dist.x, GetOption(SHARPNESS_H)); 244 | 245 | col = mix(TEX2D(tex_co).rgb, TEX2D(tex_co + dx).rgb, curve_x); 246 | col2 = mix(TEX2D(tex_co + dy).rgb, TEX2D(tex_co + dx + dy).rgb, curve_x); 247 | #endif 248 | 249 | col = mix(col, col2, curve_distance(dist.y, GetOption(SHARPNESS_V))); 250 | col = pow(col, vec3(GetOption(GAMMA_INPUT) / (GetOption(DILATION) + 1.0))); 251 | 252 | float luma = dot(vec3(0.2126, 0.7152, 0.0722), col); 253 | float bright = (max(col.r, max(col.g, col.b)) + luma) * 0.5; 254 | float scan_bright = clamp(bright, GetOption(SCANLINE_BRIGHT_MIN), GetOption(SCANLINE_BRIGHT_MAX)); 255 | float scan_beam = clamp(bright * GetOption(SCANLINE_BEAM_WIDTH_MAX), GetOption(SCANLINE_BEAM_WIDTH_MIN), GetOption(SCANLINE_BEAM_WIDTH_MAX)); 256 | float scan_weight = 1.0 - pow(cos(vTexCoord.y * 2.0 * PI * SourceSize.y) * 0.5 + 0.5, scan_beam) * GetOption(SCANLINE_STRENGTH); 257 | 258 | float mask = 1.0 - GetOption(MASK_STRENGTH); 259 | vec2 mod_fac = floor(vTexCoord * GetWindowSize().xy * SourceSize.xy / (SourceSize.xy * vec2(GetOption(MASK_SIZE), GetOption(MASK_DOT_HEIGHT) * GetOption(MASK_SIZE)))); 260 | int dot_no = int(mod((mod_fac.x + mod(mod_fac.y, 2.0) * GetOption(MASK_STAGGER)) / GetOption(MASK_DOT_WIDTH), 3.0)); 261 | vec3 mask_weight; 262 | 263 | if (dot_no == 0) mask_weight = vec3(1.0, mask, mask); 264 | else if (dot_no == 1) mask_weight = vec3(mask, 1.0, mask); 265 | else mask_weight = vec3(mask, mask, 1.0); 266 | 267 | if (SourceSize.y >= GetOption(SCANLINE_CUTOFF)) 268 | scan_weight = 1.0; 269 | 270 | col2 = col.rgb; 271 | col *= vec3(scan_weight); 272 | col = mix(col, col2, scan_bright); 273 | col *= mask_weight; 274 | col = pow(col, vec3(1.0 / GetOption(GAMMA_OUTPUT))); 275 | 276 | SetOutput(vec4(col * GetOption(BRIGHT_BOOST), 1.0)); 277 | } 278 | -------------------------------------------------------------------------------- /reshade/Shaders/crt-royale/shaders/phosphor-mask.fxh: -------------------------------------------------------------------------------- 1 | #ifndef _PHOSPHOR_MASK_H 2 | #define _PHOSPHOR_MASK_H 3 | 4 | ///////////////////////////////// MIT LICENSE //////////////////////////////// 5 | 6 | // Copyright (C) 2022 Alex Gunter 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal in the Software without restriction, including without limitation the 11 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12 | // sell copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24 | // IN THE SOFTWARE. 25 | 26 | 27 | #include "../lib/bind-shader-params.fxh" 28 | #include "../lib/phosphor-mask-calculations.fxh" 29 | 30 | #include "shared-objects.fxh" 31 | 32 | 33 | // Split into 64 segments that overlap a little bit 34 | static const float num_segments = 64; 35 | static const float segment_offset = 0.015625; // 1/64 36 | static const float segment_width = 0.0234375; // 1/128 37 | 38 | void generatePhosphorMaskVS( 39 | in uint id : SV_VertexID, 40 | 41 | out float4 position : SV_Position, 42 | out float2 texcoord : TEXCOORD0, 43 | out float2 viewport_frequency_factor: TEXCOORD1, 44 | out float2 mask_pq_x : TEXCOORD2, 45 | out float2 mask_pq_y : TEXCOORD3 46 | ) { 47 | const float screen_segment_idx = frame_count % num_segments; 48 | const float left_coord = lerp(segment_offset * screen_segment_idx, 0, overlay_active > 0); 49 | const float right_coord = lerp(left_coord + segment_width, 1, overlay_active > 0); 50 | const float pos_center = 2 * (left_coord + 0.5 * segment_width - 0.5); 51 | const float pos_left = lerp(pos_center - segment_width, -1, overlay_active > 0); 52 | const float pos_right = lerp(pos_center + segment_width, 1, overlay_active > 0); 53 | 54 | #if _DX9_ACTIVE 55 | texcoord.x = (id == 1 || id == 3) ? right_coord : left_coord; 56 | texcoord.y = (id > 1) ? 1 : 0; 57 | 58 | position.x = (id == 1 || id == 3) ? pos_right : pos_left; 59 | position.y = (id > 1) ? -1 : 1; 60 | position.zw = 1; 61 | #else 62 | texcoord.x = (id & 1) ? right_coord : left_coord; 63 | texcoord.y = (id & 2) ? 1 : 0; 64 | 65 | position.x = (id & 1) ? pos_right : pos_left; 66 | position.y = (id & 2) ? -1 : 1; 67 | position.zw = 1; 68 | #endif 69 | 70 | viewport_frequency_factor = calc_phosphor_viewport_frequency_factor(); 71 | 72 | // We don't alter these based on screen rotation because they're independent of screen dimensions. 73 | float edge_norm_tx; 74 | float edge_norm_ty; 75 | [flatten] 76 | switch (mask_type) { 77 | case 0: 78 | edge_norm_tx = grille_edge_norm_t; 79 | break; 80 | case 1: 81 | edge_norm_tx = slot_edge_norm_tx; 82 | edge_norm_ty = slot_edge_norm_ty; 83 | break; 84 | case 2: 85 | edge_norm_tx = shadow_edge_norm_tx; 86 | edge_norm_ty = shadow_edge_norm_ty; 87 | break; 88 | case 3: 89 | edge_norm_tx = smallgrille_edge_norm_t; 90 | break; 91 | case 4: 92 | edge_norm_tx = smallslot_edge_norm_tx; 93 | edge_norm_ty = smallslot_edge_norm_ty; 94 | break; 95 | default: 96 | edge_norm_tx = smallshadow_edge_norm_tx; 97 | edge_norm_ty = smallshadow_edge_norm_ty; 98 | break; 99 | } 100 | 101 | const float2 thickness_scaled = linearize_phosphor_thickness_param(phosphor_thickness); 102 | const float mask_p_x = exp(-calculate_phosphor_p_value(edge_norm_tx, thickness_scaled.x, phosphor_sharpness.x)); 103 | const float mask_p_y = exp(-calculate_phosphor_p_value(edge_norm_ty, thickness_scaled.y, phosphor_sharpness.y)); 104 | mask_pq_x = float2(mask_p_x, phosphor_sharpness.x); 105 | mask_pq_y = float2(mask_p_y, phosphor_sharpness.y); 106 | } 107 | 108 | void generatePhosphorMaskPS( 109 | in float4 pos : SV_Position, 110 | in float2 texcoord : TEXCOORD0, 111 | in float2 viewport_frequency_factor: TEXCOORD1, 112 | in float2 mask_pq_x : TEXCOORD2, 113 | in float2 mask_pq_y : TEXCOORD3, 114 | 115 | out float4 color : SV_Target 116 | ) { 117 | [branch] 118 | if (geom_rotation_mode == 1 || geom_rotation_mode == 3) { 119 | texcoord = texcoord.yx; 120 | viewport_frequency_factor = viewport_frequency_factor.yx; 121 | } 122 | 123 | float3 phosphor_color; 124 | [branch] 125 | if (mask_type == 0) { 126 | phosphor_color = get_phosphor_intensity_grille( 127 | texcoord, 128 | viewport_frequency_factor, 129 | mask_pq_x 130 | ); 131 | } 132 | else if (mask_type == 1) { 133 | phosphor_color = get_phosphor_intensity_slot( 134 | texcoord, 135 | viewport_frequency_factor, 136 | mask_pq_x, 137 | mask_pq_y 138 | ); 139 | } 140 | else if (mask_type == 2) { 141 | phosphor_color = get_phosphor_intensity_shadow( 142 | texcoord, 143 | viewport_frequency_factor, 144 | float2(mask_pq_x.y, mask_pq_y.y) 145 | ); 146 | } 147 | else if (mask_type == 3) { 148 | phosphor_color = get_phosphor_intensity_grille_small( 149 | texcoord, 150 | viewport_frequency_factor, 151 | mask_pq_x 152 | ); 153 | } 154 | else if (mask_type == 4) { 155 | phosphor_color = get_phosphor_intensity_slot_small( 156 | texcoord, 157 | viewport_frequency_factor, 158 | mask_pq_x, 159 | mask_pq_y 160 | ); 161 | } 162 | else { 163 | phosphor_color = get_phosphor_intensity_shadow_small( 164 | texcoord, 165 | viewport_frequency_factor, 166 | mask_pq_x, 167 | mask_pq_y 168 | ); 169 | } 170 | 171 | color = float4(phosphor_color, 1.0); 172 | } 173 | 174 | 175 | void applyComputedPhosphorMaskPS( 176 | in float4 pos : SV_Position, 177 | in float2 texcoord : TEXCOORD0, 178 | 179 | out float4 color : SV_Target 180 | ) { 181 | bool use_deinterlacing_tex = enable_interlacing && ( 182 | scanline_deinterlacing_mode == 2 || scanline_deinterlacing_mode == 3 183 | ); 184 | 185 | float3 scanline_color_dim; 186 | [branch] 187 | if (use_deinterlacing_tex) scanline_color_dim = tex2D(samplerDeinterlace, texcoord).rgb; 188 | else scanline_color_dim = tex2D(samplerBeamConvergence, texcoord).rgb; 189 | 190 | const float3 phosphor_color = tex2D(samplerPhosphorMask, texcoord).rgb; 191 | 192 | // Sample the halation texture (auto-dim to match the scanlines), and 193 | // account for both horizontal and vertical convergence offsets, given 194 | // in units of texels horizontally and same-field scanlines vertically: 195 | const float3 halation_color = tex2D_linearize(samplerBlurHorizontal, texcoord, get_intermediate_gamma()).rgb; 196 | 197 | // Apply halation: Halation models electrons flying around under the glass 198 | // and hitting the wrong phosphors (of any color). It desaturates, so 199 | // average the halation electrons to a scalar. Reduce the local scanline 200 | // intensity accordingly to conserve energy. 201 | const float halation_intensity_dim_scalar = dot(halation_color, float3(1, 1, 1)) / 3.0; 202 | const float3 halation_intensity_dim = halation_intensity_dim_scalar; 203 | const float3 electron_intensity_dim = lerp(scanline_color_dim, halation_intensity_dim, halation_weight); 204 | 205 | // Apply the phosphor mask: 206 | const float3 phosphor_emission_dim = electron_intensity_dim * phosphor_color; 207 | 208 | color = float4(phosphor_emission_dim, 1.0); 209 | } 210 | 211 | #endif // _PHOSPHOR_MASK_H -------------------------------------------------------------------------------- /reshade/Shaders/crt-royale/shaders/content-box.fxh: -------------------------------------------------------------------------------- 1 | #ifndef _CONTENT_BOX_H 2 | #define _CONTENT_BOX_H 3 | 4 | ///////////////////////////////// MIT LICENSE //////////////////////////////// 5 | 6 | // Copyright (C) 2020 Alex Gunter 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to 10 | // deal in the Software without restriction, including without limitation the 11 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 12 | // sell copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 24 | // IN THE SOFTWARE. 25 | 26 | 27 | #include "shared-objects.fxh" 28 | 29 | 30 | void contentCropVS( 31 | in uint id : SV_VertexID, 32 | 33 | out float4 position : SV_Position, 34 | out float2 texcoord : TEXCOORD0 35 | ) { 36 | #if _DX9_ACTIVE 37 | texcoord.x = (id == 1 || id == 3) ? content_right : content_left; 38 | texcoord.y = (id > 1) ? content_lower : content_upper; 39 | 40 | position.x = (id == 1 || id == 3) ? 1 : -1; 41 | position.y = (id > 1) ? -1 : 1; 42 | position.zw = 1; 43 | #else 44 | texcoord.x = (id & 1) ? content_right : content_left; 45 | texcoord.y = (id & 2) ? content_lower : content_upper; 46 | 47 | position.x = (id & 1) ? 1 : -1; 48 | position.y = (id & 2) ? -1 : 1; 49 | position.zw = 1; 50 | #endif 51 | } 52 | 53 | #if USE_VERTEX_UNCROPPING 54 | /* 55 | * Using the vertex shader for uncropping can save about 0.1ms in some apps. 56 | * However, some apps like SNES9X w/ DX9 don't trigger a refresh of the entire screen, 57 | * which in turn causes the ReShade UI to "stick around" after it's closed. 58 | * 59 | * The slower algorithm forces the entire screen to refresh, which forces the 60 | * area outside the content box to be black. I assume most users will prefer 61 | * the results of the slower algorithm and won't notice the 0.1ms. Users who 62 | * need that 0.1ms can use a preprocessor def to recover that time. 63 | */ 64 | void contentUncropVS( 65 | in uint id : SV_VertexID, 66 | 67 | out float4 position : SV_Position, 68 | out float2 texcoord : TEXCOORD0 69 | ) { 70 | #if _DX9_ACTIVE 71 | texcoord.x = id == 1 || id == 3; 72 | texcoord.y = id < 2; 73 | 74 | position.x = (id == 1 || id == 3) ? content_scale.x : -content_scale.x; 75 | position.y = (id > 1) ? content_scale.y : -content_scale.y; 76 | position.zw = 1; 77 | #else 78 | texcoord.x = id & 1; 79 | texcoord.y = !(id & 2); 80 | 81 | position.x = (id & 1) ? content_scale.x : -content_scale.x; 82 | position.y = (id & 2) ? content_scale.y : -content_scale.y; 83 | position.zw = 1; 84 | #endif 85 | } 86 | 87 | void uncropContentPixelShader( 88 | in float4 pos : SV_Position, 89 | in float2 texcoord : TEXCOORD0, 90 | 91 | out float4 color : SV_Target 92 | ) { 93 | color = tex2D(samplerGeometry, texcoord); 94 | } 95 | #else 96 | void contentUncropVS( 97 | in uint id : SV_VertexID, 98 | 99 | out float4 position : SV_Position, 100 | out float2 texcoord : TEXCOORD0 101 | ) { 102 | // TODO: There's probably a better way to code this. 103 | // I'll figure it out later. 104 | #if _DX9_ACTIVE 105 | texcoord.x = id == 1 || id == 3; 106 | texcoord.y = id < 2; 107 | 108 | position.x = (id == 1 || id == 3) ? 1 : -1; 109 | position.y = (id > 1) ? 1 : -1; 110 | position.zw = 1; 111 | #else 112 | texcoord.x = id & 1; 113 | texcoord.y = !(id & 2); 114 | 115 | position.x = (id & 1) ? 1 : -1; 116 | position.y = (id & 2) ? 1 : -1; 117 | position.zw = 1; 118 | #endif 119 | } 120 | 121 | void uncropContentPixelShader( 122 | in float4 pos : SV_Position, 123 | in float2 texcoord : TEXCOORD0, 124 | 125 | out float4 color : SV_Target 126 | ) { 127 | const bool is_in_boundary = float( 128 | texcoord.x >= content_left && texcoord.x <= content_right && 129 | texcoord.y >= content_upper && texcoord.y <= content_lower 130 | ); 131 | const float2 texcoord_uncropped = ((texcoord - content_offset) * buffer_size + 0) / content_size; 132 | 133 | const float4 raw_color = tex2D(samplerGeometry, texcoord_uncropped); 134 | color = float4(is_in_boundary * raw_color.rgb, raw_color.a); 135 | } 136 | #endif 137 | 138 | 139 | #if CONTENT_BOX_VISIBLE 140 | #ifndef CONTENT_BOX_INSCRIBED 141 | #define CONTENT_BOX_INSCRIBED 1 142 | #endif 143 | 144 | #ifndef CONTENT_BOX_THICKNESS 145 | #define CONTENT_BOX_THICKNESS 5 146 | #endif 147 | 148 | #ifndef CONTENT_BOX_COLOR_R 149 | #define CONTENT_BOX_COLOR_R 1.0 150 | #endif 151 | 152 | #ifndef CONTENT_BOX_COLOR_G 153 | #define CONTENT_BOX_COLOR_G 0.0 154 | #endif 155 | 156 | #ifndef CONTENT_BOX_COLOR_B 157 | #define CONTENT_BOX_COLOR_B 0.0 158 | #endif 159 | 160 | static const float vert_line_thickness = float(CONTENT_BOX_THICKNESS) / BUFFER_WIDTH; 161 | static const float horiz_line_thickness = float(CONTENT_BOX_THICKNESS) / BUFFER_HEIGHT; 162 | 163 | #if CONTENT_BOX_INSCRIBED 164 | // Set the outer borders to the edge of the content 165 | static const float left_line_1 = content_left; 166 | static const float left_line_2 = left_line_1 + vert_line_thickness; 167 | static const float right_line_2 = content_right; 168 | static const float right_line_1 = right_line_2 - vert_line_thickness; 169 | 170 | static const float upper_line_1 = content_upper; 171 | static const float upper_line_2 = upper_line_1 + horiz_line_thickness; 172 | static const float lower_line_2 = content_lower; 173 | static const float lower_line_1 = lower_line_2 - horiz_line_thickness; 174 | #else 175 | // Set the inner borders to the edge of the content 176 | static const float left_line_2 = content_left; 177 | static const float left_line_1 = left_line_2 - vert_line_thickness; 178 | static const float right_line_1 = content_right; 179 | static const float right_line_2 = right_line_1 + vert_line_thickness; 180 | 181 | static const float upper_line_2 = content_upper; 182 | static const float upper_line_1 = upper_line_2 - horiz_line_thickness; 183 | static const float lower_line_1 = content_lower; 184 | static const float lower_line_2 = lower_line_1 + horiz_line_thickness; 185 | #endif 186 | 187 | 188 | static const float4 box_color = float4( 189 | CONTENT_BOX_COLOR_R, 190 | CONTENT_BOX_COLOR_G, 191 | CONTENT_BOX_COLOR_B, 192 | 1.0 193 | ); 194 | 195 | void contentBoxPixelShader( 196 | in float4 pos : SV_Position, 197 | in float2 texcoord : TEXCOORD0, 198 | 199 | out float4 color : SV_Target 200 | ) { 201 | 202 | const bool is_inside_outerbound = ( 203 | texcoord.x >= left_line_1 && texcoord.x <= right_line_2 && 204 | texcoord.y >= upper_line_1 && texcoord.y <= lower_line_2 205 | ); 206 | const bool is_outside_innerbound = ( 207 | texcoord.x <= left_line_2 || texcoord.x >= right_line_1 || 208 | texcoord.y <= upper_line_2 || texcoord.y >= lower_line_1 209 | ); 210 | 211 | if (is_inside_outerbound && is_outside_innerbound) { 212 | color = box_color; 213 | } 214 | else { 215 | color = tex2D(ReShade::BackBuffer, texcoord); 216 | } 217 | } 218 | 219 | 220 | #endif // CONTENT_BOX_VISIBLE 221 | #endif // _CONTENT_BOX_H -------------------------------------------------------------------------------- /reshade/Shaders/misc/include/mask.fxh: -------------------------------------------------------------------------------- 1 | #ifndef MASK_PARAMS_H 2 | #define MASK_PARAMS_H 3 | 4 | uniform float MASK_DARK_STRENGTH < 5 | ui_type = "drag"; 6 | ui_min = 0.0; 7 | ui_max = 1.0; 8 | ui_step = 0.01; 9 | ui_category = "CRT Mask"; 10 | ui_label = "MASK DARK SUBPIXEL STRENGTH"; 11 | > = 0.5; 12 | 13 | uniform float MASK_LIGHT_STRENGTH < 14 | ui_type = "drag"; 15 | ui_min = 0.0; 16 | ui_max = 6.0; 17 | ui_step = 0.01; 18 | ui_category = "CRT Mask"; 19 | ui_label = "MASK LIGHT SUBPIXEL STRENGTH"; 20 | > = 0.5; 21 | 22 | /* Mask code pasted from subpixel_masks.h. Masks 3 and 4 added. */ 23 | float3 mask_weights(float2 coord, int phosphor_layout, float monitor_subpixels, float mask_light_str, float mask_dark_str){ 24 | float3 weights = float3(1.,1.,1.); 25 | float on = 1.+mask_light_str; 26 | // float on = 1.; 27 | float off = 1.-mask_dark_str; 28 | float3 red = monitor_subpixels==1.0 ? float3(on, off, off) : float3(off, off, on ); 29 | float3 green = float3(off, on, off); 30 | float3 blue = monitor_subpixels==1.0 ? float3(off, off, on ) : float3(on, off, off); 31 | float3 magenta = float3(on, off, on ); 32 | float3 yellow = monitor_subpixels==1.0 ? float3(on, on, off) : float3(off, on, on ); 33 | float3 cyan = monitor_subpixels==1.0 ? float3(off, on, on ) : float3(on, on, off); 34 | float3 black = float3(off, off, off); 35 | float3 white = float3(on, on, on ); 36 | int w, z = 0; 37 | 38 | // This pattern is used by a few layouts, so we'll define it here 39 | float3 aperture_weights = lerp(magenta, green, floor(coord.x % 2.0)); 40 | 41 | if(phosphor_layout == 0) return weights; 42 | 43 | else if(phosphor_layout == 1){ 44 | // classic aperture for RGB panels; good for 1080p, too small for 4K+ 45 | // aka aperture_1_2_bgr 46 | weights = aperture_weights; 47 | return weights; 48 | } 49 | 50 | else if(phosphor_layout == 2){ 51 | // Classic RGB layout; good for 1080p and lower 52 | float3 bw3[3] = {red, green, blue}; 53 | // float3 bw3[3] = float3[](black, yellow, blue); 54 | 55 | z = int(floor(coord.x % 3.0)); 56 | 57 | weights = bw3[z]; 58 | return weights; 59 | } 60 | 61 | else if(phosphor_layout == 3){ 62 | // black and white aperture; good for weird subpixel layouts and low brightness; good for 1080p and lower 63 | float3 bw3[3] = {black, white, black}; 64 | 65 | z = int(floor(coord.x % 3.0)); 66 | 67 | weights = bw3[z]; 68 | return weights; 69 | } 70 | 71 | else if(phosphor_layout == 4){ 72 | // reduced TVL aperture for RGB panels. Good for 4k. 73 | // aperture_2_4_rgb 74 | 75 | float3 big_ap_rgb[4] = {red, yellow, cyan, blue}; 76 | 77 | w = int(floor(coord.x % 4.0)); 78 | 79 | weights = big_ap_rgb[w]; 80 | return weights; 81 | } 82 | 83 | else if(phosphor_layout == 5){ 84 | // black and white aperture; good for weird subpixel layouts and low brightness; good for 4k 85 | float3 bw4[4] = {black, black, white, white}; 86 | 87 | z = int(floor(coord.x % 4.0)); 88 | 89 | weights = bw4[z]; 90 | return weights; 91 | } 92 | 93 | else if(phosphor_layout == 6){ 94 | // aperture_1_4_rgb; good for simulating lower 95 | float3 ap4[4] = {red, green, blue, black}; 96 | 97 | z = int(floor(coord.x % 4.0)); 98 | 99 | weights = ap4[z]; 100 | return weights; 101 | } 102 | 103 | else if(phosphor_layout == 7){ 104 | // 2x2 shadow mask for RGB panels; good for 1080p, too small for 4K+ 105 | // aka delta_1_2x1_bgr 106 | float3 inverse_aperture = lerp(green, magenta, floor(coord.x % 2.0)); 107 | weights = lerp(aperture_weights, inverse_aperture, floor(coord.y % 2.0)); 108 | return weights; 109 | } 110 | 111 | else if(phosphor_layout == 8){ 112 | // delta_2_4x1_rgb 113 | float3 delta[8] = { 114 | red, yellow, cyan, blue, 115 | cyan, blue, red, yellow 116 | }; 117 | 118 | w = int(floor(coord.y % 2.0)); 119 | z = int(floor(coord.x % 4.0)); 120 | 121 | weights = delta[4*w+z]; 122 | return weights; 123 | } 124 | 125 | else if(phosphor_layout == 9){ 126 | // delta_1_4x1_rgb; dunno why this is called 4x1 when it's obviously 4x2 /shrug 127 | float3 delta1[8] = { 128 | red, green, blue, black, 129 | blue, black, red, green 130 | }; 131 | 132 | w = int(floor(coord.y % 2.0)); 133 | z = int(floor(coord.x % 4.0)); 134 | 135 | weights = delta1[4*w+z]; 136 | return weights; 137 | } 138 | 139 | else if(phosphor_layout == 10){ 140 | // delta_2_4x2_rgb 141 | float3 delta[16] = { 142 | red, yellow, cyan, blue, 143 | red, yellow, cyan, blue, 144 | cyan, blue, red, yellow, 145 | cyan, blue, red, yellow 146 | }; 147 | 148 | w = int(floor(coord.y % 4.0)); 149 | z = int(floor(coord.x % 4.0)); 150 | 151 | weights = delta[4*w+z]; 152 | return weights; 153 | } 154 | 155 | else if(phosphor_layout == 11){ 156 | // slot mask for RGB panels; looks okay at 1080p, looks better at 4K 157 | float3 slotmask[24] = { 158 | red, green, blue, red, green, blue, 159 | red, green, blue, black, black, black, 160 | red, green, blue, red, green, blue, 161 | black, black, black, red, green, blue, 162 | }; 163 | 164 | w = int(floor(coord.y % 4.0)); 165 | z = int(floor(coord.x % 6.0)); 166 | 167 | // use the indexes to find which color to apply to the current pixel 168 | weights = slotmask[6*w+z]; 169 | return weights; 170 | } 171 | 172 | else if(phosphor_layout == 12){ 173 | // slot mask for RGB panels; looks okay at 1080p, looks better at 4K 174 | float3 slotmask[24] = { 175 | black, white, black, black, white, black, 176 | black, white, black, black, black, black, 177 | black, white, black, black, white, black, 178 | black, black, black, black, white, black 179 | }; 180 | 181 | w = int(floor(coord.y % 4.0)); 182 | z = int(floor(coord.x % 6.0)); 183 | 184 | // use the indexes to find which color to apply to the current pixel 185 | weights = slotmask[6*w+z]; 186 | return weights; 187 | } 188 | 189 | else if(phosphor_layout == 13){ 190 | // based on MajorPainInTheCactus' HDR slot mask 191 | float3 slot[32] = { 192 | red, green, blue, black, red, green, blue, black, 193 | red, green, blue, black, black, black, black, black, 194 | red, green, blue, black, red, green, blue, black, 195 | black, black, black, black, red, green, blue, black 196 | }; 197 | 198 | w = int(floor(coord.y % 4.0)); 199 | z = int(floor(coord.x % 8.0)); 200 | 201 | weights = slot[8*w+z]; 202 | return weights; 203 | } 204 | 205 | else if(phosphor_layout == 14){ 206 | // same as above but for RGB panels 207 | float3 slot2[40] = { 208 | red, yellow, green, blue, blue, red, yellow, green, blue, blue , 209 | black, green, green, blue, blue, red, red, black, black, black, 210 | red, yellow, green, blue, blue, red, yellow, green, blue, blue , 211 | red, red, black, black, black, black, green, green, blue, blue 212 | }; 213 | 214 | w = int(floor(coord.y % 4.0)); 215 | z = int(floor(coord.x % 10.0)); 216 | 217 | weights = slot2[10*w+z]; 218 | return weights; 219 | } 220 | 221 | else if(phosphor_layout == 15){ 222 | // slot_3_7x6_rgb 223 | float3 slot[84] = { 224 | red, red, yellow, green, cyan, blue, blue, red, red, yellow, green, cyan, blue, blue, 225 | red, red, yellow, green, cyan, blue, blue, red, red, yellow, green, cyan, blue, blue, 226 | red, red, yellow, green, cyan, blue, blue, black, black, black, black, black, black, black, 227 | red, red, yellow, green, cyan, blue, blue, red, red, yellow, green, cyan, blue, blue, 228 | red, red, yellow, green, cyan, blue, blue, red, red, yellow, green, cyan, blue, blue, 229 | black, black, black, black, black, black, black, black, red, red, yellow, green, cyan, blue 230 | }; 231 | 232 | w = int(floor(coord.y % 6.0)); 233 | z = int(floor(coord.x % 14.0)); 234 | 235 | weights = slot[14*w+z]; 236 | return weights; 237 | } 238 | 239 | else return weights; 240 | } 241 | 242 | #endif // MASK_PARAMS_H 243 | -------------------------------------------------------------------------------- /dolphinfx/bloom.glsl: -------------------------------------------------------------------------------- 1 | /*===============================================================================*\ 2 | |######################## [Dolphin FX Suite 2.20] #######################| 3 | |########################## By Asmodean ##########################| 4 | || || 5 | || This program is free software; you can redistribute it and/or || 6 | || modify it under the terms of the GNU General Public License || 7 | || as published by the Free Software Foundation; either version 2 || 8 | || of the License, or (at your option) any later version. || 9 | || || 10 | || This program is distributed in the hope that it will be useful, || 11 | || but WITHOUT ANY WARRANTY; without even the implied warranty of || 12 | || MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the || 13 | || GNU General Public License for more details. (C)2015 || 14 | || || 15 | |#################################################################################| 16 | \*===============================================================================*/ 17 | 18 | // Sourced from https://raw.githubusercontent.com/Asmodean-/dolphin/89d640cd557189bb5f921fc219150c74c39bdc55/Data/Sys/Shaders/DolphinFX.glsl with modifications. 19 | 20 | /* 21 | [configuration] 22 | 23 | [OptionRangeInteger] 24 | GUIName = BloomType 25 | OptionName = A_BLOOM_TYPE 26 | MinValue = 0 27 | MaxValue = 5 28 | StepAmount = 1 29 | DefaultValue = 0 30 | 31 | [OptionRangeFloat] 32 | GUIName = BloomStrength 33 | OptionName = B_BLOOM_STRENGTH 34 | MinValue = 0.000 35 | MaxValue = 1.000 36 | StepAmount = 0.001 37 | DefaultValue = 0.220 38 | 39 | [OptionRangeFloat] 40 | GUIName = BlendStrength 41 | OptionName = C_BLEND_STRENGTH 42 | MinValue = 0.000 43 | MaxValue = 1.200 44 | StepAmount = 0.010 45 | DefaultValue = 1.000 46 | 47 | [OptionRangeFloat] 48 | GUIName = BloomDefocus 49 | OptionName = D_B_DEFOCUS 50 | MinValue = 1.000 51 | MaxValue = 4.000 52 | StepAmount = 0.100 53 | DefaultValue = 2.000 54 | 55 | [OptionRangeFloat] 56 | GUIName = BloomWidth 57 | OptionName = D_BLOOM_WIDTH 58 | MinValue = 1.000 59 | MaxValue = 8.000 60 | StepAmount = 0.100 61 | DefaultValue = 3.200 62 | 63 | [OptionRangeFloat] 64 | GUIName = BloomReds 65 | OptionName = E_BLOOM_REDS 66 | MinValue = 0.000 67 | MaxValue = 0.500 68 | StepAmount = 0.001 69 | DefaultValue = 0.020 70 | 71 | [OptionRangeFloat] 72 | GUIName = BloomGreens 73 | OptionName = F_BLOOM_GREENS 74 | MinValue = 0.000 75 | MaxValue = 0.500 76 | StepAmount = 0.001 77 | DefaultValue = 0.010 78 | 79 | [OptionRangeFloat] 80 | GUIName = BloomBlues 81 | OptionName = G_BLOOM_BLUES 82 | MinValue = 0.000 83 | MaxValue = 0.500 84 | StepAmount = 0.001 85 | DefaultValue = 0.010 86 | 87 | [/configuration] 88 | */ 89 | 90 | //Average relative luminance 91 | CONSTANT float3 lumCoeff = float3(0.2126729, 0.7151522, 0.0721750); 92 | float AvgLuminance(float3 color) 93 | { 94 | return sqrt( 95 | (color.x * color.x * lumCoeff.x) + 96 | (color.y * color.y * lumCoeff.y) + 97 | (color.z * color.z * lumCoeff.z)); 98 | } 99 | 100 | float smootherstep(float a, float b, float x) 101 | { 102 | x = saturate((x - a) / (b - a)); 103 | return x*x*x*(x*(x * 6.0 - 15.0) + 10.0); 104 | } 105 | 106 | float3 BlendAddLight(float3 bloom, float3 blend) 107 | { 108 | return saturate(bloom + blend); 109 | } 110 | 111 | float3 BlendScreen(float3 bloom, float3 blend) 112 | { 113 | return (bloom + blend) - (bloom * blend); 114 | } 115 | 116 | float3 BlendAddGlow(float3 bloom, float3 blend) 117 | { 118 | float glow = smootherstep(0.0, 1.0, AvgLuminance(bloom)); 119 | return lerp(saturate(bloom + blend), 120 | (blend + blend) - (blend * blend), glow); 121 | } 122 | 123 | float3 BlendGlow(float3 bloom, float3 blend) 124 | { 125 | float glow = smootherstep(0.0, 1.0, AvgLuminance(bloom)); 126 | return lerp((bloom + blend) - (bloom * blend), 127 | (blend + blend) - (blend * blend), glow); 128 | } 129 | 130 | float3 BlendLuma(float3 bloom, float3 blend) 131 | { 132 | float lumavg = smootherstep(0.0, 1.0, AvgLuminance(bloom + blend)); 133 | return lerp((bloom * blend), (1.0 - 134 | ((1.0 - bloom) * (1.0 - blend))), lumavg); 135 | } 136 | 137 | float3 BlendOverlay(float3 bloom, float3 blend) 138 | { 139 | float3 overlay = step(0.5, bloom); 140 | return lerp((bloom * blend * 2.0), (1.0 - (2.0 * 141 | (1.0 - bloom) * (1.0 - blend))), overlay); 142 | } 143 | 144 | float3 BloomCorrection(float3 color) 145 | { 146 | float3 bloom = color; 147 | 148 | bloom.r = 2.0 / 3.0 * (1.0 - (bloom.r * bloom.r)); 149 | bloom.g = 2.0 / 3.0 * (1.0 - (bloom.g * bloom.g)); 150 | bloom.b = 2.0 / 3.0 * (1.0 - (bloom.b * bloom.b)); 151 | 152 | bloom.r = saturate(color.r + GetOption(E_BLOOM_REDS) * bloom.r); 153 | bloom.g = saturate(color.g + GetOption(F_BLOOM_GREENS) * bloom.g); 154 | bloom.b = saturate(color.b + GetOption(G_BLOOM_BLUES) * bloom.b); 155 | 156 | color = saturate(bloom); 157 | 158 | return color; 159 | } 160 | 161 | float4 PyramidFilter(float2 texcoord, float2 width) 162 | { 163 | float4 X = SampleLocation(texcoord + float2(0.5, 0.5) * width); 164 | float4 Y = SampleLocation(texcoord + float2(-0.5, 0.5) * width); 165 | float4 Z = SampleLocation(texcoord + float2(0.5, -0.5) * width); 166 | float4 W = SampleLocation(texcoord + float2(-0.5, -0.5) * width); 167 | 168 | return (X + Y + Z + W) / 4.0; 169 | } 170 | 171 | float3 Blend(float3 bloom, float3 blend) 172 | { 173 | if (GetOption(A_BLOOM_TYPE) == 0) { return BlendGlow(bloom, blend); } 174 | else if (GetOption(A_BLOOM_TYPE) == 1) { return BlendAddGlow(bloom, blend); } 175 | else if (GetOption(A_BLOOM_TYPE) == 2) { return BlendAddLight(bloom, blend); } 176 | else if (GetOption(A_BLOOM_TYPE) == 3) { return BlendScreen(bloom, blend); } 177 | else if (GetOption(A_BLOOM_TYPE) == 4) { return BlendLuma(bloom, blend); } 178 | else /*if (GetOption(A_BLOOM_TYPE) == 5) */ { return BlendOverlay(bloom, blend); } 179 | } 180 | 181 | void main() 182 | { 183 | float4 color = Sample(); 184 | float2 texcoord = GetCoordinates(); 185 | float2 pixelSize = GetInvResolution(); 186 | 187 | float anflare = 4.0; 188 | 189 | float2 defocus = float2(GetOption(D_B_DEFOCUS), GetOption(D_B_DEFOCUS)); 190 | float4 bloom = PyramidFilter(texcoord, pixelSize * defocus); 191 | 192 | float2 dx = float2(pixelSize.x * GetOption(D_BLOOM_WIDTH), 0.0); 193 | float2 dy = float2(0.0, pixelSize.y * GetOption(D_BLOOM_WIDTH)); 194 | 195 | float2 mdx = mul(dx, 2.0); 196 | float2 mdy = mul(dy, 2.0); 197 | 198 | float4 blend = bloom * 0.22520613262190495; 199 | 200 | blend += 0.002589001911021066 * SampleLocation(texcoord - mdx + mdy); 201 | blend += 0.010778807494659370 * SampleLocation(texcoord - dx + mdy); 202 | blend += 0.024146616900339800 * SampleLocation(texcoord + mdy); 203 | blend += 0.010778807494659370 * SampleLocation(texcoord + dx + mdy); 204 | blend += 0.002589001911021066 * SampleLocation(texcoord + mdx + mdy); 205 | 206 | blend += 0.010778807494659370 * SampleLocation(texcoord - mdx + dy); 207 | blend += 0.044875475183061630 * SampleLocation(texcoord - dx + dy); 208 | blend += 0.100529757860782610 * SampleLocation(texcoord + dy); 209 | blend += 0.044875475183061630 * SampleLocation(texcoord + dx + dy); 210 | blend += 0.010778807494659370 * SampleLocation(texcoord + mdx + dy); 211 | 212 | blend += 0.024146616900339800 * SampleLocation(texcoord - mdx); 213 | blend += 0.100529757860782610 * SampleLocation(texcoord - dx); 214 | blend += 0.100529757860782610 * SampleLocation(texcoord + dx); 215 | blend += 0.024146616900339800 * SampleLocation(texcoord + mdx); 216 | 217 | blend += 0.010778807494659370 * SampleLocation(texcoord - mdx - dy); 218 | blend += 0.044875475183061630 * SampleLocation(texcoord - dx - dy); 219 | blend += 0.100529757860782610 * SampleLocation(texcoord - dy); 220 | blend += 0.044875475183061630 * SampleLocation(texcoord + dx - dy); 221 | blend += 0.010778807494659370 * SampleLocation(texcoord + mdx - dy); 222 | 223 | blend += 0.002589001911021066 * SampleLocation(texcoord - mdx - mdy); 224 | blend += 0.010778807494659370 * SampleLocation(texcoord - dx - mdy); 225 | blend += 0.024146616900339800 * SampleLocation(texcoord - mdy); 226 | blend += 0.010778807494659370 * SampleLocation(texcoord + dx - mdy); 227 | blend += 0.002589001911021066 * SampleLocation(texcoord + mdx - mdy); 228 | blend = lerp(color, blend, GetOption(C_BLEND_STRENGTH)); 229 | 230 | bloom.xyz = Blend(bloom.xyz, blend.xyz); 231 | bloom.xyz = BloomCorrection(bloom.xyz); 232 | 233 | color.a = AvgLuminance(color.xyz); 234 | bloom.a = AvgLuminance(bloom.xyz); 235 | bloom.a *= anflare; 236 | 237 | SetOutput(lerp(color, bloom, GetOption(B_BLOOM_STRENGTH))); 238 | } 239 | -------------------------------------------------------------------------------- /reshade/Shaders/misc/geom.fx: -------------------------------------------------------------------------------- 1 | #include "ReShade.fxh" 2 | 3 | /* 4 | Geom Shader - a modified CRT-Geom without CRT features made to be appended/integrated 5 | into any other shaders and provide curvature/warping/oversampling features. 6 | 7 | Adapted by Hyllian (2024). 8 | */ 9 | 10 | 11 | /* 12 | CRT-interlaced 13 | 14 | Copyright (C) 2010-2012 cgwg, Themaister and DOLLS 15 | 16 | This program is free software; you can redistribute it and/or modify it 17 | under the terms of the GNU General Public License as published by the Free 18 | Software Foundation; either version 2 of the License, or (at your option) 19 | any later version. 20 | 21 | (cgwg gave their consent to have the original version of this shader 22 | distributed under the GPL in this message: 23 | 24 | http://board.byuu.org/viewtopic.php?p=26075#p26075 25 | 26 | "Feel free to distribute my shaders under the GPL. After all, the 27 | barrel distortion code was taken from the Curvature shader, which is 28 | under the GPL." 29 | ) 30 | This shader variant is pre-configured with screen curvature 31 | */ 32 | 33 | 34 | 35 | uniform bool geom_curvature < 36 | ui_type = "radio"; 37 | ui_label = "Geom Curvature Toggle"; 38 | > = 1.0; 39 | 40 | uniform float geom_R < 41 | ui_type = "drag"; 42 | ui_min = 0.1; 43 | ui_max = 10.0; 44 | ui_step = 0.1; 45 | ui_label = "Geom Curvature Radius"; 46 | > = 2.0; 47 | 48 | uniform float geom_d < 49 | ui_type = "drag"; 50 | ui_min = 0.1; 51 | ui_max = 3.0; 52 | ui_step = 0.1; 53 | ui_label = "Geom Distance"; 54 | > = 1.5; 55 | 56 | uniform bool geom_invert_aspect < 57 | ui_type = "radio"; 58 | ui_label = "Geom Curvature Aspect Inversion"; 59 | > = 0.0; 60 | 61 | uniform float geom_cornersize < 62 | ui_type = "drag"; 63 | ui_min = 0.001; 64 | ui_max = 1.0; 65 | ui_step = 0.005; 66 | ui_label = "Geom Corner Size"; 67 | > = 0.03; 68 | 69 | uniform float geom_cornersmooth < 70 | ui_type = "drag"; 71 | ui_min = 80.0; 72 | ui_max = 2000.0; 73 | ui_step = 100.0; 74 | ui_label = "Geom Corner Smoothness"; 75 | > = 1000.0; 76 | 77 | uniform float geom_x_tilt < 78 | ui_type = "drag"; 79 | ui_min = -1.0; 80 | ui_max = 1.0; 81 | ui_step = 0.05; 82 | ui_label = "Geom Horizontal Tilt"; 83 | > = 0.0; 84 | 85 | uniform float geom_y_tilt < 86 | ui_type = "drag"; 87 | ui_min = -1.0; 88 | ui_max = 1.0; 89 | ui_step = 0.05; 90 | ui_label = "Geom Vertical Tilt"; 91 | > = 0.0; 92 | 93 | uniform float geom_overscan_x < 94 | ui_type = "drag"; 95 | ui_min = -125.0; 96 | ui_max = 125.0; 97 | ui_step = 0.5; 98 | ui_label = "Geom Horiz. Overscan %"; 99 | > = 100.0; 100 | 101 | uniform float geom_overscan_y < 102 | ui_type = "drag"; 103 | ui_min = -125.0; 104 | ui_max = 125.0; 105 | ui_step = 0.5; 106 | ui_label = "Geom Vert. Overscan %"; 107 | > = 100.0; 108 | 109 | uniform float centerx < 110 | ui_type = "drag"; 111 | ui_min = -100.0; 112 | ui_max = 100.0; 113 | ui_step = 0.1; 114 | ui_label = "Image Center X"; 115 | > = 0.00; 116 | 117 | uniform float centery < 118 | ui_type = "drag"; 119 | ui_min = -100.0; 120 | ui_max = 100.0; 121 | ui_step = 0.1; 122 | ui_label = "Image Center Y"; 123 | > = 0.00; 124 | 125 | uniform float geom_lum < 126 | ui_type = "drag"; 127 | ui_min = 0.5; 128 | ui_max = 2.0; 129 | ui_step = 0.01; 130 | ui_label = "Geom Luminance"; 131 | > = 1.0; 132 | 133 | uniform float geom_target_gamma < 134 | ui_type = "drag"; 135 | ui_min = 0.1; 136 | ui_max = 5.0; 137 | ui_step = 0.1; 138 | ui_label = "Geom Target Gamma"; 139 | > = 2.4; 140 | 141 | uniform float geom_monitor_gamma < 142 | ui_type = "drag"; 143 | ui_min = 0.1; 144 | ui_max = 5.0; 145 | ui_step = 0.1; 146 | ui_label = "Geom Monitor Gamma"; 147 | > = 2.2; 148 | 149 | 150 | uniform float2 BufferToViewportRatio < source = "buffer_to_viewport_ratio"; >; 151 | uniform float2 NormalizedNativePixelSize < source = "normalized_native_pixel_size"; >; 152 | uniform float2 ViewportSize < source = "viewportsize"; >; 153 | uniform float ViewportWidth < source = "viewportwidth"; >; 154 | uniform float ViewportHeight < source = "viewportheight"; >; 155 | 156 | sampler2D sBackBuffer{Texture=ReShade::BackBufferTex;AddressU=BORDER;AddressV=BORDER;AddressW=BORDER;MagFilter=LINEAR;MinFilter=LINEAR;}; 157 | 158 | // Comment the next line to disable interpolation in linear gamma (and 159 | // gain speed). 160 | #define LINEAR_PROCESSING 161 | 162 | // Enable 3x oversampling of the beam profile; improves moire effect caused by scanlines+curvature 163 | #define OVERSAMPLE 164 | 165 | // Use the older, purely gaussian beam profile; uncomment for speed 166 | //#define USEGAUSSIAN 167 | 168 | // Macros. 169 | #define FIX(c) max(abs(c), 1e-5); 170 | #define PI 3.141592653589 171 | 172 | #ifdef LINEAR_PROCESSING 173 | # define TEX2D(c) pow(tex2D(sBackBuffer, (c)), geom_target_gamma.xxxx) 174 | #else 175 | # define TEX2D(c) tex2D(sBackBuffer, (c)) 176 | #endif 177 | 178 | // aspect ratio 179 | #define aspect (geom_invert_aspect==true?float2(ViewportHeight/ViewportWidth,1.0):float2(1.0,ViewportHeight/ViewportWidth)) 180 | #define overscan (1.01.xx); 181 | 182 | 183 | struct ST_VertexOut 184 | { 185 | float2 sinangle : TEXCOORD1; 186 | float2 cosangle : TEXCOORD2; 187 | float3 stretch : TEXCOORD3; 188 | float2 TextureSize : TEXCOORD4; 189 | }; 190 | 191 | 192 | float intersect(float2 xy, float2 sinangle, float2 cosangle) 193 | { 194 | float A = dot(xy,xy) + geom_d*geom_d; 195 | float B, C; 196 | 197 | B = 2.0*(geom_R*(dot(xy,sinangle) - geom_d*cosangle.x*cosangle.y) - geom_d*geom_d); 198 | C = geom_d*geom_d + 2.0*geom_R*geom_d*cosangle.x*cosangle.y; 199 | 200 | return (-B-sqrt(B*B - 4.0*A*C))/(2.0*A); 201 | } 202 | 203 | float2 bkwtrans(float2 xy, float2 sinangle, float2 cosangle) 204 | { 205 | float c = intersect(xy, sinangle, cosangle); 206 | float2 point = (c.xx*xy + geom_R.xx*sinangle) / geom_R.xx; 207 | float2 poc = point/cosangle; 208 | float2 tang = sinangle/cosangle; 209 | 210 | float A = dot(tang, tang) + 1.0; 211 | float B = -2.0*dot(poc, tang); 212 | float C = dot(poc, poc) - 1.0; 213 | 214 | float a = (-B + sqrt(B*B - 4.0*A*C)) / (2.0*A); 215 | float2 uv = (point - a*sinangle) / cosangle; 216 | float r = FIX(geom_R*acos(a)); 217 | 218 | return uv*r/sin(r/geom_R); 219 | } 220 | 221 | float2 fwtrans(float2 uv, float2 sinangle, float2 cosangle) 222 | { 223 | float r = FIX(sqrt(dot(uv, uv))); 224 | uv *= sin(r/geom_R)/r; 225 | float x = 1.0 - cos(r/geom_R); 226 | float D; 227 | 228 | D = geom_d/geom_R + x*cosangle.x*cosangle.y + dot(uv,sinangle); 229 | 230 | return geom_d*(uv*cosangle - x*sinangle)/D; 231 | } 232 | 233 | float3 maxscale(float2 sinangle, float2 cosangle) 234 | { 235 | float2 c = bkwtrans(-geom_R * sinangle / (1.0 + geom_R/geom_d*cosangle.x*cosangle.y), sinangle, cosangle); 236 | float2 a = 0.5.xx*aspect; 237 | 238 | float2 lo = float2(fwtrans(float2(-a.x, c.y), sinangle, cosangle).x, 239 | fwtrans(float2( c.x, -a.y), sinangle, cosangle).y)/aspect; 240 | float2 hi = float2(fwtrans(float2(+a.x, c.y), sinangle, cosangle).x, 241 | fwtrans(float2( c.x, +a.y), sinangle, cosangle).y)/aspect; 242 | 243 | return float3((hi+lo)*aspect*0.5,max(hi.x-lo.x, hi.y-lo.y)); 244 | } 245 | 246 | float2 transform(float2 coord, float2 sinangle, float2 cosangle, float3 stretch) 247 | { 248 | coord = (coord - 0.5.xx)*aspect*stretch.z + stretch.xy; 249 | 250 | return (bkwtrans(coord, sinangle, cosangle) / 251 | float2(geom_overscan_x / 100.0, geom_overscan_y / 100.0)/aspect + 0.5.xx); 252 | } 253 | 254 | 255 | // Vertex shader generating a triangle covering the entire screen 256 | void VS_CRT_Geom(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD, out ST_VertexOut vVARS) 257 | { 258 | texcoord.x = (id == 2) ? 2.0 : 0.0; 259 | texcoord.y = (id == 1) ? 2.0 : 0.0; 260 | position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 261 | 262 | // Screen centering 263 | texcoord = texcoord - float2(centerx,centery)/100.0; 264 | 265 | float2 SourceSize = 1.0/NormalizedNativePixelSize; 266 | 267 | // Precalculate a bunch of useful values we'll need in the fragment 268 | // shader. 269 | vVARS.sinangle = sin(float2(geom_x_tilt, geom_y_tilt)); 270 | vVARS.cosangle = cos(float2(geom_x_tilt, geom_y_tilt)); 271 | vVARS.stretch = maxscale(vVARS.sinangle, vVARS.cosangle); 272 | vVARS.TextureSize = float2(SourceSize.x, SourceSize.y); 273 | } 274 | 275 | 276 | float corner(float2 coord) 277 | { 278 | coord = min(coord, 1.0.xx - coord) * aspect; 279 | float2 cdist = geom_cornersize.xx; 280 | coord = (cdist - min(coord, cdist)); 281 | float dist = sqrt(dot(coord, coord)); 282 | 283 | return clamp((cdist.x - dist)*geom_cornersmooth, 0.0, 1.0); 284 | } 285 | 286 | float fwidth(float value) 287 | { 288 | return abs(ddx(value)) + abs(ddy(value)); 289 | } 290 | 291 | 292 | float4 PS_CRT_Geom(float4 vpos: SV_Position, float2 vTexCoord : TEXCOORD, in ST_VertexOut vVARS) : SV_Target 293 | { 294 | // Texture coordinates of the texel containing the active pixel. 295 | float2 xy = (geom_curvature == true) ? transform(vTexCoord, vVARS.sinangle, vVARS.cosangle, vVARS.stretch) : vTexCoord; 296 | 297 | float cval = corner((xy-0.5.xx) * BufferToViewportRatio + 0.5.xx); 298 | 299 | float2 uv_ratio = frac((xy * vVARS.TextureSize - 0.5.xx) / vVARS.TextureSize); 300 | 301 | float4 col = TEX2D(xy); 302 | 303 | #ifndef LINEAR_PROCESSING 304 | col = pow(col, geom_target_gamma.xxxx); 305 | #endif 306 | 307 | col.rgb *= (geom_lum * step(0.0, uv_ratio.y)); 308 | 309 | float3 mul_res = col.rgb * cval.xxx; 310 | 311 | // Convert the image gamma for display on our output device. 312 | mul_res = pow(mul_res, 1.0 / geom_monitor_gamma.xxx); 313 | 314 | return float4(mul_res, 1.0); 315 | } 316 | 317 | 318 | technique CRT_Geom 319 | { 320 | pass 321 | { 322 | VertexShader = VS_CRT_Geom; 323 | PixelShader = PS_CRT_Geom; 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /reshade/Shaders/crt-royale/shaders/geometry-aa-last-pass.fxh: -------------------------------------------------------------------------------- 1 | #ifndef _GEOMETRY_AA_LAST_PASS_H 2 | #define _GEOMETRY_AA_LAST_PASS_H 3 | 4 | ///////////////////////////// GPL LICENSE NOTICE ///////////////////////////// 5 | 6 | // crt-royale: A full-featured CRT shader, with cheese. 7 | // Copyright (C) 2014 TroggleMonkey 8 | // 9 | // crt-royale-reshade: A port of TroggleMonkey's crt-royale from libretro to ReShade. 10 | // Copyright (C) 2020 Alex Gunter 11 | // 12 | // This program is free software; you can redistribute it and/or modify it 13 | // under the terms of the GNU General Public License as published by the Free 14 | // Software Foundation; either version 2 of the License, or any later version. 15 | // 16 | // This program is distributed in the hope that it will be useful, but WITHOUT 17 | // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 18 | // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 19 | // more details. 20 | // 21 | // You should have received a copy of the GNU General Public License along with 22 | // this program; if not, write to the Free Software Foundation, Inc., 59 Temple 23 | // Place, Suite 330, Boston, MA 02111-1307 USA 24 | 25 | 26 | #include "../lib/user-settings.fxh" 27 | #include "../lib/derived-settings-and-constants.fxh" 28 | #include "../lib/bind-shader-params.fxh" 29 | #include "../lib/gamma-management.fxh" 30 | #include "../lib/tex2Dantialias.fxh" 31 | #include "../lib/geometry-functions.fxh" 32 | 33 | // Disabled in the ReShade port because I don't know a good way to make these 34 | // static AND global AND defined with sin(), cos(), or pow(). 35 | 36 | // #if !_RUNTIME_GEOMETRY_TILT 37 | // // Create a local-to-global rotation matrix for the CRT's coordinate frame 38 | // // and its global-to-local inverse. See the vertex shader for details. 39 | // // It's faster to compute these statically if possible. 40 | // static const float2 sin_tilt = sin(geom_tilt_angle_static); 41 | // static const float2 cos_tilt = cos(geom_tilt_angle_static); 42 | // static const float3x3 geom_local_to_global_static = float3x3( 43 | // cos_tilt.x, sin_tilt.y*sin_tilt.x, cos_tilt.y*sin_tilt.x, 44 | // 0.0, cos_tilt.y, -sin_tilt.y, 45 | // -sin_tilt.x, sin_tilt.y*cos_tilt.x, cos_tilt.y*cos_tilt.x); 46 | // static const float3x3 geom_global_to_local_static = float3x3( 47 | // cos_tilt.x, 0.0, -sin_tilt.x, 48 | // sin_tilt.y*sin_tilt.x, cos_tilt.y, sin_tilt.y*cos_tilt.x, 49 | // cos_tilt.y*sin_tilt.x, -sin_tilt.y, cos_tilt.y*cos_tilt.x); 50 | // #endif 51 | 52 | float2x2 mul_scale(float2 scale, float2x2 mtrx) 53 | { 54 | float4 temp_matrix = float4(mtrx[0][0], mtrx[0][1], mtrx[1][0], mtrx[1][1]) * scale.xxyy; 55 | return float2x2(temp_matrix.x, temp_matrix.y, temp_matrix.z, temp_matrix.w); 56 | } 57 | 58 | 59 | void geometryVS( 60 | in uint id : SV_VertexID, 61 | 62 | out float4 position : SV_Position, 63 | out float2 texcoord : TEXCOORD0, 64 | out float2 output_size_inv : TEXCOORD1, 65 | out float4 geom_aspect_and_overscan : TEXCOORD2, 66 | out float3 eye_pos_local : TEXCOORD3, 67 | out float3 global_to_local_row0 : TEXCOORD4, 68 | out float3 global_to_local_row1 : TEXCOORD5, 69 | out float3 global_to_local_row2 : TEXCOORD6 70 | ) { 71 | PostProcessVS(id, position, texcoord); 72 | 73 | output_size_inv = 1.0 / content_size; 74 | 75 | // Get aspect/overscan vectors from scalar parameters (likely uniforms): 76 | const float viewport_aspect_ratio = output_size_inv.y / output_size_inv.x; 77 | const float2 geom_aspect = get_aspect_vector(viewport_aspect_ratio); 78 | const float2 geom_overscan = get_geom_overscan_vector(); 79 | geom_aspect_and_overscan = float4(geom_aspect, geom_overscan); 80 | 81 | #if _RUNTIME_GEOMETRY_TILT 82 | // Create a local-to-global rotation matrix for the CRT's coordinate 83 | // frame and its global-to-local inverse. Rotate around the x axis 84 | // first (pitch) and then the y axis (yaw) with yucky Euler angles. 85 | // Positive angles go clockwise around the right-vec and up-vec. 86 | // Runtime shader parameters prevent us from computing these globally, 87 | // but we can still combine the pitch/yaw matrices by hand to cut a 88 | // few instructions. Note that cg matrices fill row1 first, then row2, 89 | // etc. (row-major order). 90 | const float2 geom_tilt_angle = get_geom_tilt_angle_vector(); 91 | const float2 sin_tilt = sin(geom_tilt_angle); 92 | const float2 cos_tilt = cos(geom_tilt_angle); 93 | // Conceptual breakdown: 94 | static const float3x3 rot_x_matrix = float3x3( 95 | 1.0, 0.0, 0.0, 96 | 0.0, cos_tilt.y, -sin_tilt.y, 97 | 0.0, sin_tilt.y, cos_tilt.y); 98 | static const float3x3 rot_y_matrix = float3x3( 99 | cos_tilt.x, 0.0, sin_tilt.x, 100 | 0.0, 1.0, 0.0, 101 | -sin_tilt.x, 0.0, cos_tilt.x); 102 | static const float3x3 local_to_global = 103 | mul(rot_y_matrix, rot_x_matrix); 104 | /* static const float3x3 global_to_local = 105 | transpose(local_to_global); 106 | const float3x3 local_to_global = float3x3( 107 | cos_tilt.x, sin_tilt.y*sin_tilt.x, cos_tilt.y*sin_tilt.x, 108 | 0.0, cos_tilt.y, sin_tilt.y, 109 | sin_tilt.x, sin_tilt.y*cos_tilt.x, cos_tilt.y*cos_tilt.x); 110 | */ // This is a pure rotation, so transpose = inverse: 111 | const float3x3 global_to_local = transpose(local_to_global); 112 | // Decompose the matrix into 3 float3's for output: 113 | global_to_local_row0 = float3(global_to_local[0][0], global_to_local[0][1], global_to_local[0][2]);//._m00_m01_m02); 114 | global_to_local_row1 = float3(global_to_local[1][0], global_to_local[1][1], global_to_local[1][2]);//._m10_m11_m12); 115 | global_to_local_row2 = float3(global_to_local[2][0], global_to_local[2][1], global_to_local[2][2]);//._m20_m21_m22); 116 | #else 117 | static const float3x3 global_to_local = geom_global_to_local_static; 118 | static const float3x3 local_to_global = geom_local_to_global_static; 119 | #endif 120 | 121 | // Get an optimal eye position based on geom_view_dist, viewport_aspect, 122 | // and CRT radius/rotation: 123 | #if _RUNTIME_GEOMETRY_MODE 124 | const float geom_mode = geom_mode_runtime; 125 | #else 126 | static const float geom_mode = geom_mode_static; 127 | #endif 128 | const float3 eye_pos_global = get_ideal_global_eye_pos(local_to_global, geom_aspect, geom_mode); 129 | eye_pos_local = mul(global_to_local, eye_pos_global); 130 | } 131 | 132 | void geometryPS( 133 | in float4 position : SV_Position, 134 | in float2 texcoord : TEXCOORD0, 135 | in float2 output_size_inv : TEXCOORD1, 136 | in float4 geom_aspect_and_overscan : TEXCOORD2, 137 | in float3 eye_pos_local : TEXCOORD3, 138 | in float3 global_to_local_row0 : TEXCOORD4, 139 | in float3 global_to_local_row1 : TEXCOORD5, 140 | in float3 global_to_local_row2 : TEXCOORD6, 141 | 142 | out float4 color : SV_Target 143 | ) { 144 | // Localize some parameters: 145 | const float2 geom_aspect = geom_aspect_and_overscan.xy; 146 | const float2 geom_overscan = geom_aspect_and_overscan.zw; 147 | #if _RUNTIME_GEOMETRY_TILT 148 | const float3x3 global_to_local = float3x3(global_to_local_row0, 149 | global_to_local_row1, global_to_local_row2); 150 | #else 151 | static const float3x3 global_to_local = geom_global_to_local_static; 152 | #endif 153 | #if _RUNTIME_GEOMETRY_MODE 154 | const float geom_mode = geom_mode_runtime; 155 | #else 156 | static const float geom_mode = geom_mode_static; 157 | #endif 158 | 159 | // Get flat and curved texture coords for the current fragment point sample 160 | // and a pixel_to_tangent_video_uv matrix for transforming pixel offsets: 161 | // video_uv = relative position in video frame, mapped to [0.0, 1.0] range 162 | // tex_uv = relative position in padded texture, mapped to [0.0, 1.0] range 163 | const float2 flat_video_uv = texcoord; 164 | float2x2 pixel_to_video_uv; 165 | float2 video_uv_no_geom_overscan; 166 | if(geom_mode > 0.5) 167 | { 168 | video_uv_no_geom_overscan = 169 | get_curved_video_uv_coords_and_tangent_matrix(flat_video_uv, 170 | eye_pos_local, output_size_inv, geom_aspect, 171 | geom_mode, global_to_local, pixel_to_video_uv); 172 | } 173 | else 174 | { 175 | video_uv_no_geom_overscan = flat_video_uv; 176 | pixel_to_video_uv = float2x2( 177 | output_size_inv.x, 0.0, 0.0, output_size_inv.y); 178 | } 179 | // Correct for overscan here (not in curvature code): 180 | const float2 video_uv = 181 | (video_uv_no_geom_overscan - float2(0.5, 0.5))/geom_overscan + float2(0.5, 0.5); 182 | const float2 tex_uv = video_uv; 183 | 184 | // Get a matrix transforming pixel vectors to tex_uv vectors: 185 | const float2x2 pixel_to_tex_uv = 186 | mul_scale(1.0 / geom_overscan, pixel_to_video_uv); 187 | 188 | // Sample! Skip antialiasing if antialias_level < 0.5 or both of these hold: 189 | // 1.) Geometry/curvature isn't used 190 | // 2.) Overscan == float2(1.0, 1.0) 191 | // Skipping AA is sharper, but it's only faster with dynamic branches. 192 | const float2 abs_aa_r_offset = abs(get_aa_subpixel_r_offset()); 193 | // this next check seems to always return true, even when it shouldn't so disabling it for now 194 | const bool need_subpixel_aa = false;//abs_aa_r_offset.x + abs_aa_r_offset.y > 0.0; 195 | float3 raw_color; 196 | 197 | if(antialias_level > 0.5 && (geom_mode > 0.5 || any(bool2((geom_overscan.x != 1.0), (geom_overscan.y != 1.0))))) 198 | { 199 | // Sample the input with antialiasing (due to sharp phosphors, etc.): 200 | raw_color = tex2Daa(samplerBloomHorizontal, tex_uv, pixel_to_tex_uv, float(frame_count), get_intermediate_gamma()); 201 | } 202 | else if(antialias_level > 0.5 && need_subpixel_aa) 203 | { 204 | // Sample at each subpixel location: 205 | raw_color = tex2Daa_subpixel_weights_only( 206 | samplerBloomHorizontal, tex_uv, pixel_to_tex_uv, get_intermediate_gamma()); 207 | } 208 | else 209 | { 210 | raw_color = tex2D_linearize(samplerBloomHorizontal, tex_uv, get_intermediate_gamma()).rgb; 211 | } 212 | 213 | // Dim borders and output the final result: 214 | const float border_dim_factor = get_border_dim_factor(video_uv, geom_aspect); 215 | const float3 final_color = raw_color * border_dim_factor; 216 | 217 | color = encode_output(float4(final_color, 1.0), get_output_gamma()); 218 | } 219 | 220 | #endif // _GEOMETRY_AA_LAST_PASS_H --------------------------------------------------------------------------------