├── LICENSE ├── README.md ├── Shaders ├── ASCII.fx ├── Border.fx ├── CAS.fx ├── CRT.fx ├── Cartoon.fx ├── ChromaticAberration.fx ├── ColorMatrix.fx ├── Curves.fx ├── DPX.fx ├── FXAA.fx ├── FXAA.fxh ├── FakeHDR.fx ├── FilmGrain.fx ├── Layer.fx ├── Levels.fx ├── LiftGammaGain.fx ├── LumaSharpen.fx ├── Monochrome.fx ├── Nostalgia.fx ├── SMAA.fx ├── SMAA.fxh ├── Sepia.fx ├── Splitscreen.fx ├── Technicolor.fx ├── Technicolor2.fx ├── Tonemap.fx ├── Vibrance.fx └── Vignette.fx └── Textures ├── AreaTex.png ├── Layer.png └── SearchTex.png /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 CeeJayDK 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 deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | 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 all 13 | 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 FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | .-. . .---.. . 3 | ( ) _|_ | \ / 4 | `-.. . ._.-. .-. | |--- / 5 | ( )\ \ / (.-' (.-' | | / \ 6 | `-' `' `' `--' `--'`-'' ' ' 7 | Shader Suite 8 | by CeeJay.dk 9 | 10 | 11 | ## Introduction 12 | 13 | SweetFX is a suite of effects for universal image improvement and tweaking. 14 | 15 | This is the Reshade based version. 16 | 17 | Previous SweetFX 1.x versions came bundled with InjectSMAA and used that to apply the shaders to the games. 18 | However SweetFX have been a part of Reshade ever since the first version of Reshade (and even before that when Crosire was working on EFX) 19 | 20 | Starting with Reshade 4.6 most shaders move out of the reshade-shader package and into their own, managed directly by the shader developers that created them. This means shaders can be released faster to the public because Crosire no longer needs to approve them and it frees up Crosires time to work on Reshade itself, rather than also having to manage the effect shaders it can run. 21 | 22 | I'm also hoping it will help people to realize that SweetFX never went away when we released Reshade but it became part of the included effects, as this is a common misunderstanding. 23 | 24 | Effects included: 25 | 26 | * SMAA Anti-aliasing : Anti-aliases the image using the SMAA technique - see http://www.iryoku.com/smaa/ 27 | * FXAA Anti-aliasing : Anti-aliases the image using the FXAA technique 28 | * Cartoon : Creates an outline-effect that makes the image look more cartoonish. 29 | * Advanced CRT : Mimics the look of an old arcade CRT display. 30 | * LumaSharpen : Sharpens the image, making details easier to see 31 | * HDR : Mimics an HDR tonemapped look 32 | * Levels : Sets a new black and white point. A fast and easy way to increase contrast but it causes clipping. The Curves effect does this in a more subtle way without causing clipping. 33 | * Technicolor : Makes the image look like it was processed using a three-strip Technicolor process - see http://en.wikipedia.org/wiki/Technicolor 34 | * DPX : Makes the image look like it was converted from film to Cineon DPX. Can be used to create a "sunny" look. 35 | * Monochrome : Removes colors from the image so it appears as if shot on black and white film. 36 | * Lift Gamma Gain : Adjust brightness and color of shadows, midtones and highlights (and typically does it better then the Tonemap effect) 37 | * Tonemap : Adjust gamma, exposure, saturation, bleach and defog. (may cause clipping) 38 | * Vibrance : Intelligently saturates (or desaturates if you use negative values) the pixels depending on their original saturation. 39 | * Curves : Contrast adjustments using S-curves - without causing clipping. 40 | * Sepia : Sepia tones the image - see http://en.wikipedia.org/wiki/Sepia_tone#Sepia_toning 41 | * Vignette : Darkens the edges of the image to make it look more like it was shot with a camera lens. - see http://en.wikipedia.org/wiki/Vignetting ) 42 | * Border : Makes the screenedge black as a workaround for the bright edge that forcing some AA modes sometimes causes or use it to create your own letterbox. 43 | * Layer : Allows you to overlay an image onto the game. 44 | * Nostalgia : Tries to mimic the look of very old computers or console systems. 45 | * AMD FidelityFX Contrast Adaptive Sharpening : Sharpens the image, making details easier to see. I've taken over the job of maintaining this Reshade port of AMDs sharpening effect, as it's popular with users and it's therefore best included in one of the popular shader suites. 46 | 47 | The following two effects are also created by me, but are found in the Reshade-shaders package as they are too crucial to Reshade not to include there. 48 | * DisplayDepth : A utility shader created to help you set up the depth buffer correctly in Reshade. 49 | * Splitscreen : Enables an before-and-after splitscreen comparison mode. 50 | 51 | ## Installation 52 | 53 | Either : 54 | A) Allow the Reshade installer to download SweetFX and install it for you. 55 | or 56 | B) Download SweetFX manually from https://github.com/CeeJayDK/SweetFX/archive/master.zip and extract it to the reshade-shaders folder that Reshade creates when you install it to a game directory. 57 | 58 | ## Usage 59 | 60 | Enable the SweetFX effects you want to use on the Home tab of Reshade. 61 | Then adjust the settings in the settings dialog that appears at the bottom of the Home tab. 62 | 63 | ## Presets 64 | 65 | Presets are files contain settings for the effects. 66 | People create their favorite looks for a particular game and then share these with others. 67 | 68 | You can find a lot of them in the SweetFX Settings Database (created and run by Terrasque) 69 | http://sfx.thelazy.net/games/ 70 | 71 | To work with Reshade they need to be made for Reshade and for a similar enough version of Reshade. 72 | 73 | But you can still make presets made for older versions or presets made for the SweetFX 1.x series work in recent Reshade versions, by manually copying the settings over. 74 | 75 | To do this: 76 | 1) Download the preset you want. 77 | 2) Look in the top section for effects with their ´USE_´ define set to 1 - These are the effect that have been enabled. 78 | 3) Enable these same effects in Reshade. 79 | 4) Scroll down to the settings of these effect in the preset and see what values they are set to. 80 | 5) Try to find the exact or similar setting in the effect settings in Reshade and give it the same value. 81 | 82 | Most settings still have the same name because I try not to modify the settings if I can avoid it - so they stay more compatible with older presets. 83 | 84 | ## Problems? 85 | 86 | Post issues with Reshade on the Reshade forum : 87 | https://reshade.me/forum 88 | 89 | Post suggestions and ideas for the (sweet) effects in SweetFX on the Reshade discord: 90 | https://discordapp.com/invite/GEb23bD as I'm often there. 91 | 92 | If I'm not there you can try the subreddit at : 93 | https://www.reddit.com/r/ReShade 94 | 95 | ## Uninstallation 96 | 97 | 1) Delete all the files you copied during the installation. 98 | 99 | ## Credits 100 | 101 | Runs on Reshade by Crosire 102 | 103 | Uses SMAA. Copyright (C) 2011 by Jorge Jimenez, Jose I. Echevarria, 104 | Belen Masia, Fernando Navarro and Diego Gutierrez. 105 | - More info on: http://www.iryoku.com/smaa/ 106 | 107 | Uses FXAA by Timothy Lottes (Nvidia) 108 | - His blog: http://timothylottes.blogspot.com 109 | 110 | Uses the HDR, Tonemap, Technicolor, Sepia and Vignette shaders from FXAATool by Violator, [some dude], fpedace, BeetleatWar1977 and [DKT70] 111 | - https://www.assembla.com/wiki/show/fxaa-pp-inject/ 112 | - All of these shaders have been modified by me (CeeJay.dk) .. some of them extensively. 113 | 114 | AMD FidelityFX Contrast Adaptive Sharpening by AMD 115 | - https://gpuopen.com/fidelityfx-cas/ 116 | 117 | DPX shader by Loadus 118 | 119 | Border shader by Oomek - rewritten, optimized and improved by CeeJay.dk 120 | 121 | Advanced CRT shader by cgwg, Themaister and DOLLS - ported to SweetFX by Boulotaur2024. 122 | 123 | Lift Gamma Gain shader by 3an and CeeJay.dk 124 | 125 | Cartoon by CeeJay.dk, but based on the Auto Toon cg shader found in the Dolphin emulator. 126 | - http://dolphin-emu.org/ 127 | 128 | SweetFX, LumaSharpen, Dither, Curves, Vibrance, Monochrome, Splitscreen, Explosion, Border, and Levels by Christian Cann Schuldt Jensen ( CeeJay.dk ) 129 | 130 | ## Contact 131 | 132 | Post comments, suggestions, support questions, screenshots, videos and presets on the Reshade forum at 133 | https://reshade.me/forum 134 | 135 | Or join the Reshade discord : 136 | https://discordapp.com/invite/GEb23bD 137 | 138 | Also check out the Reshade subreddit : 139 | https://www.reddit.com/r/ReShade/ 140 | 141 | Submit your presets to the SweetFX Settings Database at: 142 | http://sfx.thelazy.net/games/ 143 | -------------------------------------------------------------------------------- /Shaders/ASCII.fx: -------------------------------------------------------------------------------- 1 | /*------------------. 2 | | :: Description :: | 3 | '-------------------/ 4 | 5 | Ascii (Version 0.9) 6 | 7 | Author: CeeJay.dk 8 | License: MIT 9 | 10 | About: 11 | Converts the image to ASCII characters using a greyscale algoritm, 12 | cherrypicked characters and a custom bitmap font stored in a set of floats. 13 | 14 | It has 17 gray levels but uses dithering to greatly increase that number. 15 | 16 | Ideas for future improvement: 17 | * Cleanup code 18 | * Maybe find a better/faster pattern - possibly blur the pixels first with a 2 pass aproach 19 | * Try using a font atlas for more fonts or perhaps more performance 20 | * Try making an ordered dither rather than the random one. I think the random looks a bit too noisy. 21 | * Calculate luma from linear colorspace 22 | 23 | History: 24 | (*) Feature (+) Improvement (x) Bugfix (-) Information (!) Compatibility 25 | 26 | Version 0.7 by CeeJay.dk 27 | * Added the 3x5 font 28 | 29 | Version 0.8 by CeeJay.dk 30 | + Cleaned up settings UI for Reshade 3.x 31 | 32 | Version 0.9 by CeeJay.dk 33 | x Fixed an issue with the settings where the 3x5 could not be selected. 34 | - Cleaned up and commented the code. More cleanup is still needed. 35 | * Added the ability to toggle dithering on/off 36 | x Removed temporal dither code due to incompatibility with humans - it was giving me headaches and I didn't want to cause anyones seizure 37 | x Fixed an uneven distribution of the greyscale shades 38 | */ 39 | 40 | 41 | /*---------------. 42 | | :: Includes :: | 43 | '---------------*/ 44 | 45 | #include "ReShade.fxh" 46 | 47 | 48 | /*------------------. 49 | | :: UI Settings :: | 50 | '------------------*/ 51 | 52 | #include "ReShadeUI.fxh" 53 | 54 | /* 55 | uniform float Version < 56 | ui_label = "Version"; 57 | ui_min = 0.8; 58 | ui_max = 0.8; 59 | ui_step = 1.0; 60 | ui_category = "Author : CeeJay.dk\n\n" 61 | "To increase the size of the characters on screen simply lower your resolution in-game\n\n" 62 | "Try using this together with Nostagia. It also looks best if you first increase the contrast with Curves.\n\n"; 63 | > = float(0.8); 64 | */ 65 | 66 | uniform int Ascii_spacing < __UNIFORM_SLIDER_INT1 67 | ui_min = 0; 68 | ui_max = 5; 69 | ui_label = "Character Spacing"; 70 | ui_tooltip = "Determines the spacing between characters. I feel 1 to 3 looks best."; 71 | ui_category = "Font style"; 72 | > = 1; 73 | 74 | /* 75 | uniform int Ascii_font < 76 | ui_type = "drag"; 77 | ui_min = 1; 78 | ui_max = 2; 79 | ui_label = "Font Size"; 80 | ui_tooltip = "1 = 5x5 font, 2 = 3x5 font"; 81 | ui_category = "Font style"; 82 | > = 1; 83 | */ 84 | 85 | uniform int Ascii_font < 86 | ui_type = "combo"; 87 | ui_label = "Font Size"; 88 | ui_tooltip = "Choose font size"; 89 | ui_category = "Font style"; 90 | ui_items = 91 | "Smaller 3x5 font\0" 92 | "Normal 5x5 font\0" 93 | ; 94 | > = 1; 95 | 96 | 97 | uniform int Ascii_font_color_mode < __UNIFORM_SLIDER_INT1 98 | ui_min = 0; 99 | ui_max = 2; 100 | ui_label = "Font Color Mode"; 101 | ui_tooltip = "0 = Foreground color on background color, 1 = Colorized grayscale, 2 = Full color"; 102 | ui_category = "Color options"; 103 | > = 1; 104 | 105 | uniform float3 Ascii_font_color < __UNIFORM_COLOR_FLOAT3 106 | ui_label = "Font Color"; 107 | ui_tooltip = "Choose a font color"; 108 | ui_category = "Color options"; 109 | > = float3(1.0, 1.0, 1.0); 110 | 111 | uniform float3 Ascii_background_color < __UNIFORM_COLOR_FLOAT3 112 | ui_label = "Background Color"; 113 | ui_tooltip = "Choose a background color"; 114 | ui_category = "Color options"; 115 | > = float3(0.0, 0.0, 0.0); 116 | 117 | uniform bool Ascii_swap_colors < 118 | ui_label = "Swap Colors"; 119 | ui_tooltip = "Swaps the font and background color when you are too lazy to edit the settings above (I know I am)"; 120 | ui_category = "Color options"; 121 | > = 0; 122 | 123 | uniform bool Ascii_invert_brightness < 124 | ui_label = "Invert Brightness"; 125 | ui_category = "Color options"; 126 | > = 0; 127 | 128 | uniform bool Ascii_dithering < 129 | ui_label = "Dithering"; 130 | ui_category = "Dithering"; 131 | > = 1; 132 | 133 | uniform float Ascii_dithering_intensity < __UNIFORM_SLIDER_FLOAT1 134 | ui_min = 0.0; 135 | ui_max = 4.0; 136 | ui_label = "Dither shift intensity"; 137 | ui_tooltip = "For debugging purposes"; 138 | ui_category = "Debugging"; 139 | > = 2.0; 140 | 141 | uniform bool Ascii_dithering_debug_gradient < 142 | ui_label = "Dither debug gradient"; 143 | ui_category = "Debugging"; 144 | > = 0; 145 | 146 | /*-------------------------. 147 | | :: Sampler and timers :: | 148 | '-------------------------*/ 149 | 150 | #define asciiSampler ReShade::BackBuffer 151 | 152 | uniform float timer < source = "timer"; >; 153 | uniform float framecount < source = "framecount"; >; 154 | 155 | /*-------------. 156 | | :: Effect :: | 157 | '-------------*/ 158 | 159 | float3 AsciiPass( float2 tex ) 160 | { 161 | 162 | /*-------------------------. 163 | | :: Sample and average :: | 164 | '-------------------------*/ 165 | 166 | //if (Ascii_font != 1) 167 | float2 Ascii_font_size = float2(3.0,5.0); //3x5 168 | float num_of_chars = 14. ; 169 | 170 | if (Ascii_font == 1) 171 | { 172 | Ascii_font_size = float2(5.0,5.0); //5x5 173 | num_of_chars = 17.; 174 | } 175 | 176 | float quant = 1.0/(num_of_chars-1.0); //value used for quantization 177 | 178 | float2 Ascii_block = Ascii_font_size + float(Ascii_spacing); 179 | float2 cursor_position = trunc((BUFFER_SCREEN_SIZE / Ascii_block) * tex) * (Ascii_block / BUFFER_SCREEN_SIZE); 180 | 181 | 182 | //TODO Cleanup - and maybe find a better/faster pattern - possibly blur the pixels first with a 2 pass aproach 183 | //-- Pattern 2 - Sample ALL the pixels! -- 184 | float3 color = tex2D(asciiSampler, cursor_position + float2( 1.5, 1.5) * BUFFER_PIXEL_SIZE).rgb; 185 | color += tex2D(asciiSampler, cursor_position + float2( 1.5, 3.5) * BUFFER_PIXEL_SIZE).rgb; 186 | color += tex2D(asciiSampler, cursor_position + float2( 1.5, 5.5) * BUFFER_PIXEL_SIZE).rgb; 187 | //color += tex2D(asciiSampler, cursor_position + float2( 0.5, 6.5) * BUFFER_PIXEL_SIZE).rgb; 188 | color += tex2D(asciiSampler, cursor_position + float2( 3.5, 1.5) * BUFFER_PIXEL_SIZE).rgb; 189 | color += tex2D(asciiSampler, cursor_position + float2( 3.5, 3.5) * BUFFER_PIXEL_SIZE).rgb; 190 | color += tex2D(asciiSampler, cursor_position + float2( 3.5, 5.5) * BUFFER_PIXEL_SIZE).rgb; 191 | //color += tex2D(asciiSampler, cursor_position + float2( 2.5, 6.5) * BUFFER_PIXEL_SIZE).rgb; 192 | color += tex2D(asciiSampler, cursor_position + float2( 5.5, 1.5) * BUFFER_PIXEL_SIZE).rgb; 193 | color += tex2D(asciiSampler, cursor_position + float2( 5.5, 3.5) * BUFFER_PIXEL_SIZE).rgb; 194 | color += tex2D(asciiSampler, cursor_position + float2( 5.5, 5.5) * BUFFER_PIXEL_SIZE).rgb; 195 | //color += tex2D(asciiSampler, cursor_position + float2( 4.5, 6.5) * BUFFER_PIXEL_SIZE).rgb; 196 | //color += tex2D(asciiSampler, cursor_position + float2( 6.5, 0.5) * BUFFER_PIXEL_SIZE).rgb; 197 | //color += tex2D(asciiSampler, cursor_position + float2( 6.5, 2.5) * BUFFER_PIXEL_SIZE).rgb; 198 | //color += tex2D(asciiSampler, cursor_position + float2( 6.5, 4.5) * BUFFER_PIXEL_SIZE).rgb; 199 | //color += tex2D(asciiSampler, cursor_position + float2( 6.5, 6.5) * BUFFER_PIXEL_SIZE).rgb; 200 | 201 | color /= 9.0; 202 | 203 | /* 204 | //-- Pattern 3 - Just one -- 205 | float3 color = tex2D(asciiSampler, cursor_position + float2(4.0,4.0) * BUFFER_PIXEL_SIZE) .rgb; //this may be fast but it's not very temporally stable 206 | */ 207 | 208 | /*------------------------. 209 | | :: Make it grayscale :: | 210 | '------------------------*/ 211 | 212 | float luma = dot(color,float3(0.2126, 0.7152, 0.0722)); 213 | 214 | float gray = luma; 215 | 216 | if (Ascii_invert_brightness) 217 | gray = 1.0 - gray; 218 | 219 | 220 | /*----------------. 221 | | :: Debugging :: | 222 | '----------------*/ 223 | 224 | if (Ascii_dithering_debug_gradient) 225 | { 226 | //gray = sqrt(dot(float2((cursor_position.x - 0.5)*1.778,cursor_position.y - 0.5),float2((cursor_position.x - 0.5)*1.778,cursor_position.y - 0.5))) * 1.1; 227 | //gray = (cursor_position.x + cursor_position.y) * 0.5; //diagonal test gradient 228 | //gray = smoothstep(0.0,1.0,gray); //increase contrast 229 | gray = cursor_position.x; //horizontal test gradient 230 | //gray = cursor_position.y; //vertical test gradient 231 | } 232 | /*-------------------. 233 | | :: Get position :: | 234 | '-------------------*/ 235 | 236 | float2 p = frac((BUFFER_SCREEN_SIZE / Ascii_block) * tex); //p is the position of the current pixel inside the character 237 | 238 | p = trunc(p * Ascii_block); 239 | //p = trunc(p * Ascii_block - float2(1.5,1.5)) ; 240 | 241 | float x = (Ascii_font_size.x * p.y + p.x); //x is the number of the position in the bitfield 242 | 243 | /*----------------. 244 | | :: Dithering :: | 245 | '----------------*/ 246 | 247 | //TODO : Try make an ordered dither rather than the random dither. Random looks a bit too noisy for my taste. 248 | 249 | if (Ascii_dithering != 0) 250 | { 251 | //Pseudo Random Number Generator 252 | // -- PRNG 1 - Reference -- 253 | float seed = dot(cursor_position, float2(12.9898,78.233)); //I could add more salt here if I wanted to 254 | float sine = sin(seed); //cos also works well. Sincos too if you want 2D noise. 255 | float noise = frac(sine * 43758.5453 + cursor_position.y); 256 | 257 | float dither_shift = (quant * Ascii_dithering_intensity); // Using noise to determine shift. 258 | 259 | float dither_shift_half = (dither_shift * 0.5); // The noise should vary between +- 0.5 260 | dither_shift = dither_shift * noise - dither_shift_half; // MAD 261 | 262 | //shift the color by dither_shift 263 | gray += dither_shift; //apply dithering 264 | } 265 | 266 | /*---------------------------. 267 | | :: Convert to character :: | 268 | '---------------------------*/ 269 | 270 | float n = 0; 271 | 272 | if (Ascii_font == 1) 273 | { 274 | // -- 5x5 bitmap font by CeeJay.dk -- 275 | // .:^"~cvo*wSO8Q0# 276 | 277 | //17 characters including space which is handled as a special case 278 | 279 | //The serial aproach to this would take 16 cycles, so I instead used an upside down binary tree to parallelize this to only 5 cycles 280 | 281 | float n12 = (gray < (2. * quant)) ? 4194304. : 131200. ; // . or : 282 | float n34 = (gray < (4. * quant)) ? 324. : 330. ; // ^ or " 283 | float n56 = (gray < (6. * quant)) ? 283712. : 12650880.; // ~ or c 284 | float n78 = (gray < (8. * quant)) ? 4532768. : 13191552.; // v or o 285 | float n910 = (gray < (10. * quant)) ? 10648704. : 11195936.; // * or w 286 | float n1112 = (gray < (12. * quant)) ? 15218734. : 15255086.; // S or O 287 | float n1314 = (gray < (14. * quant)) ? 15252014. : 32294446.; // 8 or Q 288 | float n1516 = (gray < (16. * quant)) ? 15324974. : 11512810.; // 0 or # 289 | 290 | float n1234 = (gray < (3. * quant)) ? n12 : n34; 291 | float n5678 = (gray < (7. * quant)) ? n56 : n78; 292 | float n9101112 = (gray < (11. * quant)) ? n910 : n1112; 293 | float n13141516 = (gray < (15. * quant)) ? n1314 : n1516; 294 | 295 | float n12345678 = (gray < (5. * quant)) ? n1234 : n5678; 296 | float n910111213141516 = (gray < (13. * quant)) ? n9101112 : n13141516; 297 | 298 | n = (gray < (9. * quant)) ? n12345678 : n910111213141516; 299 | } 300 | else // Ascii_font == 0 , the 3x5 font 301 | { 302 | // -- 3x5 bitmap font by CeeJay.dk -- 303 | // .:;s*oSOXH0 304 | 305 | //14 characters including space which is handled as a special case 306 | 307 | /* Font reference : 308 | 309 | //The plusses are "likes". I was rating how much I liked that character over other alternatives. 310 | 311 | 3 ^ 42. 312 | 3 - 448. 313 | 3 i (short) 9232. 314 | 3 ; 5136. ++ 315 | 4 " 45. 316 | 4 i 9346. 317 | 4 s 5200. ++ 318 | 5 + 1488. 319 | 5 * 2728. ++ 320 | 6 c 25200. 321 | 6 o 11088. ++ 322 | 7 v 11112. 323 | 7 S 14478. ++ 324 | 8 O 11114. ++ 325 | 9 F 5071. 326 | 9 5 (rounded) 14543. 327 | 9 X 23213. ++ 328 | 10 A 23530. 329 | 10 D 15211. + 330 | 11 H 23533. + 331 | 11 5 (square) 31183. 332 | 11 2 (square) 29671. ++ 333 | 334 | 5 (rounded) 14543. 335 | */ 336 | 337 | float n12 = (gray < (2. * quant)) ? 4096. : 1040. ; // . or : 338 | float n34 = (gray < (4. * quant)) ? 5136. : 5200. ; // ; or s 339 | float n56 = (gray < (6. * quant)) ? 2728. : 11088.; // * or o 340 | float n78 = (gray < (8. * quant)) ? 14478. : 11114.; // S or O 341 | float n910 = (gray < (10. * quant)) ? 23213. : 15211.; // X or D 342 | float n1112 = (gray < (12. * quant)) ? 23533. : 31599.; // H or 0 343 | float n13 = 31727.; // 8 344 | 345 | float n1234 = (gray < (3. * quant)) ? n12 : n34; 346 | float n5678 = (gray < (7. * quant)) ? n56 : n78; 347 | float n9101112 = (gray < (11. * quant)) ? n910 : n1112; 348 | 349 | float n12345678 = (gray < (5. * quant)) ? n1234 : n5678; 350 | float n910111213 = (gray < (13. * quant)) ? n9101112 : n13; 351 | 352 | n = (gray < (9. * quant)) ? n12345678 : n910111213; 353 | } 354 | 355 | 356 | /*--------------------------------. 357 | | :: Decode character bitfield :: | 358 | '--------------------------------*/ 359 | 360 | float character = 0.0; 361 | 362 | //Test values 363 | //n = -(exp2(24.)-1.0); //-(2^24-1) All bits set - a white 5x5 box 364 | 365 | float lit = (gray <= (1. * quant)) //If black then set all pixels to black (the space character) 366 | ? 0.0 //That way I don't have to use a character bitfield for space 367 | : 1.0 ; //I simply let it to decode to the second darkest "." and turn its pixels off 368 | 369 | float signbit = (n < 0.0) //is n negative? (I would like to test for negative 0 here too but can't) 370 | ? lit 371 | : 0.0 ; 372 | 373 | signbit = (x > 23.5) //is this the first pixel in the character? 374 | ? signbit //if so set to the signbit (which may be on or off depending on if the number was negative) 375 | : 0.0 ; //else make it black 376 | 377 | //Tenary Multiply exp2 378 | character = ( frac( abs( n*exp2(-x-1.0))) >= 0.5) ? lit : signbit; //If the bit for the right position is set, then light up the pixel 379 | //UNLESS gray was dark enough, then keep the pixel dark to make a space 380 | //If the bit for the right position was not set, then turn off the pixel 381 | //UNLESS it's the first pixel in the character AND n is negative - if so light up the pixel. 382 | //This way I can use all 24 bits in the mantissa as well as the signbit for characters. 383 | 384 | if (clamp(p.x, 0.0, Ascii_font_size.x - 1.0) != p.x || clamp(p.y, 0.0, Ascii_font_size.y - 1.0) != p.y) //Is this the space around the character? 385 | character = 0.0; //If so make the pixel black. 386 | 387 | 388 | /*---------------. 389 | | :: Colorize :: | 390 | '---------------*/ 391 | 392 | if (Ascii_swap_colors) 393 | { 394 | if (Ascii_font_color_mode == 2) 395 | { 396 | color = (character) ? character * color : Ascii_font_color; 397 | } 398 | else if (Ascii_font_color_mode == 1) 399 | { 400 | color = (character) ? Ascii_background_color * gray : Ascii_font_color; 401 | } 402 | else // Ascii_font_color_mode == 0 403 | { 404 | color = (character) ? Ascii_background_color : Ascii_font_color; 405 | } 406 | } 407 | else 408 | { 409 | if (Ascii_font_color_mode == 2) 410 | { 411 | color = (character) ? character * color : Ascii_background_color; 412 | } 413 | else if (Ascii_font_color_mode == 1) 414 | { 415 | color = (character) ? Ascii_font_color * gray : Ascii_background_color; 416 | } 417 | else // Ascii_font_color_mode == 0 418 | { 419 | color = (character) ? Ascii_font_color : Ascii_background_color; 420 | } 421 | } 422 | 423 | /*-------------. 424 | | :: Return :: | 425 | '-------------*/ 426 | 427 | //color = gray; 428 | return saturate(color); 429 | } 430 | 431 | 432 | float3 PS_Ascii(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target 433 | { 434 | float3 color = AsciiPass(texcoord); 435 | return color.rgb; 436 | } 437 | 438 | 439 | technique ASCII 440 | { 441 | pass ASCII 442 | { 443 | VertexShader=PostProcessVS; 444 | PixelShader=PS_Ascii; 445 | } 446 | } 447 | 448 | 449 | /* 450 | .---------------------. 451 | | :: Character set :: | 452 | '---------------------' 453 | 454 | Here are some various chacters and gradients I created in my quest to get the best look 455 | 456 | .'~:;!>+=icjtJY56SXDQKHNWM 457 | .':!+ijY6XbKHNM 458 | .:%oO$8@#M 459 | .:+j6bHM 460 | .:coCO8@ 461 | .:oO8@ 462 | .:oO8 463 | :+# 464 | 465 | .:^"~cso*wSO8Q0# 466 | .:^"~csoCwSO8Q0# 467 | .:^"~c?o*wSO8Q0# 468 | 469 | n value // # of pixels // character 470 | ------------//----//------------------- 471 | 4194304. // 1 // . (bottom aligned) * 472 | 131200. // 2 // : (middle aligned) * 473 | 4198400. // 2 // : (bottom aligned) 474 | 132. // 2 // ' 475 | 2228352. // 3 // ; 476 | 4325504. // 3 // i (short) 477 | 14336. // 3 // - (small) 478 | 324. // 3 // ^ 479 | 4329476. // 4 // i (tall) 480 | 330. // 4 // " 481 | 31744. // 5 // - (larger) 482 | 283712. // 5 // ~ 483 | 10627072. // 5 // x 484 | 145536. // 5 // * or + (small and centered) 485 | 6325440. // 6 // c (narrow - left aligned) 486 | 12650880. // 6 // c (narrow - center aligned) 487 | 9738240. // 6 // n (left aligned) 488 | 6557772. // 7 // s (tall) 489 | 8679696. // 7 // f 490 | 4532768. // 7 // v (1st) 491 | 4539936. // 7 // v (2nd) 492 | 4207118. // 7 // ? 493 | -17895696. // 7 // % 494 | 6557958. // 7 // 3 495 | 6595776. // 8 // o (left aligned) 496 | 13191552. // 8 // o (right aligned) 497 | 14714304. // 8 // c (wide) 498 | 12806528. // 9 // e (right aligned) 499 | 332772. // 9 // * (top aligned) 500 | 10648704. // 9 // * (bottom aligned) 501 | 4357252. // 9 // + 502 | -18157904. // 9 // X 503 | 11195936. // 10 // w 504 | 483548. // 10 // s (thick) 505 | 15218734. // 11 // S 506 | 31491134. // 11 // C 507 | 15238702. // 11 // C (rounded) 508 | 22730410. // 11 // M (more like a large m) 509 | 10648714. // 11 // * (larger) 510 | 4897444. // 11 // * (2nd larger) 511 | 14726438. // 11 // @ (also looks like a large e) 512 | 23385164. // 11 // & 513 | 15255086. // 12 // O 514 | 16267326. // 13 // S (slightly larger) 515 | 15252014. // 13 // 8 516 | 15259182. // 13 // 0 (O with dot in the middle) 517 | 15517230. // 13 // Q (1st) 518 | -18405232. // 13 // M 519 | -11196080. // 13 // W 520 | 32294446. // 14 // Q (2nd) 521 | 15521326. // 14 // Q (3rd) 522 | 32298542. // 15 // Q (4th) 523 | 15324974. // 15 // 0 or Ø 524 | 16398526. // 15 // $ 525 | 11512810. // 16 // # 526 | -33061950. // 17 // 5 or S (stylized) 527 | -33193150. // 19 // $ (stylized) 528 | -33150782. // 19 // 0 (stylized) 529 | 530 | */ 531 | -------------------------------------------------------------------------------- /Shaders/Border.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * Border version 1.4.1 3 | * 4 | * -- Version 1.0 by Oomek -- 5 | * Fixes light, one pixel thick border in some games when forcing MSAA like i.e. Dishonored 6 | * -- Version 1.1 by CeeJay.dk -- 7 | * Optimized the shader. It still does the same but now it runs faster. 8 | * -- Version 1.2 by CeeJay.dk -- 9 | * Added border_width and border_color features 10 | * -- Version 1.3 by CeeJay.dk -- 11 | * Optimized the performance further 12 | * -- Version 1.4 by CeeJay.dk -- 13 | * Added the border_ratio feature 14 | * -- Version 1.4.1 by CeeJay.dk -- 15 | * Cleaned up setting for Reshade 3.x 16 | */ 17 | 18 | #include "ReShade.fxh" 19 | #include "ReShadeUI.fxh" 20 | 21 | /* 22 | uniform float2 border_width < 23 | ui_type = "input"; 24 | ui_label = "Size"; 25 | ui_tooltip = "Measured in pixels. If this is set to zero then the ratio will be used instead."; 26 | > = float2(0.0, 0.0); 27 | */ 28 | 29 | uniform float2 border_width < 30 | ui_type = "drag"; 31 | ui_label = "Size"; 32 | ui_tooltip = "Measured in pixels. If this is set to zero then the ratio will be used instead."; 33 | ui_min = 0.0; ui_max = (BUFFER_WIDTH * 0.5); 34 | ui_step = 1.0; 35 | > = float2(0.0, 0.0); 36 | 37 | uniform float border_ratio < 38 | ui_type = "input"; 39 | ui_label = "Size Ratio"; 40 | ui_tooltip = "Set the desired ratio for the visible area."; 41 | > = 2.35; 42 | 43 | uniform float3 border_color < 44 | ui_type = "color"; 45 | ui_label = "Border Color"; 46 | > = float3(0.0, 0.0, 0.0); 47 | 48 | float3 BorderPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 49 | { 50 | float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb; 51 | 52 | // -- calculate the right border_width for a given border_ratio -- 53 | float2 border_width_variable = border_width; 54 | if (border_width.x == -border_width.y) // If width is not used 55 | if (BUFFER_ASPECT_RATIO < border_ratio) 56 | border_width_variable = float2(0.0, (BUFFER_HEIGHT - (BUFFER_WIDTH / border_ratio)) * 0.5); 57 | else 58 | border_width_variable = float2((BUFFER_WIDTH - (BUFFER_HEIGHT * border_ratio)) * 0.5, 0.0); 59 | 60 | float2 border = (BUFFER_PIXEL_SIZE * border_width_variable); // Translate integer pixel width to floating point 61 | float2 within_border = saturate((-texcoord * texcoord + texcoord) - (-border * border + border)); // Becomes positive when inside the border and zero when outside 62 | 63 | return all(within_border) ? color : border_color; 64 | } 65 | 66 | technique Border 67 | { 68 | pass 69 | { 70 | VertexShader = PostProcessVS; 71 | PixelShader = BorderPass; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Shaders/CAS.fx: -------------------------------------------------------------------------------- 1 | // LICENSE 2 | // ======= 3 | // Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All rights reserved. 4 | // ------- 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 6 | // files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 7 | // modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 8 | // Software is furnished to do so, subject to the following conditions: 9 | // ------- 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the 11 | // Software. 12 | // ------- 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 14 | // WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 16 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE 17 | 18 | //Initial port to ReShade: SLSNe https://gist.github.com/SLSNe/bbaf2d77db0b2a2a0755df581b3cf00c 19 | 20 | //Optimizations by Marty McFly: 21 | // vectorized math, even with scalar gcn hardware this should work 22 | // out the same, order of operations has not changed 23 | // For some reason, it went from 64 to 48 instructions, a lot of MOV gone 24 | // Also modified the way the final window is calculated 25 | // 26 | // reordered min() and max() operations, from 11 down to 9 registers 27 | // 28 | // restructured final weighting, 49 -> 48 instructions 29 | // 30 | // delayed RCP to replace SQRT with RSQRT 31 | // 32 | // removed the saturate() from the control var as it is clamped 33 | // by UI manager already, 48 -> 47 instructions 34 | // 35 | // replaced tex2D with tex2Doffset intrinsic (address offset by immediate integer) 36 | // 47 -> 43 instructions 37 | // 9 -> 8 registers 38 | 39 | //Further modified by OopyDoopy and Lord of Lunacy: 40 | // Changed wording in the UI for the existing variable and added a new variable and relevant code to adjust sharpening strength. 41 | 42 | //Fix by Lord of Lunacy: 43 | // Made the shader use a linear colorspace rather than sRGB, as recommended by the original AMD documentation from FidelityFX. 44 | 45 | //Modified by CeeJay.dk: 46 | // Included a label and tooltip description. I followed AMDs official naming guidelines for FidelityFX. 47 | // 48 | // Used gather trick to reduce the number of texture operations by one (9 -> 8). It's now 42 -> 51 instructions but still faster 49 | // because of the texture operation that was optimized away. 50 | 51 | //Fix by CeeJay.dk 52 | // Fixed precision issues with the gather at super high resolutions 53 | // Also tried to refactor the samples so more work can be done while they are being sampled, but it's not so easy and the gains 54 | // I'm seeing are so small they might be statistical noise. So it MIGHT be faster - no promises. 55 | 56 | //Fix by CeeJay.dk 57 | // Gather optimization is only faster on DX11 and up - Not DX10 and up. Correcting this so DX10 does not use the Gather codepath 58 | 59 | uniform float Contrast < 60 | ui_type = "drag"; 61 | ui_label = "Contrast Adaptation"; 62 | ui_tooltip = "Adjusts the range the shader adapts to high contrast (0 is not all the way off). Higher values = more high contrast sharpening."; 63 | ui_min = 0.0; ui_max = 1.0; 64 | > = 0.0; 65 | 66 | uniform float Sharpening < 67 | ui_type = "drag"; 68 | ui_label = "Sharpening intensity"; 69 | ui_tooltip = "Adjusts sharpening intensity by averaging the original pixels to the sharpened result. 1.0 is the unmodified default."; 70 | ui_min = 0.0; ui_max = 1.0; 71 | > = 1.0; 72 | 73 | #include "ReShade.fxh" 74 | #define pixel float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT) 75 | 76 | texture TexColor : COLOR; 77 | sampler sTexColor {Texture = TexColor; SRGBTexture = true;}; 78 | 79 | float3 CASPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 80 | { 81 | // fetch a 3x3 neighborhood around the pixel 'e', 82 | // a b c 83 | // d(e)f 84 | // g h i 85 | 86 | 87 | float3 b = tex2Doffset(sTexColor, texcoord, int2(0, -1)).rgb; 88 | float3 d = tex2Doffset(sTexColor, texcoord, int2(-1, 0)).rgb; 89 | 90 | 91 | #if __RENDERER__ >= 0xb000 // If DX11 or higher 92 | float4 red_efhi = tex2DgatherR(sTexColor, texcoord + 0.5 * pixel); 93 | 94 | float3 e = float3( red_efhi.w, red_efhi.w, red_efhi.w); 95 | float3 f = float3( red_efhi.z, red_efhi.z, red_efhi.z); 96 | float3 h = float3( red_efhi.x, red_efhi.x, red_efhi.x); 97 | float3 i = float3( red_efhi.y, red_efhi.y, red_efhi.y); 98 | 99 | float4 green_efhi = tex2DgatherG(sTexColor, texcoord + 0.5 * pixel); 100 | 101 | e.g = green_efhi.w; 102 | f.g = green_efhi.z; 103 | h.g = green_efhi.x; 104 | i.g = green_efhi.y; 105 | 106 | float4 blue_efhi = tex2DgatherB(sTexColor, texcoord + 0.5 * pixel); 107 | 108 | e.b = blue_efhi.w; 109 | f.b = blue_efhi.z; 110 | h.b = blue_efhi.x; 111 | i.b = blue_efhi.y; 112 | 113 | 114 | #else // If DX9 115 | float3 e = tex2D(sTexColor, texcoord).rgb; 116 | float3 f = tex2Doffset(sTexColor, texcoord, int2(1, 0)).rgb; 117 | 118 | float3 h = tex2Doffset(sTexColor, texcoord, int2(0, 1)).rgb; 119 | float3 i = tex2Doffset(sTexColor, texcoord, int2(1, 1)).rgb; 120 | 121 | #endif 122 | 123 | float3 g = tex2Doffset(sTexColor, texcoord, int2(-1, 1)).rgb; 124 | float3 a = tex2Doffset(sTexColor, texcoord, int2(-1, -1)).rgb; 125 | float3 c = tex2Doffset(sTexColor, texcoord, int2(1, -1)).rgb; 126 | 127 | 128 | // Soft min and max. 129 | // a b c b 130 | // d e f * 0.5 + d e f * 0.5 131 | // g h i h 132 | // These are 2.0x bigger (factored out the extra multiply). 133 | float3 mnRGB = min(min(min(d, e), min(f, b)), h); 134 | float3 mnRGB2 = min(mnRGB, min(min(a, c), min(g, i))); 135 | mnRGB += mnRGB2; 136 | 137 | float3 mxRGB = max(max(max(d, e), max(f, b)), h); 138 | float3 mxRGB2 = max(mxRGB, max(max(a, c), max(g, i))); 139 | mxRGB += mxRGB2; 140 | 141 | // Smooth minimum distance to signal limit divided by smooth max. 142 | float3 rcpMRGB = rcp(mxRGB); 143 | float3 ampRGB = saturate(min(mnRGB, 2.0 - mxRGB) * rcpMRGB); 144 | 145 | // Shaping amount of sharpening. 146 | ampRGB = rsqrt(ampRGB); 147 | 148 | float peak = -3.0 * Contrast + 8.0; 149 | float3 wRGB = -rcp(ampRGB * peak); 150 | 151 | float3 rcpWeightRGB = rcp(4.0 * wRGB + 1.0); 152 | 153 | // 0 w 0 154 | // Filter shape: w 1 w 155 | // 0 w 0 156 | float3 window = (b + d) + (f + h); 157 | float3 outColor = saturate((window * wRGB + e) * rcpWeightRGB); 158 | 159 | return lerp(e, outColor, Sharpening); 160 | } 161 | 162 | technique ContrastAdaptiveSharpen 163 | < 164 | ui_label = "AMD FidelityFX Contrast Adaptive Sharpening"; 165 | ui_tooltip = 166 | "CAS is a low overhead adaptive sharpening algorithm that AMD includes with their drivers.\n" 167 | "This port to Reshade works with all cards from all vendors,\n" 168 | "but cannot do the optional scaling that CAS is normally also capable of when activated in the AMD drivers.\n" 169 | "\n" 170 | "The algorithm adjusts the amount of sharpening per pixel to target an even level of sharpness across the image.\n" 171 | "Areas of the input image that are already sharp are sharpened less, while areas that lack detail are sharpened more.\n" 172 | "This allows for higher overall natural visual sharpness with fewer artifacts."; 173 | > 174 | { 175 | pass 176 | { 177 | VertexShader = PostProcessVS; 178 | PixelShader = CASPass; 179 | SRGBWriteEnable = true; 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /Shaders/CRT.fx: -------------------------------------------------------------------------------- 1 | // CRT shader 2 | // 3 | // Copyright (C) 2010-2012 cgwg, Themaister and DOLLS 4 | // 5 | // This program is free software; you can redistribute it and/or modify it 6 | // under the terms of the GNU General Public License as published by the Free 7 | // Software Foundation; either version 2 of the License, or (at your option) 8 | // any later version. 9 | 10 | // Comment the next line to disable interpolation in linear gamma (and gain speed). 11 | //#define LINEAR_PROCESSING 12 | 13 | #include "ReShadeUI.fxh" 14 | 15 | uniform float Amount < __UNIFORM_SLIDER_FLOAT1 16 | ui_min = 0.0; ui_max = 1.0; 17 | ui_tooltip = "Amount of CRT effect you want"; 18 | > = 1.00; 19 | uniform float Resolution < __UNIFORM_SLIDER_FLOAT1 20 | ui_min = 1.0; ui_max = 8.0; 21 | ui_tooltip = "Input size coefficient (low values gives the 'low - res retro look')."; 22 | > = 1.15; 23 | uniform float Gamma < __UNIFORM_SLIDER_FLOAT1 24 | ui_min = 0.0; ui_max = 4.0; 25 | ui_tooltip = "Gamma of simulated CRT"; 26 | > = 2.4; 27 | uniform float MonitorGamma < __UNIFORM_SLIDER_FLOAT1 28 | ui_min = 0.0; ui_max = 4.0; 29 | ui_tooltip = "Gamma of display monitor"; 30 | > = 2.2; 31 | uniform float Brightness < __UNIFORM_SLIDER_FLOAT1 32 | ui_min = 0.0; ui_max = 3.0; 33 | ui_tooltip = "Used to boost brightness a little."; 34 | > = 0.9; 35 | 36 | uniform int ScanlineIntensity < __UNIFORM_SLIDER_INT1 37 | ui_min = 2; ui_max = 4; 38 | ui_label = "Scanline Intensity"; 39 | > = 2; 40 | uniform bool ScanlineGaussian < 41 | ui_label = "Scanline Bloom Effect"; 42 | ui_tooltip = "Use the new nongaussian scanlines bloom effect."; 43 | > = true; 44 | 45 | uniform bool Curvature < 46 | ui_tooltip = "Barrel effect"; 47 | > = false; 48 | uniform float CurvatureRadius < __UNIFORM_SLIDER_FLOAT1 49 | ui_min = 0.0; ui_max = 2.0; 50 | ui_label = "Curvature Radius"; 51 | > = 1.5; 52 | uniform float CornerSize < __UNIFORM_SLIDER_FLOAT1 53 | ui_min = 0.00; ui_max = 0.02; ui_step = 0.001; 54 | ui_label = "Corner Size"; 55 | ui_tooltip = "Higher values => more rounded corner"; 56 | > = 0.0100; 57 | uniform float ViewerDistance < __UNIFORM_SLIDER_FLOAT1 58 | ui_min = 0.0; ui_max = 4.0; 59 | ui_Label = "Viewer Distance"; 60 | ui_tooltip = "Simulated distance from viewer to monitor"; 61 | > = 2.00; 62 | uniform float2 Angle < __UNIFORM_SLIDER_FLOAT2 63 | ui_min = -0.2; ui_max = 0.2; 64 | ui_tooltip = "Tilt angle in radians"; 65 | > = 0.00; 66 | 67 | uniform float Overscan < __UNIFORM_SLIDER_FLOAT1 68 | ui_min = 1.0; ui_max = 1.10; ui_step = 0.01; 69 | ui_tooltip = "Overscan (e.g. 1.02 for 2% overscan)."; 70 | > = 1.01; 71 | uniform bool Oversample < 72 | ui_tooltip = "Enable 3x oversampling of the beam profile (warning : performance hit)"; 73 | > = true; 74 | 75 | #include "ReShade.fxh" 76 | 77 | #define CeeJay_aspect float2(1.0, 0.75) 78 | 79 | // A bunch of useful values we'll need in the fragment shader. 80 | #define sinangle sin(Angle) 81 | #define cosangle cos(Angle) 82 | #define stretch maxscale() 83 | 84 | // Macros. 85 | #define FIX(c) max(abs(c), 1e-5); 86 | 87 | #ifndef PI 88 | #define PI 3.1415927 89 | #endif 90 | 91 | // The size of one texel, in texture-coordinates. 92 | #define coone 1.0 / rubyTextureSize 93 | 94 | #define mod_factor tex.x * rubyTextureSize.x * rubyOutputSize.x / rubyInputSize.x 95 | 96 | #ifdef LINEAR_PROCESSING 97 | #define TEX2D(c) pow(tex2D(ReShade::BackBuffer, (c)), Gamma) 98 | #else 99 | #define TEX2D(c) tex2D(ReShade::BackBuffer, (c)) 100 | #endif 101 | 102 | float intersect(float2 xy) 103 | { 104 | float A = dot(xy,xy) + (ViewerDistance * ViewerDistance); 105 | float B = 2.0 * (CurvatureRadius * (dot(xy, sinangle) - ViewerDistance * cosangle.x * cosangle.y) - ViewerDistance * ViewerDistance); 106 | float C = ViewerDistance * ViewerDistance + 2.0 * CurvatureRadius * ViewerDistance * cosangle.x * cosangle.y; //all constants 107 | return (-B - sqrt(B * B -4.0 * A * C)) / (2.0 * A); 108 | } 109 | 110 | float2 bkwtrans(float2 xy) 111 | { 112 | float c = intersect(xy); 113 | float2 _point = float2(c, c) * xy; 114 | _point -= float2(-CurvatureRadius, -CurvatureRadius) * sinangle; 115 | _point /= float2(CurvatureRadius, CurvatureRadius); 116 | float2 tang = sinangle / cosangle; 117 | float2 poc = _point / cosangle; 118 | float A = dot(tang, tang) + 1.0; 119 | float B = -2.0 * dot(poc, tang); 120 | float C = dot(poc, poc) - 1.0; 121 | float a = (-B + sqrt(B * B -4.0 * A * C)) / (2.0 * A); 122 | float2 uv = (_point - a * sinangle) / cosangle; 123 | float r = CurvatureRadius * acos(a); 124 | return uv * r / sin(r / CurvatureRadius); 125 | } 126 | float2 fwtrans(float2 uv) 127 | { 128 | float r = FIX(sqrt(dot(uv, uv))); 129 | uv *= sin(r / CurvatureRadius) / r; 130 | float x = 1.0 - cos(r / CurvatureRadius); 131 | float D = ViewerDistance / CurvatureRadius + x * cosangle.x * cosangle.y + dot(uv, sinangle); 132 | return ViewerDistance * (uv * cosangle - x * sinangle) / D; 133 | } 134 | 135 | float3 maxscale() 136 | { 137 | float2 c = bkwtrans(-CurvatureRadius * sinangle / (1.0 + CurvatureRadius / ViewerDistance * cosangle.x * cosangle.y)); 138 | float2 a = float2(0.5, 0.5) * CeeJay_aspect; 139 | float2 lo = float2(fwtrans(float2(-a.x, c.y)).x, fwtrans(float2(c.x,-a.y)).y) / CeeJay_aspect; 140 | float2 hi = float2(fwtrans(float2(+a.x, c.y)).x, fwtrans(float2(c.x, +a.y)).y) / CeeJay_aspect; 141 | return float3((hi + lo) * CeeJay_aspect * 0.5, max(hi.x - lo.x, hi.y - lo.y)); 142 | } 143 | 144 | float2 transform(float2 coord, float2 textureSize, float2 inputSize) 145 | { 146 | coord *= textureSize / inputSize; 147 | coord = (coord - 0.5) * CeeJay_aspect * stretch.z + stretch.xy; 148 | return (bkwtrans(coord) / float2(Overscan, Overscan) / CeeJay_aspect + 0.5) * inputSize / textureSize; 149 | } 150 | 151 | float corner(float2 coord, float2 textureSize, float2 inputSize) 152 | { 153 | coord *= textureSize / inputSize; 154 | coord = (coord - 0.5) * float2(Overscan, Overscan) + 0.5; 155 | coord = min(coord, 1.0 - coord) * CeeJay_aspect; 156 | float2 cdist = float2(CornerSize, CornerSize); 157 | coord = (cdist - min(coord, cdist)); 158 | float dist = sqrt(dot(coord, coord)); 159 | return clamp((cdist.x-dist) * 1000.0, 0.0, 1.0); 160 | } 161 | 162 | // Calculate the influence of a scanline on the current pixel. 163 | // 164 | // 'distance' is the distance in texture coordinates from the current 165 | // pixel to the scanline in question. 166 | // 'color' is the colour of the scanline at the horizontal location of 167 | // the current pixel. 168 | float4 scanlineWeights(float distance, float4 color) 169 | { 170 | // "wid" controls the width of the scanline beam, for each RGB channel 171 | // The "weights" lines basically specify the formula that gives 172 | // you the profile of the beam, i.e. the intensity as 173 | // a function of distance from the vertical center of the 174 | // scanline. In this case, it is gaussian if width=2, and 175 | // becomes nongaussian for larger widths. Ideally this should 176 | // be normalized so that the integral across the beam is 177 | // independent of its width. That is, for a narrower beam 178 | // "weights" should have a higher peak at the center of the 179 | // scanline than for a wider beam. 180 | if (!ScanlineGaussian) 181 | { 182 | float4 wid = 0.3 + 0.1 * pow(abs(color), 3.0); 183 | float4 weights = float4(distance / wid); 184 | return 0.4 * exp(-weights * weights) / wid; 185 | } 186 | else 187 | { 188 | float4 wid = 2.0 * pow(abs(color), 4.0) + 2.0; 189 | float4 weights = (distance / 0.3).xxxx; 190 | return 1.4 * exp(-pow(abs(weights * rsqrt(0.5 * wid)), abs(wid))) / (0.2 * wid + 0.6); 191 | } 192 | } 193 | 194 | float3 AdvancedCRTPass(float4 position : SV_Position, float2 tex : TEXCOORD) : SV_Target 195 | { 196 | // Here's a helpful diagram to keep in mind while trying to 197 | // understand the code: 198 | // 199 | // | | | | | 200 | // ------------------------------- 201 | // | | | | | 202 | // | 01 | 11 | 21 | 31 | <-- current scanline 203 | // | | @ | | | 204 | // ------------------------------- 205 | // | | | | | 206 | // | 02 | 12 | 22 | 32 | <-- next scanline 207 | // | | | | | 208 | // ------------------------------- 209 | // | | | | | 210 | // 211 | // Each character-cell represents a pixel on the output 212 | // surface, "@" represents the current pixel (always somewhere 213 | // in the bottom half of the current scan-line, or the top-half 214 | // of the next scanline). The grid of lines represents the 215 | // edges of the texels of the underlying texture. 216 | 217 | float Input_ratio = ceil(256 * Resolution); 218 | float2 Resolution = float2(Input_ratio, Input_ratio); 219 | float2 rubyTextureSize = Resolution; 220 | float2 rubyInputSize = Resolution; 221 | float2 rubyOutputSize = BUFFER_SCREEN_SIZE; 222 | 223 | float2 orig_xy = Curvature ? transform(tex, rubyTextureSize, rubyInputSize) : tex; 224 | float cval = corner(orig_xy, rubyTextureSize, rubyInputSize); 225 | 226 | // Of all the pixels that are mapped onto the texel we are 227 | // currently rendering, which pixel are we currently rendering? 228 | float2 ratio_scale = orig_xy * rubyTextureSize - 0.5; 229 | 230 | float filter = fwidth(ratio_scale.y); 231 | float2 uv_ratio = frac(ratio_scale); 232 | 233 | // Snap to the center of the underlying texel. 234 | float2 xy = (floor(ratio_scale) + 0.5) / rubyTextureSize; 235 | 236 | // Calculate Lanczos scaling coefficients describing the effect 237 | // of various neighbour texels in a scanline on the current 238 | // pixel. 239 | float4 coeffs = PI * float4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x); 240 | 241 | // Prevent division by zero. 242 | coeffs = FIX(coeffs); 243 | 244 | // Lanczos2 kernel. 245 | coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs); 246 | 247 | // Normalize. 248 | coeffs /= dot(coeffs, 1.0); 249 | 250 | // Calculate the effective colour of the current and next 251 | // scanlines at the horizontal location of the current pixel, 252 | // using the Lanczos coefficients above. 253 | float4 col = clamp(mul(coeffs, float4x4( 254 | TEX2D(xy + float2(-coone.x, 0.0)), 255 | TEX2D(xy), 256 | TEX2D(xy + float2(coone.x, 0.0)), 257 | TEX2D(xy + float2(2.0 * coone.x, 0.0)))), 258 | 0.0, 1.0); 259 | float4 col2 = clamp(mul(coeffs, float4x4( 260 | TEX2D(xy + float2(-coone.x, coone.y)), 261 | TEX2D(xy + float2(0.0, coone.y)), 262 | TEX2D(xy + coone), 263 | TEX2D(xy + float2(2.0 * coone.x, coone.y)))), 264 | 0.0, 1.0); 265 | 266 | #ifndef LINEAR_PROCESSING 267 | col = pow(abs(col) , Gamma); 268 | col2 = pow(abs(col2), Gamma); 269 | #endif 270 | 271 | // Calculate the influence of the current and next scanlines on 272 | // the current pixel. 273 | float4 weights = scanlineWeights(uv_ratio.y, col); 274 | float4 weights2 = scanlineWeights(1.0 - uv_ratio.y, col2); 275 | 276 | #if __RENDERER__ < 0xa000 && !__RESHADE_PERFORMANCE_MODE__ 277 | [flatten] 278 | #endif 279 | if (Oversample) 280 | { 281 | uv_ratio.y = uv_ratio.y + 1.0 / 3.0 * filter; 282 | weights = (weights + scanlineWeights(uv_ratio.y, col)) / 3.0; 283 | weights2 = (weights2 + scanlineWeights(abs(1.0 - uv_ratio.y), col2)) / 3.0; 284 | uv_ratio.y = uv_ratio.y - 2.0 / 3.0 * filter; 285 | weights = weights + scanlineWeights(abs(uv_ratio.y), col) / 3.0; 286 | weights2 = weights2 + scanlineWeights(abs(1.0 - uv_ratio.y), col2) / 3.0; 287 | } 288 | 289 | float3 mul_res = (col * weights + col2 * weights2).rgb * cval.xxx; 290 | 291 | // dot-mask emulation: 292 | // Output pixels are alternately tinted green and magenta. 293 | float3 dotMaskWeights = lerp(float3(1.0, 0.7, 1.0), float3(0.7, 1.0, 0.7), floor(mod_factor % ScanlineIntensity)); 294 | mul_res *= dotMaskWeights * float3(0.83, 0.83, 1.0) * Brightness; 295 | 296 | // Convert the image gamma for display on our output device. 297 | mul_res = pow(abs(mul_res), 1.0 / MonitorGamma); 298 | 299 | float3 color = TEX2D(orig_xy).rgb * cval.xxx; 300 | color = lerp(color, mul_res, Amount); 301 | 302 | return saturate(color); 303 | } 304 | 305 | technique AdvancedCRT 306 | { 307 | pass 308 | { 309 | VertexShader = PostProcessVS; 310 | PixelShader = AdvancedCRTPass; 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /Shaders/Cartoon.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * Cartoon 3 | * by Christian Cann Schuldt Jensen ~ CeeJay.dk 4 | */ 5 | 6 | #include "ReShadeUI.fxh" 7 | 8 | uniform float Power < __UNIFORM_SLIDER_FLOAT1 9 | ui_min = 0.1; ui_max = 10.0; 10 | ui_tooltip = "Amount of effect you want."; 11 | > = 1.5; 12 | uniform float EdgeSlope < __UNIFORM_SLIDER_FLOAT1 13 | ui_min = 0.1; ui_max = 6.0; 14 | ui_label = "Edge Slope"; 15 | ui_tooltip = "Raise this to filter out fainter edges. You might need to increase the power to compensate. Whole numbers are faster."; 16 | > = 1.5; 17 | 18 | #include "ReShade.fxh" 19 | 20 | float3 CartoonPass(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target 21 | { 22 | float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb; 23 | const float3 coefLuma = float3(0.2126, 0.7152, 0.0722); 24 | 25 | float diff1 = dot(coefLuma, tex2D(ReShade::BackBuffer, texcoord + BUFFER_PIXEL_SIZE).rgb); 26 | diff1 = dot(float4(coefLuma, -1.0), float4(tex2D(ReShade::BackBuffer, texcoord - BUFFER_PIXEL_SIZE).rgb , diff1)); 27 | float diff2 = dot(coefLuma, tex2D(ReShade::BackBuffer, texcoord + BUFFER_PIXEL_SIZE * float2(1, -1)).rgb); 28 | diff2 = dot(float4(coefLuma, -1.0), float4(tex2D(ReShade::BackBuffer, texcoord + BUFFER_PIXEL_SIZE * float2(-1, 1)).rgb , diff2)); 29 | 30 | float edge = dot(float2(diff1, diff2), float2(diff1, diff2)); 31 | 32 | return saturate(pow(abs(edge), EdgeSlope) * -Power + color); 33 | } 34 | 35 | technique Cartoon 36 | { 37 | pass 38 | { 39 | VertexShader = PostProcessVS; 40 | PixelShader = CartoonPass; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Shaders/ChromaticAberration.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * Chromatic Aberration 3 | * by Christian Cann Schuldt Jensen ~ CeeJay.dk 4 | * 5 | * Distorts the image by shifting each color component, which creates color artifacts similar to those in a very cheap lens or a cheap sensor. 6 | */ 7 | 8 | #include "ReShadeUI.fxh" 9 | 10 | uniform float2 Shift < __UNIFORM_SLIDER_FLOAT2 11 | ui_min = -10; ui_max = 10; 12 | ui_tooltip = "Distance (X,Y) in pixels to shift the color components. For a slightly blurred look try fractional values (.5) between two pixels."; 13 | > = float2(2.5, -0.5); 14 | uniform float Strength < __UNIFORM_SLIDER_FLOAT1 15 | ui_min = 0.0; ui_max = 1.0; 16 | > = 0.5; 17 | 18 | #include "ReShade.fxh" 19 | 20 | float3 ChromaticAberrationPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 21 | { 22 | float3 color, colorInput = tex2D(ReShade::BackBuffer, texcoord).rgb; 23 | // Sample the color components 24 | color.r = tex2D(ReShade::BackBuffer, texcoord + (BUFFER_PIXEL_SIZE * Shift)).r; 25 | color.g = colorInput.g; 26 | color.b = tex2D(ReShade::BackBuffer, texcoord - (BUFFER_PIXEL_SIZE * Shift)).b; 27 | 28 | // Adjust the strength of the effect 29 | return lerp(colorInput, color, Strength); 30 | } 31 | 32 | technique CA 33 | { 34 | pass 35 | { 36 | VertexShader = PostProcessVS; 37 | PixelShader = ChromaticAberrationPass; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Shaders/ColorMatrix.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * Color Matrix version 1.0 3 | * by Christian Cann Schuldt Jensen ~ CeeJay.dk 4 | * 5 | * ColorMatrix allow the user to transform the colors using a color matrix 6 | */ 7 | 8 | #include "ReShadeUI.fxh" 9 | 10 | uniform float3 ColorMatrix_Red < __UNIFORM_SLIDER_FLOAT3 11 | ui_min = 0.0; ui_max = 1.0; 12 | ui_label = "Matrix Red"; 13 | ui_tooltip = "How much of a red, green and blue tint the new red value should contain. Should sum to 1.0 if you don't wish to change the brightness."; 14 | > = float3(0.817, 0.183, 0.000); 15 | uniform float3 ColorMatrix_Green < __UNIFORM_SLIDER_FLOAT3 16 | ui_min = 0.0; ui_max = 1.0; 17 | ui_label = "Matrix Green"; 18 | ui_tooltip = "How much of a red, green and blue tint the new green value should contain. Should sum to 1.0 if you don't wish to change the brightness."; 19 | > = float3(0.333, 0.667, 0.000); 20 | uniform float3 ColorMatrix_Blue < __UNIFORM_SLIDER_FLOAT3 21 | ui_min = 0.0; ui_max = 1.0; 22 | ui_label = "Matrix Blue"; 23 | ui_tooltip = "How much of a red, green and blue tint the new blue value should contain. Should sum to 1.0 if you don't wish to change the brightness."; 24 | > = float3(0.000, 0.125, 0.875); 25 | 26 | uniform float Strength < __UNIFORM_SLIDER_FLOAT1 27 | ui_min = 0.0; ui_max = 1.0; 28 | ui_tooltip = "Adjust the strength of the effect."; 29 | > = 1.0; 30 | 31 | #include "ReShade.fxh" 32 | 33 | float3 ColorMatrixPass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target 34 | { 35 | float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb; 36 | 37 | const float3x3 ColorMatrix = float3x3(ColorMatrix_Red, ColorMatrix_Green, ColorMatrix_Blue); 38 | color = lerp(color, mul(ColorMatrix, color), Strength); 39 | 40 | return saturate(color); 41 | } 42 | 43 | technique ColorMatrix 44 | { 45 | pass 46 | { 47 | VertexShader = PostProcessVS; 48 | PixelShader = ColorMatrixPass; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Shaders/Curves.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * Curves 3 | * by Christian Cann Schuldt Jensen ~ CeeJay.dk 4 | * 5 | * Curves, uses S-curves to increase contrast, without clipping highlights and shadows. 6 | */ 7 | 8 | #include "ReShadeUI.fxh" 9 | 10 | uniform int Mode < 11 | ui_type = "combo"; 12 | ui_items = "Luma\0Chroma\0Both Luma and Chroma\0"; 13 | ui_tooltip = "Choose what to apply contrast to."; 14 | > = 0; 15 | uniform int Formula < 16 | ui_type = "combo"; 17 | ui_items = "Sine\0Abs split\0Smoothstep\0Exp formula\0Simplified Catmull-Rom (0,0,1,1)\0Perlins Smootherstep\0Abs add\0Techicolor Cinestyle\0Parabola\0Half-circles\0Polynomial split\0"; 18 | ui_tooltip = "The contrast s-curve you want to use. Note that Technicolor Cinestyle is practically identical to Sine, but runs slower. In fact I think the difference might only be due to rounding errors. I prefer 2 myself, but 3 is a nice alternative with a little more effect (but harsher on the highlight and shadows) and it's the fastest formula."; 19 | > = 4; 20 | 21 | uniform float Contrast < __UNIFORM_SLIDER_FLOAT1 22 | ui_min = -1.0; ui_max = 1.0; 23 | ui_tooltip = "The amount of contrast you want."; 24 | > = 0.65; 25 | 26 | #include "ReShade.fxh" 27 | 28 | float4 CurvesPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 29 | { 30 | float4 colorInput = tex2D(ReShade::BackBuffer, texcoord); 31 | float3 lumCoeff = float3(0.2126, 0.7152, 0.0722); //Values to calculate luma with 32 | float Contrast_blend = Contrast; 33 | const float PI = 3.1415927; 34 | 35 | /*-----------------------------------------------------------. 36 | / Separation of Luma and Chroma / 37 | '-----------------------------------------------------------*/ 38 | 39 | // -- Calculate Luma and Chroma if needed -- 40 | //calculate luma (grey) 41 | float luma = dot(lumCoeff, colorInput.rgb); 42 | //calculate chroma 43 | float3 chroma = colorInput.rgb - luma; 44 | 45 | // -- Which value to put through the contrast formula? -- 46 | // I name it x because makes it easier to copy-paste to Graphtoy or Wolfram Alpha or another graphing program 47 | float3 x; 48 | if (Mode == 0) 49 | x = luma; //if the curve should be applied to Luma 50 | else if (Mode == 1) 51 | x = chroma, //if the curve should be applied to Chroma 52 | x = x * 0.5 + 0.5; //adjust range of Chroma from -1 -> 1 to 0 -> 1 53 | else 54 | x = colorInput.rgb; //if the curve should be applied to both Luma and Chroma 55 | 56 | /*-----------------------------------------------------------. 57 | / Contrast formulas / 58 | '-----------------------------------------------------------*/ 59 | 60 | // -- Curve 1 -- 61 | if (Formula == 0) 62 | { 63 | x = sin(PI * 0.5 * x); // Sin - 721 amd fps, +vign 536 nv 64 | x *= x; 65 | 66 | //x = 0.5 - 0.5*cos(PI*x); 67 | //x = 0.5 * -sin(PI * -x + (PI*0.5)) + 0.5; 68 | } 69 | 70 | // -- Curve 2 -- 71 | if (Formula == 1) 72 | { 73 | x = x - 0.5; 74 | x = (x / (0.5 + abs(x))) + 0.5; 75 | 76 | //x = ( (x - 0.5) / (0.5 + abs(x-0.5)) ) + 0.5; 77 | } 78 | 79 | // -- Curve 3 -- 80 | if (Formula == 2) 81 | { 82 | //x = smoothstep(0.0,1.0,x); //smoothstep 83 | x = x*x*(3.0 - 2.0*x); //faster smoothstep alternative - 776 amd fps, +vign 536 nv 84 | //x = x - 2.0 * (x - 1.0) * x* (x- 0.5); //2.0 is contrast. Range is 0.0 to 2.0 85 | } 86 | 87 | // -- Curve 4 -- 88 | if (Formula == 3) 89 | { 90 | x = (1.0524 * exp(6.0 * x) - 1.05248) / (exp(6.0 * x) + 20.0855); //exp formula 91 | } 92 | 93 | // -- Curve 5 -- 94 | if (Formula == 4) 95 | { 96 | //x = 0.5 * (x + 3.0 * x * x - 2.0 * x * x * x); //a simplified catmull-rom (0,0,1,1) - btw smoothstep can also be expressed as a simplified catmull-rom using (1,0,1,0) 97 | //x = (0.5 * x) + (1.5 -x) * x*x; //estrin form - faster version 98 | x = x * (x * (1.5 - x) + 0.5); //horner form - fastest version 99 | 100 | Contrast_blend = Contrast * 2.0; //I multiply by two to give it a strength closer to the other curves. 101 | } 102 | 103 | // -- Curve 6 -- 104 | if (Formula == 5) 105 | { 106 | x = x*x*x*(x*(x*6.0 - 15.0) + 10.0); //Perlins smootherstep 107 | } 108 | 109 | // -- Curve 7 -- 110 | if (Formula == 6) 111 | { 112 | //x = ((x-0.5) / ((0.5/(4.0/3.0)) + abs((x-0.5)*1.25))) + 0.5; 113 | x = x - 0.5; 114 | x = x / ((abs(x)*1.25) + 0.375) + 0.5; 115 | //x = ( (x-0.5) / ((abs(x-0.5)*1.25) + (0.5/(4.0/3.0))) ) + 0.5; 116 | } 117 | 118 | // -- Curve 8 -- 119 | if (Formula == 7) 120 | { 121 | x = (x * (x * (x * (x * (x * (x * (1.6 * x - 7.2) + 10.8) - 4.2) - 3.6) + 2.7) - 1.8) + 2.7) * x * x; //Techicolor Cinestyle - almost identical to curve 1 122 | } 123 | 124 | // -- Curve 9 -- 125 | if (Formula == 8) 126 | { 127 | x = -0.5 * (x*2.0 - 1.0) * (abs(x*2.0 - 1.0) - 2.0) + 0.5; //parabola 128 | } 129 | 130 | // -- Curve 10 -- 131 | if (Formula == 9) 132 | { 133 | float3 xstep = step(x, 0.5); //tenary might be faster here 134 | float3 xstep_shift = (xstep - 0.5); 135 | float3 shifted_x = x + xstep_shift; 136 | 137 | x = abs(xstep - sqrt(-shifted_x * shifted_x + shifted_x)) - xstep_shift; 138 | 139 | //x = abs(step(x,0.5)-sqrt(-(x+step(x,0.5)-0.5)*(x+step(x,0.5)-0.5)+(x+step(x,0.5)-0.5)))-(step(x,0.5)-0.5); //single line version of the above 140 | 141 | //x = 0.5 + (sign(x-0.5)) * sqrt(0.25-(x-trunc(x*2))*(x-trunc(x*2))); //worse 142 | 143 | /* // if/else - even worse 144 | if (x-0.5) 145 | x = 0.5-sqrt(0.25-x*x); 146 | else 147 | x = 0.5+sqrt(0.25-(x-1)*(x-1)); 148 | */ 149 | 150 | //x = (abs(step(0.5,x)-clamp( 1-sqrt(1-abs(step(0.5,x)- frac(x*2%1)) * abs(step(0.5,x)- frac(x*2%1))),0 ,1))+ step(0.5,x) )*0.5; //worst so far 151 | 152 | //TODO: Check if I could use an abs split instead of step. It might be more efficient 153 | 154 | Contrast_blend = Contrast * 0.5; //I divide by two to give it a strength closer to the other curves. 155 | } 156 | 157 | // -- Curve 11 -- 158 | if (Formula == 10) 159 | { 160 | float3 a = float3(0.0, 0.0, 0.0); 161 | float3 b = float3(0.0, 0.0, 0.0); 162 | 163 | a = x * x * 2.0; 164 | b = (2.0 * -x + 4.0) * x - 1.0; 165 | x = (x < 0.5) ? a : b; 166 | } 167 | 168 | /*-----------------------------------------------------------. 169 | / Joining of Luma and Chroma / 170 | '-----------------------------------------------------------*/ 171 | 172 | if (Mode == 0) // Only Luma 173 | { 174 | x = lerp(luma, x, Contrast_blend); //Blend by Contrast 175 | colorInput.rgb = x + chroma; //Luma + Chroma 176 | } 177 | else if (Mode == 1) // Only Chroma 178 | { 179 | x = x * 2.0 - 1.0; //adjust the Chroma range back to -1 -> 1 180 | float3 color = luma + x; //Luma + Chroma 181 | colorInput.rgb = lerp(colorInput.rgb, color, Contrast_blend); //Blend by Contrast 182 | } 183 | else // Both Luma and Chroma 184 | { 185 | float3 color = x; //if the curve should be applied to both Luma and Chroma 186 | colorInput.rgb = lerp(colorInput.rgb, color, Contrast_blend); //Blend by Contrast 187 | } 188 | 189 | return colorInput; 190 | } 191 | 192 | technique Curves 193 | { 194 | pass 195 | { 196 | VertexShader = PostProcessVS; 197 | PixelShader = CurvesPass; 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /Shaders/DPX.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * DPX/Cineon shader by Loadus 3 | */ 4 | 5 | #include "ReShadeUI.fxh" 6 | 7 | uniform float3 RGB_Curve < __UNIFORM_SLIDER_FLOAT3 8 | ui_min = 1.0; ui_max = 15.0; 9 | ui_label = "RGB Curve"; 10 | > = float3(8.0, 8.0, 8.0); 11 | uniform float3 RGB_C < __UNIFORM_SLIDER_FLOAT3 12 | ui_min = 0.2; ui_max = 0.5; 13 | ui_label = "RGB C"; 14 | > = float3(0.36, 0.36, 0.34); 15 | 16 | uniform float Contrast < __UNIFORM_SLIDER_FLOAT1 17 | ui_min = 0.0; ui_max = 1.0; 18 | > = 0.1; 19 | uniform float Saturation < __UNIFORM_SLIDER_FLOAT1 20 | ui_min = 0.0; ui_max = 8.0; 21 | > = 3.0; 22 | uniform float Colorfulness < __UNIFORM_SLIDER_FLOAT1 23 | ui_min = 0.1; ui_max = 2.5; 24 | > = 2.5; 25 | 26 | uniform float Strength < __UNIFORM_SLIDER_FLOAT1 27 | ui_min = 0.0; ui_max = 1.0; 28 | ui_tooltip = "Adjust the strength of the effect."; 29 | > = 0.20; 30 | 31 | #include "ReShade.fxh" 32 | 33 | static const float3x3 RGB = float3x3( 34 | 2.6714711726599600, -1.2672360578624100, -0.4109956021722270, 35 | -1.0251070293466400, 1.9840911624108900, 0.0439502493584124, 36 | 0.0610009456429445, -0.2236707508128630, 1.1590210416706100 37 | ); 38 | static const float3x3 XYZ = float3x3( 39 | 0.5003033835433160, 0.3380975732227390, 0.1645897795458570, 40 | 0.2579688942747580, 0.6761952591447060, 0.0658358459823868, 41 | 0.0234517888692628, 0.1126992737203000, 0.8668396731242010 42 | ); 43 | 44 | float3 DPXPass(float4 vois : SV_Position, float2 texcoord : TexCoord) : SV_Target 45 | { 46 | float3 input = tex2D(ReShade::BackBuffer, texcoord).rgb; 47 | 48 | float3 B = input; 49 | B = B * (1.0 - Contrast) + (0.5 * Contrast); 50 | float3 Btemp = (1.0 / (1.0 + exp(RGB_Curve / 2.0))); 51 | B = ((1.0 / (1.0 + exp(-RGB_Curve * (B - RGB_C)))) / (-2.0 * Btemp + 1.0)) + (-Btemp / (-2.0 * Btemp + 1.0)); 52 | 53 | float value = max(max(B.r, B.g), B.b); 54 | float3 color = B / value; 55 | color = pow(abs(color), 1.0 / Colorfulness); 56 | 57 | float3 c0 = color * value; 58 | c0 = mul(XYZ, c0); 59 | float luma = dot(c0, float3(0.30, 0.59, 0.11)); 60 | c0 = (1.0 - Saturation) * luma + Saturation * c0; 61 | c0 = mul(RGB, c0); 62 | 63 | return lerp(input, c0, Strength); 64 | } 65 | 66 | technique DPX 67 | { 68 | pass 69 | { 70 | VertexShader = PostProcessVS; 71 | PixelShader = DPXPass; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Shaders/FXAA.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * FXAA 3.11 3 | * 4 | * for ReShade 3.0+ 5 | */ 6 | 7 | #include "ReShadeUI.fxh" 8 | 9 | uniform float Subpix < __UNIFORM_SLIDER_FLOAT1 10 | ui_min = 0.0; ui_max = 1.0; 11 | ui_tooltip = "Amount of sub-pixel aliasing removal. Higher values makes the image softer/blurrier."; 12 | > = 0.25; 13 | 14 | uniform float EdgeThreshold < __UNIFORM_SLIDER_FLOAT1 15 | ui_min = 0.0; ui_max = 1.0; 16 | ui_label = "Edge Detection Threshold"; 17 | ui_tooltip = "The minimum amount of local contrast required to apply algorithm."; 18 | > = 0.125; 19 | uniform float EdgeThresholdMin < __UNIFORM_SLIDER_FLOAT1 20 | ui_min = 0.0; ui_max = 1.0; 21 | ui_label = "Darkness Threshold"; 22 | ui_tooltip = "Pixels darker than this are not processed in order to increase performance."; 23 | > = 0.0; 24 | 25 | //------------------------------ Non-GUI-settings ------------------------------------------------- 26 | 27 | #ifndef FXAA_QUALITY__PRESET 28 | // Valid Quality Presets 29 | // 10 to 15 - default medium dither (10=fastest, 15=highest quality) 30 | // 20 to 29 - less dither, more expensive (20=fastest, 29=highest quality) 31 | // 39 - no dither, very expensive 32 | #define FXAA_QUALITY__PRESET 15 33 | #endif 34 | 35 | #ifndef FXAA_GREEN_AS_LUMA 36 | #define FXAA_GREEN_AS_LUMA 0 37 | #endif 38 | 39 | #ifndef FXAA_LINEAR_LIGHT 40 | #define FXAA_LINEAR_LIGHT 0 41 | #endif 42 | 43 | //------------------------------------------------------------------------------------------------- 44 | 45 | #if (__RENDERER__ == 0xb000 || __RENDERER__ == 0xb100) 46 | #define FXAA_GATHER4_ALPHA 1 47 | #define FxaaTexAlpha4(t, p) tex2Dgather(t, p, 3) 48 | #define FxaaTexOffAlpha4(t, p, o) tex2Dgatheroffset(t, p, o, 3) 49 | #define FxaaTexGreen4(t, p) tex2Dgather(t, p, 1) 50 | #define FxaaTexOffGreen4(t, p, o) tex2Dgatheroffset(t, p, o, 1) 51 | #endif 52 | 53 | #define FXAA_PC 1 54 | #define FXAA_HLSL_3 1 55 | 56 | // Green as luma requires non-linear colorspace 57 | #if FXAA_GREEN_AS_LUMA 58 | #undef FXAA_LINEAR_LIGHT 59 | #endif 60 | 61 | #include "FXAA.fxh" 62 | #include "ReShade.fxh" 63 | 64 | // Samplers 65 | 66 | sampler FXAATexture 67 | { 68 | Texture = ReShade::BackBufferTex; 69 | MinFilter = Linear; MagFilter = Linear; 70 | #if FXAA_LINEAR_LIGHT 71 | SRGBTexture = true; 72 | #endif 73 | }; 74 | 75 | // Pixel shaders 76 | 77 | #if !FXAA_GREEN_AS_LUMA 78 | float4 FXAALumaPass(float4 vpos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target 79 | { 80 | float4 color = tex2D(ReShade::BackBuffer, texcoord.xy); 81 | color.a = sqrt(dot(color.rgb * color.rgb, float3(0.299, 0.587, 0.114))); 82 | return color; 83 | } 84 | #endif 85 | 86 | float4 FXAAPixelShader(float4 vpos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target 87 | { 88 | return FxaaPixelShader( 89 | texcoord, // pos 90 | 0, // fxaaConsolePosPos 91 | FXAATexture, // tex 92 | FXAATexture, // fxaaConsole360TexExpBiasNegOne 93 | FXAATexture, // fxaaConsole360TexExpBiasNegTwo 94 | BUFFER_PIXEL_SIZE, // fxaaQualityRcpFrame 95 | 0, // fxaaConsoleRcpFrameOpt 96 | 0, // fxaaConsoleRcpFrameOpt2 97 | 0, // fxaaConsole360RcpFrameOpt2 98 | Subpix, // fxaaQualitySubpix 99 | EdgeThreshold, // fxaaQualityEdgeThreshold 100 | EdgeThresholdMin, // fxaaQualityEdgeThresholdMin 101 | 0, // fxaaConsoleEdgeSharpness 102 | 0, // fxaaConsoleEdgeThreshold 103 | 0, // fxaaConsoleEdgeThresholdMin 104 | 0 // fxaaConsole360ConstDir 105 | ); 106 | } 107 | 108 | // Rendering passes 109 | 110 | technique FXAA 111 | { 112 | #if !FXAA_GREEN_AS_LUMA 113 | pass 114 | { 115 | VertexShader = PostProcessVS; 116 | PixelShader = FXAALumaPass; 117 | } 118 | #endif 119 | pass 120 | { 121 | VertexShader = PostProcessVS; 122 | PixelShader = FXAAPixelShader; 123 | #if FXAA_LINEAR_LIGHT 124 | SRGBWriteEnable = true; 125 | #endif 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Shaders/FakeHDR.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * HDR 3 | * by Christian Cann Schuldt Jensen ~ CeeJay.dk 4 | * 5 | * Not actual HDR - It just tries to mimic an HDR look (relatively high performance cost) 6 | */ 7 | 8 | #include "ReShadeUI.fxh" 9 | 10 | uniform float HDRPower < __UNIFORM_SLIDER_FLOAT1 11 | ui_min = 0.0; ui_max = 8.0; 12 | ui_label = "Power"; 13 | > = 1.30; 14 | uniform float radius1 < __UNIFORM_SLIDER_FLOAT1 15 | ui_min = 0.0; ui_max = 8.0; 16 | ui_label = "Radius 1"; 17 | > = 0.793; 18 | uniform float radius2 < __UNIFORM_SLIDER_FLOAT1 19 | ui_min = 0.0; ui_max = 8.0; 20 | ui_label = "Radius 2"; 21 | ui_tooltip = "Raising this seems to make the effect stronger and also brighter."; 22 | > = 0.87; 23 | 24 | #include "ReShade.fxh" 25 | 26 | float3 HDRPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 27 | { 28 | float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb; 29 | 30 | float3 bloom_sum1 = tex2D(ReShade::BackBuffer, texcoord + float2(1.5, -1.5) * radius1 * BUFFER_PIXEL_SIZE).rgb; 31 | bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2(-1.5, -1.5) * radius1 * BUFFER_PIXEL_SIZE).rgb; 32 | bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2( 1.5, 1.5) * radius1 * BUFFER_PIXEL_SIZE).rgb; 33 | bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2(-1.5, 1.5) * radius1 * BUFFER_PIXEL_SIZE).rgb; 34 | bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2( 0.0, -2.5) * radius1 * BUFFER_PIXEL_SIZE).rgb; 35 | bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2( 0.0, 2.5) * radius1 * BUFFER_PIXEL_SIZE).rgb; 36 | bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2(-2.5, 0.0) * radius1 * BUFFER_PIXEL_SIZE).rgb; 37 | bloom_sum1 += tex2D(ReShade::BackBuffer, texcoord + float2( 2.5, 0.0) * radius1 * BUFFER_PIXEL_SIZE).rgb; 38 | 39 | bloom_sum1 *= 0.005; 40 | 41 | float3 bloom_sum2 = tex2D(ReShade::BackBuffer, texcoord + float2(1.5, -1.5) * radius2 * BUFFER_PIXEL_SIZE).rgb; 42 | bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2(-1.5, -1.5) * radius2 * BUFFER_PIXEL_SIZE).rgb; 43 | bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2( 1.5, 1.5) * radius2 * BUFFER_PIXEL_SIZE).rgb; 44 | bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2(-1.5, 1.5) * radius2 * BUFFER_PIXEL_SIZE).rgb; 45 | bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2( 0.0, -2.5) * radius2 * BUFFER_PIXEL_SIZE).rgb; 46 | bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2( 0.0, 2.5) * radius2 * BUFFER_PIXEL_SIZE).rgb; 47 | bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2(-2.5, 0.0) * radius2 * BUFFER_PIXEL_SIZE).rgb; 48 | bloom_sum2 += tex2D(ReShade::BackBuffer, texcoord + float2( 2.5, 0.0) * radius2 * BUFFER_PIXEL_SIZE).rgb; 49 | 50 | bloom_sum2 *= 0.010; 51 | 52 | float dist = radius2 - radius1; 53 | float3 HDR = (color + (bloom_sum2 - bloom_sum1)) * dist; 54 | float3 blend = HDR + color; 55 | color = pow(abs(blend), abs(HDRPower)) + HDR; // pow - don't use fractions for HDRpower 56 | 57 | return saturate(color); 58 | } 59 | 60 | technique HDR 61 | { 62 | pass 63 | { 64 | VertexShader = PostProcessVS; 65 | PixelShader = HDRPass; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Shaders/FilmGrain.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * FilmGrain version 1.0 3 | * by Christian Cann Schuldt Jensen ~ CeeJay.dk 4 | * 5 | * Computes a noise pattern and blends it with the image to create a film grain look. 6 | */ 7 | 8 | #include "ReShadeUI.fxh" 9 | 10 | uniform float Intensity < __UNIFORM_SLIDER_FLOAT1 11 | ui_min = 0.0; ui_max = 1.0; 12 | ui_tooltip = "How visible the grain is. Higher is more visible."; 13 | > = 0.50; 14 | uniform float Variance < __UNIFORM_SLIDER_FLOAT1 15 | ui_min = 0.0; ui_max = 1.0; 16 | ui_tooltip = "Controls the variance of the Gaussian noise. Lower values look smoother."; 17 | > = 0.40; 18 | uniform float Mean < __UNIFORM_SLIDER_FLOAT1 19 | ui_min = 0.0; ui_max = 1.0; 20 | ui_tooltip = "Affects the brightness of the noise."; 21 | > = 0.5; 22 | 23 | uniform int SignalToNoiseRatio < __UNIFORM_SLIDER_INT1 24 | ui_min = 0; ui_max = 16; 25 | ui_label = "Signal-to-Noise Ratio"; 26 | ui_tooltip = "Higher Signal-to-Noise Ratio values give less grain to brighter pixels. 0 disables this feature."; 27 | > = 6; 28 | 29 | uniform float Timer < source = "timer"; >; 30 | 31 | #include "ReShade.fxh" 32 | 33 | float3 FilmGrainPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 34 | { 35 | float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb; 36 | 37 | //float inv_luma = dot(color, float3(-0.2126, -0.7152, -0.0722)) + 1.0; 38 | float inv_luma = dot(color, float3(-1.0/3.0, -1.0/3.0, -1.0/3.0)) + 1.0; //Calculate the inverted luma so it can be used later to control the variance of the grain 39 | 40 | /*---------------------. 41 | | :: Generate Grain :: | 42 | '---------------------*/ 43 | 44 | const float PI = 3.1415927; 45 | 46 | //time counter using requested counter from ReShade 47 | float t = Timer * 0.0022337; 48 | 49 | //PRNG 2D - create two uniform noise values and save one DP2ADD 50 | float seed = dot(texcoord, float2(12.9898, 78.233));// + t; 51 | float sine = sin(seed); 52 | float cosine = cos(seed); 53 | float uniform_noise1 = frac(sine * 43758.5453 + t); //I just salt with t because I can 54 | float uniform_noise2 = frac(cosine * 53758.5453 - t); // and it doesn't cost any extra ASM 55 | 56 | //Get settings 57 | float stn = SignalToNoiseRatio != 0 ? pow(abs(inv_luma), (float)SignalToNoiseRatio) : 1.0; // Signal to noise feature - Brighter pixels get less noise. 58 | float variance = (Variance*Variance) * stn; 59 | float mean = Mean; 60 | 61 | //Box-Muller transform 62 | uniform_noise1 = (uniform_noise1 < 0.0001) ? 0.0001 : uniform_noise1; //fix log(0) 63 | 64 | float r = sqrt(-log(uniform_noise1)); 65 | r = (uniform_noise1 < 0.0001) ? PI : r; //fix log(0) - PI happened to be the right answer for uniform_noise == ~ 0.0000517.. Close enough and we can reuse a constant. 66 | float theta = (2.0 * PI) * uniform_noise2; 67 | 68 | float gauss_noise1 = variance * r * cos(theta) + mean; 69 | //float gauss_noise2 = variance * r * sin(theta) + mean; //we can get two gaussians out of it :) 70 | 71 | //gauss_noise1 = (ddx(gauss_noise1) - ddy(gauss_noise1)) * 0.50 + gauss_noise2; 72 | 73 | 74 | //Calculate how big the shift should be 75 | //float grain = lerp(1.0 - Intensity, 1.0 + Intensity, gauss_noise1); 76 | float grain = lerp(1.0 + Intensity, 1.0 - Intensity, gauss_noise1); 77 | 78 | //float grain2 = (2.0 * Intensity) * gauss_noise1 + (1.0 - Intensity); 79 | 80 | //Apply grain 81 | color = color * grain; 82 | 83 | //color = (grain-1.0) *2.0 + 0.5; 84 | 85 | //color = lerp(color,colorInput.rgb,sqrt(luma)); 86 | 87 | /*-------------------------. 88 | | :: Debugging features :: | 89 | '-------------------------*/ 90 | 91 | //color.rgb = frac(gauss_noise1).xxx; //show the noise 92 | //color.rgb = (gauss_noise1 > 0.999) ? float3(1.0,1.0,0.0) : 0.0 ; //does it reach 1.0? 93 | 94 | return color.rgb; 95 | } 96 | 97 | technique FilmGrain 98 | { 99 | pass 100 | { 101 | VertexShader = PostProcessVS; 102 | PixelShader = FilmGrainPass; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Shaders/Layer.fx: -------------------------------------------------------------------------------- 1 | /*------------------. 2 | | :: Description :: | 3 | '-------------------/ 4 | 5 | Layer (version 0.2) 6 | 7 | Author: CeeJay.dk 8 | License: MIT 9 | 10 | About: 11 | Blends an image with the game. 12 | The idea is to give users with graphics skills the ability to create effects using a layer just like in an image editor. 13 | Maybe they could use this to create custom CRT effects, custom vignettes, logos, custom hud elements, toggable help screens and crafting tables or something I haven't thought of. 14 | 15 | Ideas for future improvement: 16 | * More blend modes 17 | * Tiling control 18 | * A default Layer texture with something useful in it 19 | 20 | History: 21 | (*) Feature (+) Improvement (x) Bugfix (-) Information (!) Compatibility 22 | 23 | Version 0.2 by seri14 & Marot Satil 24 | * Added the ability to scale and move the layer around on XY axis 25 | */ 26 | 27 | #include "ReShade.fxh" 28 | 29 | #ifndef LAYER_SOURCE 30 | #define LAYER_SOURCE "Layer.png" 31 | #endif 32 | #ifndef LAYER_SIZE_X 33 | #define LAYER_SIZE_X 1280 34 | #endif 35 | #ifndef LAYER_SIZE_Y 36 | #define LAYER_SIZE_Y 720 37 | #endif 38 | 39 | #if LAYER_SINGLECHANNEL 40 | #define TEXFORMAT R8 41 | #else 42 | #define TEXFORMAT RGBA8 43 | #endif 44 | 45 | #include "ReShadeUI.fxh" 46 | 47 | uniform float2 Layer_Pos < __UNIFORM_DRAG_FLOAT2 48 | ui_label = "Layer Position"; 49 | ui_min = 0.0; ui_max = 1.0; 50 | ui_step = (1.0 / 200.0); 51 | > = float2(0.5, 0.5); 52 | 53 | uniform float Layer_Scale < __UNIFORM_DRAG_FLOAT1 54 | ui_label = "Layer Scale"; 55 | ui_min = (1.0 / 100.0); ui_max = 4.0; 56 | ui_step = (1.0 / 250.0); 57 | > = 1.0; 58 | 59 | uniform float Layer_Blend < __UNIFORM_COLOR_FLOAT1 60 | ui_label = "Layer Blend"; 61 | ui_tooltip = "How much to blend layer with the original image."; 62 | ui_min = 0.0; ui_max = 1.0; 63 | ui_step = (1.0 / 255.0); // for slider and drag 64 | > = 1.0; 65 | 66 | texture Layer_Tex < 67 | source = LAYER_SOURCE; 68 | > { 69 | Format = TEXFORMAT; 70 | Width = LAYER_SIZE_X; 71 | Height = LAYER_SIZE_Y; 72 | }; 73 | 74 | sampler Layer_Sampler 75 | { 76 | Texture = Layer_Tex; 77 | AddressU = BORDER; 78 | AddressV = BORDER; 79 | }; 80 | 81 | void PS_Layer(float4 pos : SV_Position, float2 texCoord : TEXCOORD, out float4 passColor : SV_Target) 82 | { 83 | const float4 backColor = tex2D(ReShade::BackBuffer, texCoord); 84 | const float2 pixelSize = 1.0 / (float2(LAYER_SIZE_X, LAYER_SIZE_Y) * Layer_Scale / BUFFER_SCREEN_SIZE); 85 | const float4 layer = tex2D(Layer_Sampler, texCoord * pixelSize + Layer_Pos * (1.0 - pixelSize)); 86 | 87 | passColor = lerp(backColor, layer, layer.a * Layer_Blend); 88 | passColor.a = backColor.a; 89 | } 90 | 91 | technique Layer 92 | { 93 | pass 94 | { 95 | VertexShader = PostProcessVS; 96 | PixelShader = PS_Layer; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Shaders/Levels.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * Levels version 1.2 3 | * by Christian Cann Schuldt Jensen ~ CeeJay.dk 4 | * 5 | * Allows you to set a new black and a white level. 6 | * This increases contrast, but clips any colors outside the new range to either black or white 7 | * and so some details in the shadows or highlights can be lost. 8 | * 9 | * The shader is very useful for expanding the 16-235 TV range to 0-255 PC range. 10 | * You might need it if you're playing a game meant to display on a TV with an emulator that does not do this. 11 | * But it's also a quick and easy way to uniformly increase the contrast of an image. 12 | * 13 | * -- Version 1.0 -- 14 | * First release 15 | * -- Version 1.1 -- 16 | * Optimized to only use 1 instruction (down from 2 - a 100% performance increase :) ) 17 | * -- Version 1.2 -- 18 | * Added the ability to highlight clipping regions of the image with #define HighlightClipping 1 19 | */ 20 | 21 | #include "ReShadeUI.fxh" 22 | 23 | uniform int BlackPoint < __UNIFORM_SLIDER_INT1 24 | ui_min = 0; ui_max = 255; 25 | ui_label = "Black Point"; 26 | ui_tooltip = "The black point is the new black - literally. Everything darker than this will become completely black."; 27 | > = 16; 28 | 29 | uniform int WhitePoint < __UNIFORM_SLIDER_INT1 30 | ui_min = 0; ui_max = 255; 31 | ui_label = "White Point"; 32 | ui_tooltip = "The new white point. Everything brighter than this becomes completely white"; 33 | > = 235; 34 | 35 | uniform bool HighlightClipping < 36 | ui_label = "Highlight clipping pixels"; 37 | ui_tooltip = "Colors between the two points will stretched, which increases contrast, but details above and below the points are lost (this is called clipping).\n" 38 | "This setting marks the pixels that clip.\n" 39 | "Red: Some detail is lost in the highlights\n" 40 | "Yellow: All detail is lost in the highlights\n" 41 | "Blue: Some detail is lost in the shadows\n" 42 | "Cyan: All detail is lost in the shadows."; 43 | > = false; 44 | 45 | #include "ReShade.fxh" 46 | 47 | float3 LevelsPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 48 | { 49 | float black_point_float = BlackPoint / 255.0; 50 | float white_point_float = WhitePoint == BlackPoint ? (255.0 / 0.00025) : (255.0 / (WhitePoint - BlackPoint)); // Avoid division by zero if the white and black point are the same 51 | 52 | float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb; 53 | color = color * white_point_float - (black_point_float * white_point_float); 54 | 55 | if (HighlightClipping) 56 | { 57 | float3 clipped_colors; 58 | 59 | clipped_colors = any(color > saturate(color)) // any colors whiter than white? 60 | ? float3(1.0, 0.0, 0.0) 61 | : color; 62 | clipped_colors = all(color > saturate(color)) // all colors whiter than white? 63 | ? float3(1.0, 1.0, 0.0) 64 | : clipped_colors; 65 | clipped_colors = any(color < saturate(color)) // any colors blacker than black? 66 | ? float3(0.0, 0.0, 1.0) 67 | : clipped_colors; 68 | clipped_colors = all(color < saturate(color)) // all colors blacker than black? 69 | ? float3(0.0, 1.0, 1.0) 70 | : clipped_colors; 71 | 72 | color = clipped_colors; 73 | } 74 | 75 | return color; 76 | } 77 | 78 | technique Levels 79 | { 80 | pass 81 | { 82 | VertexShader = PostProcessVS; 83 | PixelShader = LevelsPass; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Shaders/LiftGammaGain.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * Lift Gamma Gain version 1.1 3 | * by 3an and CeeJay.dk 4 | */ 5 | 6 | #include "ReShadeUI.fxh" 7 | 8 | uniform float3 RGB_Lift < __UNIFORM_SLIDER_FLOAT3 9 | ui_min = 0.0; ui_max = 2.0; 10 | ui_label = "RGB Lift"; 11 | ui_tooltip = "Adjust shadows for red, green and blue."; 12 | > = float3(1.0, 1.0, 1.0); 13 | uniform float3 RGB_Gamma < __UNIFORM_SLIDER_FLOAT3 14 | ui_min = 0.0; ui_max = 2.0; 15 | ui_label = "RGB Gamma"; 16 | ui_tooltip = "Adjust midtones for red, green and blue."; 17 | > = float3(1.0, 1.0, 1.0); 18 | uniform float3 RGB_Gain < __UNIFORM_SLIDER_FLOAT3 19 | ui_min = 0.0; ui_max = 2.0; 20 | ui_label = "RGB Gain"; 21 | ui_tooltip = "Adjust highlights for red, green and blue."; 22 | > = float3(1.0, 1.0, 1.0); 23 | 24 | 25 | #include "ReShade.fxh" 26 | 27 | float3 LiftGammaGainPass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target 28 | { 29 | float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb; 30 | 31 | // -- Lift -- 32 | color = color * (1.5 - 0.5 * RGB_Lift) + 0.5 * RGB_Lift - 0.5; 33 | color = saturate(color); // Is not strictly necessary, but does not cost performance 34 | 35 | // -- Gain -- 36 | color *= RGB_Gain; 37 | 38 | // -- Gamma -- 39 | color = pow(abs(color), 1.0 / RGB_Gamma); 40 | 41 | return saturate(color); 42 | } 43 | 44 | 45 | technique LiftGammaGain 46 | { 47 | pass 48 | { 49 | VertexShader = PostProcessVS; 50 | PixelShader = LiftGammaGainPass; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Shaders/LumaSharpen.fx: -------------------------------------------------------------------------------- 1 | /** 2 | LumaSharpen version 1.5.0 3 | by Christian Cann Schuldt Jensen ~ CeeJay.dk 4 | 5 | It blurs the original pixel with the surrounding pixels and then subtracts this blur to sharpen the image. 6 | It does this in luma to avoid color artifacts and allows limiting the maximum sharpning to avoid or lessen halo artifacts. 7 | This is similar to using Unsharp Mask in Photoshop. 8 | 9 | Version 1.5.1 10 | - UI improvements for Reshade 3.x 11 | */ 12 | 13 | #include "ReShadeUI.fxh" 14 | 15 | uniform float sharp_strength < __UNIFORM_SLIDER_FLOAT1 16 | ui_min = 0.1; ui_max = 3.0; 17 | ui_label = "Shapening strength"; 18 | ui_tooltip = "Strength of the sharpening"; 19 | 20 | > = 0.65; 21 | uniform float sharp_clamp < __UNIFORM_SLIDER_FLOAT1 22 | ui_min = 0.0; ui_max = 1.0; ui_step = 0.005; 23 | ui_label = "Sharpening limit"; 24 | ui_tooltip = "Limits maximum amount of sharpening a pixel receives\nThis helps avoid \"haloing\" artifacts which would otherwise occur when you raised the strength too much."; 25 | > = 0.035; 26 | uniform int pattern < 27 | ui_type = "combo"; 28 | ui_items = "Fast" "\0" 29 | "Normal" "\0" 30 | "Wider" "\0" 31 | "Pyramid shaped" "\0"; 32 | ui_label = "Sample pattern"; 33 | ui_tooltip = "Choose a sample pattern.\n" 34 | "Fast is faster but slightly lower quality.\n" 35 | "Normal is normal.\n" 36 | "Wider is less sensitive to noise but also to fine details.\n" 37 | "Pyramid has a slightly more aggresive look."; 38 | > = 1; 39 | uniform float offset_bias < __UNIFORM_SLIDER_FLOAT1 40 | ui_min = 0.0; ui_max = 6.0; 41 | ui_label = "Offset bias"; 42 | ui_tooltip = "Offset bias adjusts the radius of the sampling pattern. I designed the pattern for an offset bias of 1.0, but feel free to experiment."; 43 | > = 1.0; 44 | uniform bool show_sharpen < 45 | ui_label = "Show sharpening pattern"; 46 | ui_tooltip = "Visualize the strength of the sharpen\nThis is useful for seeing what areas the sharpning affects the most"; 47 | > = false; 48 | 49 | #include "ReShade.fxh" 50 | 51 | /*-----------------------------------------------------------. 52 | / Developer settings / 53 | '-----------------------------------------------------------*/ 54 | #define CoefLuma float3(0.2126, 0.7152, 0.0722) // BT.709 & sRBG luma coefficient (Monitors and HD Television) 55 | //#define CoefLuma float3(0.299, 0.587, 0.114) // BT.601 luma coefficient (SD Television) 56 | //#define CoefLuma float3(1.0/3.0, 1.0/3.0, 1.0/3.0) // Equal weight coefficient 57 | 58 | /*-----------------------------------------------------------. 59 | / Main code / 60 | '-----------------------------------------------------------*/ 61 | 62 | float3 LumaSharpenPass(float4 position : SV_Position, float2 tex : TEXCOORD) : SV_Target 63 | { 64 | // -- Get the original pixel -- 65 | float3 ori = tex2D(ReShade::BackBuffer, tex).rgb; // ori = original pixel 66 | 67 | // -- Combining the strength and luma multipliers -- 68 | float3 sharp_strength_luma = (CoefLuma * sharp_strength); //I'll be combining even more multipliers with it later on 69 | 70 | /*-----------------------------------------------------------. 71 | / Sampling patterns / 72 | '-----------------------------------------------------------*/ 73 | float3 blur_ori; 74 | 75 | // [ NW, , NE ] Each texture lookup (except ori) 76 | // [ ,ori, ] samples 4 pixels 77 | // [ SW, , SE ] 78 | 79 | // -- Pattern 1 -- A (fast) 7 tap gaussian using only 2+1 texture fetches. 80 | if (pattern == 0) 81 | { 82 | // -- Gaussian filter -- 83 | // [ 1/9, 2/9, ] [ 1 , 2 , ] 84 | // [ 2/9, 8/9, 2/9] = [ 2 , 8 , 2 ] 85 | // [ , 2/9, 1/9] [ , 2 , 1 ] 86 | 87 | blur_ori = tex2D(ReShade::BackBuffer, tex + (BUFFER_PIXEL_SIZE / 3.0) * offset_bias).rgb; // North West 88 | blur_ori += tex2D(ReShade::BackBuffer, tex + (-BUFFER_PIXEL_SIZE / 3.0) * offset_bias).rgb; // South East 89 | 90 | //blur_ori += tex2D(ReShade::BackBuffer, tex + (BUFFER_PIXEL_SIZE / 3.0) * offset_bias); // North East 91 | //blur_ori += tex2D(ReShade::BackBuffer, tex + (-BUFFER_PIXEL_SIZE / 3.0) * offset_bias); // South West 92 | 93 | blur_ori /= 2; //Divide by the number of texture fetches 94 | 95 | sharp_strength_luma *= 1.5; // Adjust strength to aproximate the strength of pattern 2 96 | } 97 | 98 | // -- Pattern 2 -- A 9 tap gaussian using 4+1 texture fetches. 99 | if (pattern == 1) 100 | { 101 | // -- Gaussian filter -- 102 | // [ .25, .50, .25] [ 1 , 2 , 1 ] 103 | // [ .50, 1, .50] = [ 2 , 4 , 2 ] 104 | // [ .25, .50, .25] [ 1 , 2 , 1 ] 105 | 106 | blur_ori = tex2D(ReShade::BackBuffer, tex + float2(BUFFER_PIXEL_SIZE.x, -BUFFER_PIXEL_SIZE.y) * 0.5 * offset_bias).rgb; // South East 107 | blur_ori += tex2D(ReShade::BackBuffer, tex - BUFFER_PIXEL_SIZE * 0.5 * offset_bias).rgb; // South West 108 | blur_ori += tex2D(ReShade::BackBuffer, tex + BUFFER_PIXEL_SIZE * 0.5 * offset_bias).rgb; // North East 109 | blur_ori += tex2D(ReShade::BackBuffer, tex - float2(BUFFER_PIXEL_SIZE.x, -BUFFER_PIXEL_SIZE.y) * 0.5 * offset_bias).rgb; // North West 110 | 111 | blur_ori *= 0.25; // ( /= 4) Divide by the number of texture fetches 112 | } 113 | 114 | // -- Pattern 3 -- An experimental 17 tap gaussian using 4+1 texture fetches. 115 | if (pattern == 2) 116 | { 117 | // -- Gaussian filter -- 118 | // [ , 4 , 6 , , ] 119 | // [ ,16 ,24 ,16 , 4 ] 120 | // [ 6 ,24 , ,24 , 6 ] 121 | // [ 4 ,16 ,24 ,16 , ] 122 | // [ , , 6 , 4 , ] 123 | 124 | blur_ori = tex2D(ReShade::BackBuffer, tex + BUFFER_PIXEL_SIZE * float2(0.4, -1.2) * offset_bias).rgb; // South South East 125 | blur_ori += tex2D(ReShade::BackBuffer, tex - BUFFER_PIXEL_SIZE * float2(1.2, 0.4) * offset_bias).rgb; // West South West 126 | blur_ori += tex2D(ReShade::BackBuffer, tex + BUFFER_PIXEL_SIZE * float2(1.2, 0.4) * offset_bias).rgb; // East North East 127 | blur_ori += tex2D(ReShade::BackBuffer, tex - BUFFER_PIXEL_SIZE * float2(0.4, -1.2) * offset_bias).rgb; // North North West 128 | 129 | blur_ori *= 0.25; // ( /= 4) Divide by the number of texture fetches 130 | 131 | sharp_strength_luma *= 0.51; 132 | } 133 | 134 | // -- Pattern 4 -- A 9 tap high pass (pyramid filter) using 4+1 texture fetches. 135 | if (pattern == 3) 136 | { 137 | // -- Gaussian filter -- 138 | // [ .50, .50, .50] [ 1 , 1 , 1 ] 139 | // [ .50, , .50] = [ 1 , , 1 ] 140 | // [ .50, .50, .50] [ 1 , 1 , 1 ] 141 | 142 | blur_ori = tex2D(ReShade::BackBuffer, tex + float2(0.5 * BUFFER_PIXEL_SIZE.x, -BUFFER_PIXEL_SIZE.y * offset_bias)).rgb; // South South East 143 | blur_ori += tex2D(ReShade::BackBuffer, tex + float2(offset_bias * -BUFFER_PIXEL_SIZE.x, 0.5 * -BUFFER_PIXEL_SIZE.y)).rgb; // West South West 144 | blur_ori += tex2D(ReShade::BackBuffer, tex + float2(offset_bias * BUFFER_PIXEL_SIZE.x, 0.5 * BUFFER_PIXEL_SIZE.y)).rgb; // East North East 145 | blur_ori += tex2D(ReShade::BackBuffer, tex + float2(0.5 * -BUFFER_PIXEL_SIZE.x, BUFFER_PIXEL_SIZE.y * offset_bias)).rgb; // North North West 146 | 147 | //blur_ori += (2 * ori); // Probably not needed. Only serves to lessen the effect. 148 | 149 | blur_ori /= 4.0; //Divide by the number of texture fetches 150 | 151 | sharp_strength_luma *= 0.666; // Adjust strength to aproximate the strength of pattern 2 152 | } 153 | 154 | /*-----------------------------------------------------------. 155 | / Sharpen / 156 | '-----------------------------------------------------------*/ 157 | 158 | // -- Calculate the sharpening -- 159 | float3 sharp = ori - blur_ori; //Subtracting the blurred image from the original image 160 | 161 | #if 0 //older 1.4 code (included here because the new code while faster can be difficult to understand) 162 | // -- Adjust strength of the sharpening -- 163 | float sharp_luma = dot(sharp, sharp_strength_luma); //Calculate the luma and adjust the strength 164 | 165 | // -- Clamping the maximum amount of sharpening to prevent halo artifacts -- 166 | sharp_luma = clamp(sharp_luma, -sharp_clamp, sharp_clamp); //TODO Try a curve function instead of a clamp 167 | 168 | #else //new code 169 | // -- Adjust strength of the sharpening and clamp it-- 170 | float4 sharp_strength_luma_clamp = float4(sharp_strength_luma * (0.5 / sharp_clamp),0.5); //Roll part of the clamp into the dot 171 | 172 | //sharp_luma = saturate((0.5 / sharp_clamp) * sharp_luma + 0.5); //scale up and clamp 173 | float sharp_luma = saturate(dot(float4(sharp,1.0), sharp_strength_luma_clamp)); //Calculate the luma, adjust the strength, scale up and clamp 174 | sharp_luma = (sharp_clamp * 2.0) * sharp_luma - sharp_clamp; //scale down 175 | #endif 176 | 177 | // -- Combining the values to get the final sharpened pixel -- 178 | float3 outputcolor = ori + sharp_luma; // Add the sharpening to the the original. 179 | 180 | /*-----------------------------------------------------------. 181 | / Returning the output / 182 | '-----------------------------------------------------------*/ 183 | 184 | if (show_sharpen) 185 | { 186 | //outputcolor = abs(sharp * 4.0); 187 | outputcolor = saturate(0.5 + (sharp_luma * 4.0)).rrr; 188 | } 189 | 190 | return saturate(outputcolor); 191 | } 192 | 193 | technique LumaSharpen 194 | { 195 | pass 196 | { 197 | VertexShader = PostProcessVS; 198 | PixelShader = LumaSharpenPass; 199 | } 200 | } 201 | -------------------------------------------------------------------------------- /Shaders/Monochrome.fx: -------------------------------------------------------------------------------- 1 | /*------------------. 2 | | :: Description :: | 3 | '-------------------/ 4 | 5 | Monochrome (version 1.1) 6 | 7 | Author: CeeJay.dk 8 | License: MIT 9 | 10 | About: 11 | Removes color making everything monochrome. 12 | 13 | Ideas for future improvement: 14 | * Tinting 15 | * Select a hue to keep its color, thus making it stand out against a monochrome background 16 | * Try Lab colorspace 17 | * Apply color gradient 18 | * Add an option to normalize the coefficients 19 | * Publish best-selling book titled "256 shades of grey" 20 | 21 | History: 22 | (*) Feature (+) Improvement (x) Bugfix (-) Information (!) Compatibility 23 | 24 | Version 1.0 25 | * Converts image to monochrome 26 | * Allows users to add saturation back in. 27 | 28 | Version 1.1 29 | * Added many presets based on B/W camera films 30 | + Improved settings UI 31 | ! Made settings backwards compatible with SweetFX 32 | 33 | */ 34 | 35 | 36 | /*---------------. 37 | | :: Includes :: | 38 | '---------------*/ 39 | 40 | #include "ReShade.fxh" 41 | #include "ReShadeUI.fxh" 42 | 43 | uniform int Monochrome_preset < 44 | ui_type = "combo"; 45 | ui_label = "Preset"; 46 | ui_tooltip = "Choose a preset"; 47 | //ui_category = ""; 48 | ui_items = "Custom\0" 49 | "Monitor or modern TV\0" 50 | "Equal weight\0" 51 | "Agfa 200X\0" 52 | "Agfapan 25\0" 53 | "Agfapan 100\0" 54 | "Agfapan 400\0" 55 | "Ilford Delta 100\0" 56 | "Ilford Delta 400\0" 57 | "Ilford Delta 400 Pro & 3200\0" 58 | "Ilford FP4\0" 59 | "Ilford HP5\0" 60 | "Ilford Pan F\0" 61 | "Ilford SFX\0" 62 | "Ilford XP2 Super\0" 63 | "Kodak Tmax 100\0" 64 | "Kodak Tmax 400\0" 65 | "Kodak Tri-X\0"; 66 | > = 0; 67 | 68 | uniform float3 Monochrome_conversion_values < __UNIFORM_COLOR_FLOAT3 69 | ui_label = "Custom Conversion values"; 70 | > = float3(0.21, 0.72, 0.07); 71 | 72 | /* 73 | uniform bool Normalize < 74 | ui_label = "Normalize"; 75 | ui_tooltip = "Normalize the coefficients?"; 76 | > = false; 77 | */ 78 | 79 | uniform float Monochrome_color_saturation < __UNIFORM_SLIDER_FLOAT1 80 | ui_label = "Saturation"; 81 | ui_min = 0.0; ui_max = 1.0; 82 | > = 0.0; 83 | 84 | float3 MonochromePass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 85 | { 86 | float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb; 87 | 88 | float3 Coefficients = float3(0.21, 0.72, 0.07); 89 | 90 | float3 Coefficients_array[18] = 91 | { 92 | Monochrome_conversion_values, //Custom 93 | float3(0.21, 0.72, 0.07), //sRGB monitor 94 | float3(0.3333333, 0.3333334, 0.3333333), //Equal weight 95 | float3(0.18, 0.41, 0.41), //Agfa 200X 96 | float3(0.25, 0.39, 0.36), //Agfapan 25 97 | float3(0.21, 0.40, 0.39), //Agfapan 100 98 | float3(0.20, 0.41, 0.39), //Agfapan 400 99 | float3(0.21, 0.42, 0.37), //Ilford Delta 100 100 | float3(0.22, 0.42, 0.36), //Ilford Delta 400 101 | float3(0.31, 0.36, 0.33), //Ilford Delta 400 Pro & 3200 102 | float3(0.28, 0.41, 0.31), //Ilford FP4 103 | float3(0.23, 0.37, 0.40), //Ilford HP5 104 | float3(0.33, 0.36, 0.31), //Ilford Pan F 105 | float3(0.36, 0.31, 0.33), //Ilford SFX 106 | float3(0.21, 0.42, 0.37), //Ilford XP2 Super 107 | float3(0.24, 0.37, 0.39), //Kodak Tmax 100 108 | float3(0.27, 0.36, 0.37), //Kodak Tmax 400 109 | float3(0.25, 0.35, 0.40) //Kodak Tri-X 110 | }; 111 | 112 | Coefficients = Coefficients_array[Monochrome_preset]; 113 | 114 | // Calculate monochrome 115 | float3 grey = dot(Coefficients, color); 116 | 117 | // Adjust the remaining saturation 118 | color = lerp(grey, color, Monochrome_color_saturation); 119 | 120 | // Return the result 121 | return saturate(color); 122 | } 123 | 124 | technique Monochrome 125 | { 126 | pass 127 | { 128 | VertexShader = PostProcessVS; 129 | PixelShader = MonochromePass; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /Shaders/Nostalgia.fx: -------------------------------------------------------------------------------- 1 | /*------------------. 2 | | :: Description :: | 3 | '-------------------/ 4 | 5 | Nostalgia (version 1.3) 6 | 7 | Author: CeeJay.dk 8 | License: MIT 9 | 10 | About: 11 | In this effect I try to recreate the looks of systems from a bygone era. 12 | I've started with reducing the color to that of systems with 16 color palette. 13 | 14 | Ideas for future improvement: 15 | * Try HSL / HCY / Lab or other colorspaces. I'm not sure RGB is the best choice for color matching. 16 | * Pixelation 17 | * Scanlines 18 | * CRT patterns 19 | * Curvature 20 | * More Dithering (both good and the bad dithering used back then) 21 | * Levels (might be needed because older system were often displayed on televisions and older monitors - not modern monitors) 22 | 23 | History: 24 | (*) Feature (+) Improvement (x) Bugfix (-) Information (!) Compatibility 25 | 26 | Version 1.0 by CeeJay.dk 27 | * Color reduction to C64 palette 28 | 29 | Version 1.1 by CeeJay.dk 30 | * Added ability to set a custom palette 31 | * Added EGA palette 32 | + Improved settings UI 33 | - Commented much of the code 34 | 35 | Version 1.2 by microdee 36 | + Added more color palettes from wikipedia 37 | + Palettes can have different color counts 38 | 39 | Version 1.3 by CeeJay.dk 40 | * Added Aek16 palette 41 | + Made Nostalgia do color matching in linear space which improves color matching 42 | * Added checker board dithering 43 | * Added scanlines 44 | */ 45 | 46 | 47 | /*---------------. 48 | | :: Includes :: | 49 | '---------------*/ 50 | 51 | #include "ReShade.fxh" 52 | #include "ReShadeUI.fxh" 53 | 54 | /*--------------. 55 | | :: Defines :: | 56 | '--------------*/ 57 | 58 | #ifndef Nostalgia_linear 59 | #define Nostalgia_linear 1 60 | #endif 61 | 62 | /*------------------. 63 | | :: UI Settings :: | 64 | '------------------*/ 65 | 66 | uniform int Nostalgia_scanlines 67 | < 68 | ui_type = "combo"; 69 | ui_label = "Scanlines"; 70 | ui_items = 71 | "None\0" 72 | "Type 1\0" 73 | "Type 2\0"; 74 | //ui_category = ""; 75 | > = 1; 76 | 77 | uniform int Nostalgia_color_reduction 78 | < 79 | ui_type = "combo"; 80 | ui_label = "Color reduction type"; 81 | //ui_tooltip = "Choose a color reduction type"; 82 | //ui_category = ""; 83 | ui_items = 84 | "None\0" 85 | "Palette\0" 86 | //"Quantize\0" 87 | ; 88 | > = 1; 89 | 90 | uniform bool Nostalgia_dither 91 | < 92 | ui_label = "Dither"; 93 | > = 0; 94 | 95 | uniform int Nostalgia_palette < 96 | ui_type = "combo"; 97 | ui_label = "Palette"; 98 | ui_tooltip = "Choose a palette"; 99 | //ui_category = ""; 100 | ui_items = 101 | "Custom\0" 102 | "C64 palette\0" 103 | "EGA palette\0" 104 | "IBMPC palette\0" 105 | "ZXSpectrum palette\0" 106 | "AppleII palette\0" 107 | "NTSC palette\0" 108 | "Commodore VIC-20\0" 109 | "MSX Systems\0" 110 | "Thomson MO5\0" 111 | "Amstrad CPC\0" 112 | "Atari ST\0" 113 | "Mattel Aquarius\0" 114 | "Gameboy\0" 115 | "Aek16 palette"; 116 | > = 0; 117 | 118 | uniform float3 Nostalgia_color_0 < __UNIFORM_COLOR_FLOAT3 119 | ui_label = "Color 0"; 120 | ui_category = "Custom palette"; 121 | > = float3( 0. , 0. , 0. ); //Black; 122 | 123 | uniform float3 Nostalgia_color_1 < __UNIFORM_COLOR_FLOAT3 124 | ui_label = "Color 1"; 125 | ui_category = "Custom palette"; > 126 | = float3(255. , 255. , 255. ) / 255.; //White 127 | 128 | uniform float3 Nostalgia_color_2 < __UNIFORM_COLOR_FLOAT3 129 | ui_label = "Color 2"; 130 | ui_category = "Custom palette"; 131 | > = float3(136. , 0. , 0. ) / 255.; //Red; 132 | 133 | uniform float3 Nostalgia_color_3 < __UNIFORM_COLOR_FLOAT3 134 | ui_label = "Color 3"; 135 | ui_category = "Custom palette"; 136 | > = float3(170. , 255. , 238. ) / 255.; //Cyan 137 | 138 | uniform float3 Nostalgia_color_4 < __UNIFORM_COLOR_FLOAT3 139 | ui_label = "Color 4"; 140 | ui_category = "Custom palette"; 141 | > = float3(204. , 68. , 204. ) / 255.; //Violet 142 | 143 | uniform float3 Nostalgia_color_5 < __UNIFORM_COLOR_FLOAT3 144 | ui_label = "Color 5"; 145 | ui_category = "Custom palette"; 146 | > = float3( 0. , 204. , 85. ) / 255.; //Green 147 | 148 | uniform float3 Nostalgia_color_6 < __UNIFORM_COLOR_FLOAT3 149 | ui_label = "Color 6"; 150 | ui_category = "Custom palette"; 151 | > = float3( 0. , 0. , 170. ) / 255.; //Blue 152 | 153 | uniform float3 Nostalgia_color_7 < __UNIFORM_COLOR_FLOAT3 154 | ui_label = "Color 7"; 155 | ui_category = "Custom palette"; 156 | > = float3(238. , 238. , 119. ) / 255.; //Yellow 1 157 | 158 | uniform float3 Nostalgia_color_8 < __UNIFORM_COLOR_FLOAT3 159 | ui_label = "Color 8"; 160 | ui_category = "Custom palette"; 161 | > = float3(221. , 136. , 85. ) / 255.; //Orange 162 | 163 | uniform float3 Nostalgia_color_9 < __UNIFORM_COLOR_FLOAT3 164 | ui_label = "Color 9"; 165 | ui_category = "Custom palette"; 166 | > = float3(102. , 68. , 0. ) / 255.; //Brown 167 | 168 | uniform float3 Nostalgia_color_10 < __UNIFORM_COLOR_FLOAT3 169 | ui_label = "Color 10"; 170 | ui_category = "Custom palette"; 171 | > = float3(255. , 119. , 119. ) / 255.; //Yellow 2 172 | 173 | uniform float3 Nostalgia_color_11 < __UNIFORM_COLOR_FLOAT3 174 | ui_label = "Color 11"; 175 | ui_category = "Custom palette"; 176 | > = float3( 51. , 51. , 51. ) / 255.; //Grey 1 177 | 178 | uniform float3 Nostalgia_color_12 < __UNIFORM_COLOR_FLOAT3 179 | ui_label = "Color 12"; 180 | ui_category = "Custom palette"; 181 | > = float3(119. , 119. , 119. ) / 255.; //Grey 2 182 | 183 | uniform float3 Nostalgia_color_13 < __UNIFORM_COLOR_FLOAT3 184 | ui_label = "Color 13"; 185 | ui_category = "Custom palette"; 186 | > = float3(170. , 255. , 102. ) / 255.; //Lightgreen 187 | 188 | uniform float3 Nostalgia_color_14 < __UNIFORM_COLOR_FLOAT3 189 | ui_label = "Color 14"; 190 | ui_category = "Custom palette"; 191 | > = float3( 0. , 136. , 255. ) / 255.; //Lightblue 192 | 193 | uniform float3 Nostalgia_color_15 < __UNIFORM_COLOR_FLOAT3 194 | ui_label = "Color 15"; 195 | ui_category = "Custom palette"; 196 | > = float3(187. , 187. , 187. ) / 255.; //Grey 3 197 | 198 | /* 199 | uniform bool Nostalgia_linear //Can't currently make a UI setting for this since I need the preprocessor for that and it does not accept uniforms from the UI 200 | < 201 | ui_label = "Linear"; 202 | //ui_category = "Color options"; 203 | > = 0; 204 | */ 205 | 206 | /*--------------. 207 | | :: Sampler :: | 208 | '--------------*/ 209 | 210 | sampler Linear 211 | { 212 | Texture = ReShade::BackBufferTex; 213 | SRGBTexture = true; 214 | }; 215 | 216 | 217 | /*-------------. 218 | | :: Effect :: | 219 | '-------------*/ 220 | 221 | float3 PS_Nostalgia(float4 vpos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target 222 | { 223 | float3 color; 224 | int colorCount = 16; 225 | 226 | #if Nostalgia_linear == 1 227 | color = tex2D(Linear, texcoord.xy).rgb; 228 | #else 229 | color = tex2D(ReShade::BackBuffer, texcoord.xy).rgb; 230 | #endif 231 | 232 | 233 | if (Nostalgia_color_reduction) 234 | { 235 | float3 palette[16] = //Custom palette 236 | { 237 | Nostalgia_color_0, 238 | Nostalgia_color_1, 239 | Nostalgia_color_2, 240 | Nostalgia_color_3, 241 | Nostalgia_color_4, 242 | Nostalgia_color_5, 243 | Nostalgia_color_6, 244 | Nostalgia_color_7, 245 | Nostalgia_color_8, 246 | Nostalgia_color_9, 247 | Nostalgia_color_10, 248 | Nostalgia_color_11, 249 | Nostalgia_color_12, 250 | Nostalgia_color_13, 251 | Nostalgia_color_14, 252 | Nostalgia_color_15 253 | }; 254 | 255 | if (Nostalgia_palette == 1) //C64 palette from http://www.c64-wiki.com/index.php/Color 256 | { 257 | palette[0] = float3( 0. , 0. , 0. ) / 255.; //Black 258 | palette[1] = float3(255. , 255. , 255. ) / 255.; //White 259 | palette[2] = float3(136. , 0. , 0. ) / 255.; //Red 260 | palette[3] = float3(170. , 255. , 238. ) / 255.; //Cyan 261 | palette[4] = float3(204. , 68. , 204. ) / 255.; //Violet 262 | palette[5] = float3( 0. , 204. , 85. ) / 255.; //Green 263 | palette[6] = float3( 0. , 0. , 170. ) / 255.; //Blue 264 | palette[7] = float3(238. , 238. , 119. ) / 255.; //Yellow 1 265 | palette[8] = float3(221. , 136. , 85. ) / 255.; //Orange 266 | palette[9] = float3(102. , 68. , 0. ) / 255.; //Brown 267 | palette[10] = float3(255. , 119. , 119. ) / 255.; //Yellow 2 268 | palette[11] = float3( 51. , 51. , 51. ) / 255.; //Grey 1 269 | palette[12] = float3(119. , 119. , 119. ) / 255.; //Grey 2 270 | palette[13] = float3(170. , 255. , 102. ) / 255.; //Lightgreen 271 | palette[14] = float3( 0. , 136. , 255. ) / 255.; //Lightblue 272 | palette[15] = float3(187. , 187. , 187. ) / 255.; //Grey 3 273 | } 274 | 275 | if (Nostalgia_palette == 2) //EGA palette 276 | { 277 | palette[0] = float3(0.0, 0.0, 0.0 ); //Black 278 | palette[1] = float3(0.0, 0.0, 0.666667); //Blue 279 | palette[2] = float3(0.0, 0.666667, 0.0 ); //Green 280 | palette[3] = float3(0.0, 0.666667, 0.666667); //Cyan 281 | palette[4] = float3(0.666667, 0.0, 0.0 ); //Red 282 | palette[5] = float3(0.666667, 0.0, 0.666667); //Magenta 283 | palette[6] = float3(0.666667, 0.333333, 0.0 ); //Brown 284 | palette[7] = float3(0.666667, 0.666667, 0.666667); //Light gray 285 | palette[8] = float3(0.333333, 0.333333, 0.333333); //Dark gray 286 | palette[9] = float3(0.333333, 0.333333, 1.0 ); //Bright blue 287 | palette[10] = float3(0.333333, 1.0, 0.333333); //Bright green 288 | palette[11] = float3(0.333333, 1.0, 1.0 ); //Bright cyan 289 | palette[12] = float3(1.0, 0.333333, 0.333333); //Bright red 290 | palette[13] = float3(1.0, 0.333333, 1.0 ); //Bright magenta 291 | palette[14] = float3(1.0, 1.0, 0.333333); //Bright yellow 292 | palette[15] = float3(1.0, 1.0, 1.0 ); //White 293 | } 294 | 295 | if (Nostalgia_palette == 3) //IBMPC palette 296 | { 297 | palette[0] = float3(0,0,0); 298 | palette[1] = float3(0,0,0.8); 299 | palette[2] = float3(0,0.6,0); 300 | palette[3] = float3(0,0.6,0.8); 301 | palette[4] = float3(0.8,0,0); 302 | palette[5] = float3(0.8,0,0.8); 303 | palette[6] = float3(0.8,0.6,0); 304 | palette[7] = float3(0.8,0.8,0.8); 305 | palette[8] = float3(0.4,0.4,0.4); 306 | palette[9] = float3(0.4,0.4,1); 307 | palette[10] = float3(0.4,1,0.4); 308 | palette[11] = float3(0.4,1,1); 309 | palette[12] = float3(0.99,0.4,0.4); 310 | palette[13] = float3(1,0.4,1); 311 | palette[14] = float3(1,1,0.4); 312 | palette[15] = float3(1,1,1); 313 | } 314 | 315 | if (Nostalgia_palette == 4) //ZX Spectrum palette 316 | { 317 | palette[0] = float3(0,0,0); 318 | palette[1] = float3(0,0,0.811764705882353); 319 | palette[2] = float3(0,0.811764705882353,0); 320 | palette[3] = float3(0,0.811764705882353,0.811764705882353); 321 | palette[4] = float3(0.811764705882353,0,0); 322 | palette[5] = float3(0.811764705882353,0,0.752941176470588); 323 | palette[6] = float3(0.811764705882353,0.811764705882353,0); 324 | palette[7] = float3(0.811764705882353,0.811764705882353,0.811764705882353); 325 | palette[8] = float3(0,0,0); 326 | palette[9] = float3(0,0,1); 327 | palette[10] = float3(0,1,0); 328 | palette[11] = float3(0,1,1); 329 | palette[12] = float3(1,0,0); 330 | palette[13] = float3(1,0,1); 331 | palette[14] = float3(1,1,0); 332 | palette[15] = float3(1,1,1); 333 | } 334 | 335 | if (Nostalgia_palette == 5) //AppleII palette 336 | { 337 | palette[0] = float3(0,0,0); 338 | palette[1] = float3(0.890196078431373,0.117647058823529,0.376470588235294); 339 | palette[2] = float3(0.376470588235294,0.305882352941176,0.741176470588235); 340 | palette[3] = float3(1,0.266666666666667,0.992156862745098); 341 | palette[4] = float3(0,0.63921568627451,0.376470588235294); 342 | palette[5] = float3(0.611764705882353,0.611764705882353,0.611764705882353); 343 | palette[6] = float3(0.0784313725490196,0.811764705882353,0.992156862745098); 344 | palette[7] = float3(0.815686274509804,0.764705882352941,1); 345 | palette[8] = float3(0.376470588235294,0.447058823529412,0.0117647058823529); 346 | palette[9] = float3(1,0.415686274509804,0.235294117647059); 347 | palette[10] = float3(0.611764705882353,0.611764705882353,0.611764705882353); 348 | palette[11] = float3(1,0.627450980392157,0.815686274509804); 349 | palette[12] = float3(0.0784313725490196,0.96078431372549,0.235294117647059); 350 | palette[13] = float3(0.815686274509804,0.866666666666667,0.552941176470588); 351 | palette[14] = float3(0.447058823529412,1,0.815686274509804); 352 | palette[15] = float3(1,1,1); 353 | } 354 | 355 | if (Nostalgia_palette == 6) //NTSC palette 356 | { 357 | palette[0] = float3(0.831372549019608,0.831372549019608,0.831372549019608); 358 | palette[1] = float3(0.866666666666667,0.776470588235294,0.474509803921569); 359 | palette[2] = float3(0.0392156862745098,0.96078431372549,0.776470588235294); 360 | palette[3] = float3(0.0470588235294118,0.917647058823529,0.380392156862745); 361 | palette[4] = float3(1,0.156862745098039,0.709803921568627); 362 | palette[5] = float3(1,0.109803921568627,0.298039215686275); 363 | palette[6] = float3(0.149019607843137,0.254901960784314,0.607843137254902); 364 | palette[7] = float3(0,0.87843137254902,0.905882352941176); 365 | palette[8] = float3(1,1,1); 366 | palette[9] = float3(1,0.317647058823529,1); 367 | palette[10] = float3(0.16078431372549,0.16078431372549,0.16078431372549); 368 | palette[11] = float3(0.16078431372549,0.16078431372549,0.16078431372549); 369 | palette[12] = float3(0.16078431372549,0.16078431372549,0.16078431372549); 370 | palette[13] = float3(0.831372549019608,0.831372549019608,0.831372549019608); 371 | palette[14] = float3(0.866666666666667,0.776470588235294,0.474509803921569); 372 | palette[15] = float3(0.0392156862745098,0.96078431372549,0.776470588235294); 373 | } 374 | 375 | if (Nostalgia_palette == 7) // Commodore VIC-20 376 | { 377 | palette[0] = float3(0,0,0); 378 | palette[1] = float3(1,1,1); 379 | palette[2] = float3(0.470588235294118,0.16078431372549,0.133333333333333); 380 | palette[3] = float3(0.529411764705882,0.83921568627451,0.866666666666667); 381 | palette[4] = float3(0.666666666666667,0.372549019607843,0.713725490196078); 382 | palette[5] = float3(0.101960784313725,0.509803921568627,0.149019607843137); 383 | palette[6] = float3(0.250980392156863,0.192156862745098,0.552941176470588); 384 | palette[7] = float3(0.749019607843137,0.807843137254902,0.447058823529412); 385 | palette[8] = float3(0.666666666666667,0.454901960784314,0.286274509803922); 386 | palette[9] = float3(0.917647058823529,0.705882352941177,0.537254901960784); 387 | palette[10] = float3(0.72156862745098,0.411764705882353,0.384313725490196); 388 | palette[11] = float3(0.780392156862745,1,1); 389 | palette[12] = float3(0.917647058823529,0.623529411764706,0.964705882352941); 390 | palette[13] = float3(0.580392156862745,0.87843137254902,0.537254901960784); 391 | palette[14] = float3(0.501960784313725,0.443137254901961,0.8); 392 | palette[15] = float3(1,1,0.698039215686274); 393 | } 394 | 395 | if (Nostalgia_palette == 8) // MSX Systems 396 | { 397 | palette[0] = float3(0,0,0); 398 | palette[1] = float3(1,1,1); 399 | palette[2] = float3(0.243137254901961,0.72156862745098,0.286274509803922); 400 | palette[3] = float3(0.454901960784314,0.815686274509804,0.490196078431373); 401 | palette[4] = float3(0.349019607843137,0.333333333333333,0.87843137254902); 402 | palette[5] = float3(0.501960784313725,0.462745098039216,0.945098039215686); 403 | palette[6] = float3(0.725490196078431,0.368627450980392,0.317647058823529); 404 | palette[7] = float3(0.396078431372549,0.858823529411765,0.937254901960784); 405 | palette[8] = float3(0.858823529411765,0.396078431372549,0.349019607843137); 406 | palette[9] = float3(1,0.537254901960784,0.490196078431373); 407 | palette[10] = float3(0.8,0.764705882352941,0.368627450980392); 408 | palette[11] = float3(0.870588235294118,0.815686274509804,0.529411764705882); 409 | palette[12] = float3(0.227450980392157,0.635294117647059,0.254901960784314); 410 | palette[13] = float3(0.717647058823529,0.4,0.709803921568627); 411 | palette[14] = float3(0.8,0.8,0.8); 412 | palette[15] = float3(1,1,0.698039215686274); 413 | } 414 | 415 | if (Nostalgia_palette == 9) // Thomson MO5 416 | { 417 | palette[0] = float3(0,0,0); 418 | palette[1] = float3(1,1,1); 419 | palette[2] = float3(1,0,0); 420 | palette[3] = float3(0,1,0); 421 | palette[4] = float3(1,1,0); 422 | palette[5] = float3(0,0,1); 423 | palette[6] = float3(1,0,1); 424 | palette[7] = float3(0,1,1); 425 | palette[8] = float3(0,0,0); 426 | palette[9] = float3(0.733333333333333,0.733333333333333,0.733333333333333); 427 | palette[10] = float3(0.866666666666667,0.466666666666667,0.466666666666667); 428 | palette[11] = float3(0.466666666666667,0.866666666666667,0.466666666666667); 429 | palette[12] = float3(0.866666666666667,0.866666666666667,0.466666666666667); 430 | palette[13] = float3(0.466666666666667,0.466666666666667,0.866666666666667); 431 | palette[14] = float3(0.866666666666667,0.466666666666667,0.933333333333333); 432 | palette[15] = float3(0.733333333333333,1,1); 433 | } 434 | 435 | if (Nostalgia_palette == 10) // Amstrad CPC 436 | { 437 | palette[0] = float3(0,0,0); 438 | palette[1] = float3(1,1,1); 439 | palette[2] = float3(0,0,0.498039215686275); 440 | palette[3] = float3(0.498039215686275,0,0); 441 | palette[4] = float3(0.498039215686275,0,0.498039215686275); 442 | palette[5] = float3(0,0.498039215686275,0); 443 | palette[6] = float3(1,0,0); 444 | palette[7] = float3(0,0.498039215686275,0.498039215686275); 445 | palette[8] = float3(0.498039215686275,0.498039215686275,0); 446 | palette[9] = float3(0.498039215686275,0.498039215686275,0.498039215686275); 447 | palette[10] = float3(0.498039215686275,0.498039215686275,1); 448 | palette[11] = float3(1,0.498039215686275,0); 449 | palette[12] = float3(1,0.498039215686275,0.498039215686275); 450 | palette[13] = float3(0.498039215686275,1,0.498039215686275); 451 | palette[14] = float3(0.498039215686275,1,1); 452 | palette[15] = float3(1,1,0.498039215686275); 453 | } 454 | 455 | if (Nostalgia_palette == 11) // Atari ST 456 | { 457 | palette[0] = float3(0,0,0); 458 | palette[1] = float3(1,0.886274509803922,0.882352941176471); 459 | palette[2] = float3(0.376470588235294,0.0392156862745098,0.0117647058823529); 460 | palette[3] = float3(0.811764705882353,0.133333333333333,0.0549019607843137); 461 | palette[4] = float3(0.16078431372549,0.345098039215686,0.0352941176470588); 462 | palette[5] = float3(0.937254901960784,0.16078431372549,0.0705882352941176); 463 | palette[6] = float3(0.356862745098039,0.349019607843137,0.0431372549019608); 464 | palette[7] = float3(0.352941176470588,0.352941176470588,0.352941176470588); 465 | palette[8] = float3(0.803921568627451,0.372549019607843,0.207843137254902); 466 | palette[9] = float3(0.494117647058824,0.509803921568627,0.756862745098039); 467 | palette[10] = float3(0.305882352941176,0.623529411764706,0.0980392156862745); 468 | palette[11] = float3(0.792156862745098,0.509803921568627,0.364705882352941); 469 | palette[12] = float3(1,0.392156862745098,0.215686274509804); 470 | palette[13] = float3(1,0.525490196078431,0.368627450980392); 471 | palette[14] = float3(0.631372549019608,0.63921568627451,0.76078431372549); 472 | palette[15] = float3(1,0.768627450980392,0.517647058823529); 473 | } 474 | 475 | if (Nostalgia_palette == 12) // Mattel Aquarius 476 | { 477 | palette[0] = float3(0,0,0); 478 | palette[1] = float3(1,1,1); 479 | palette[2] = float3(0.494117647058824,0.0980392156862745,0.164705882352941); 480 | palette[3] = float3(0.764705882352941,0,0.105882352941176); 481 | palette[4] = float3(0.725490196078431,0.694117647058824,0.337254901960784); 482 | palette[5] = float3(0.784313725490196,0.725490196078431,0.0274509803921569); 483 | palette[6] = float3(0.231372549019608,0.592156862745098,0.180392156862745); 484 | palette[7] = float3(0.0274509803921569,0.749019607843137,0); 485 | palette[8] = float3(0.250980392156863,0.650980392156863,0.584313725490196); 486 | palette[9] = float3(0,0.776470588235294,0.643137254901961); 487 | palette[10] = float3(0.749019607843137,0.749019607843137,0.749019607843137); 488 | palette[11] = float3(0.513725490196078,0.152941176470588,0.564705882352941); 489 | palette[12] = float3(0.717647058823529,0,0.819607843137255); 490 | palette[13] = float3(0.0196078431372549,0.0509803921568627,0.407843137254902); 491 | colorCount = 14; 492 | } 493 | 494 | if (Nostalgia_palette == 13) // Gameboy 495 | { 496 | palette[0] = float3(0.0588235294117647,0.219607843137255,0.0588235294117647); 497 | palette[1] = float3(0.607843137254902,0.737254901960784,0.0588235294117647); 498 | palette[2] = float3(0.188235294117647,0.384313725490196,0.188235294117647); 499 | palette[3] = float3(0.545098039215686,0.674509803921569,0.0588235294117647); 500 | colorCount = 4; 501 | } 502 | 503 | 504 | if (Nostalgia_palette == 14) //aek16 ( http://eastfarthing.com/blog/2016-05-06-palette/ ) 505 | { 506 | palette[0] = float3(0.247059, 0.196078, 0.682353); // 507 | palette[1] = float3(0.890196, 0.054902, 0.760784); // 508 | palette[2] = float3(0.729412, 0.666667, 1.000000); // 509 | palette[3] = float3(1., 1.000000, 1. ); //White 510 | palette[4] = float3(1.000000, 0.580392, 0.615686); // 511 | palette[5] = float3(0.909804, 0.007843, 0.000000); // 512 | palette[6] = float3(0.478431, 0.141176, 0.239216); // 513 | palette[7] = float3(0., 0. , 0. ); //Black 514 | palette[8] = float3(0.098039, 0.337255, 0.282353); // 515 | palette[9] = float3(0.415686, 0.537255, 0.152941); // 516 | palette[10] = float3(0.086275, 0.929412, 0.458824); // 517 | palette[11] = float3(0.196078, 0.756863, 0.764706); // 518 | palette[12] = float3(0.019608, 0.498039, 0.756863); // 519 | palette[13] = float3(0.431373, 0.305882, 0.137255); // 520 | palette[14] = float3(0.937255, 0.890196, 0.019608); // 521 | palette[15] = float3(0.788235, 0.560784, 0.298039); // 522 | } 523 | 524 | // :: Dither :: // 525 | 526 | if (Nostalgia_dither == 1) //aek16 ( http://eastfarthing.com/blog/2016-05-06-palette/ ) 527 | { 528 | 529 | //Calculate grid position 530 | float grid_position = frac(dot(texcoord, BUFFER_SCREEN_SIZE * 0.5) + 0.25); //returns 0.25 and 0.75 531 | 532 | //Calculate how big the shift should be 533 | float dither_shift = (0.25) * (1.0 / (pow(2,2.0) - 1.0)); // 0.25 seems good both when using math and when eyeballing it. So does 0.75 btw. 534 | 535 | //Shift the individual colors differently, thus making it even harder to see the dithering pattern 536 | float3 dither_shift_RGB = float3(dither_shift, dither_shift, dither_shift); //dithering 537 | 538 | //modify shift acording to grid position. 539 | dither_shift_RGB = lerp(2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position); //shift acording to grid position. 540 | 541 | //shift the color by dither_shift 542 | //color.rgb += lerp(2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position); //shift acording to grid position. 543 | color.rgb += dither_shift_RGB; 544 | } 545 | 546 | // :: Color matching :: // 547 | 548 | float3 diff = color - palette[0]; //find the difference in color compared to color 0 549 | 550 | float dist = dot(diff,diff); //squared distance of difference - we don't need to calculate the square root of this 551 | 552 | float closest_dist = dist; //this has to be the closest distance so far as it's the first we have checked 553 | float3 closest_color = palette[0]; //and closest color so far is this one 554 | 555 | for (int i = 1 ; i < colorCount ; i++) //for colors 1 to colorCount 556 | { 557 | diff = color - palette[i]; //find the difference in color 558 | 559 | dist = dot(diff,diff); //squared distance of difference - we don't need to calculate the square root of this 560 | 561 | if (dist < closest_dist) //is the distance closer than the previously closest distance? 562 | { 563 | closest_dist = dist; //closest distance is now this distance 564 | closest_color = palette[i]; //closest color is now this color 565 | } 566 | } 567 | 568 | color = closest_color; //return the pixel 569 | } 570 | 571 | if (Nostalgia_scanlines == 1) 572 | { 573 | color *= frac(texcoord.y * (BUFFER_HEIGHT * 0.5)) + 0.5; //Scanlines 574 | } 575 | if (Nostalgia_scanlines == 2) 576 | { 577 | float grey = dot(color,float(1.0/3.0)); 578 | color = (frac(texcoord.y * (BUFFER_HEIGHT * 0.5)) < 0.25) ? color : color * ((-grey*grey+grey+grey) * 0.5 + 0.5); 579 | } 580 | 581 | return color; //return the pixel 582 | } 583 | 584 | 585 | /*----------------. 586 | | :: Technique :: | 587 | '----------------*/ 588 | 589 | technique Nostalgia 590 | { 591 | pass NostalgiaPass 592 | { 593 | VertexShader = PostProcessVS; 594 | PixelShader = PS_Nostalgia; 595 | 596 | #if Nostalgia_linear == 1 597 | SRGBWriteEnable = true; 598 | #endif 599 | 600 | ClearRenderTargets = false; 601 | } 602 | } 603 | -------------------------------------------------------------------------------- /Shaders/SMAA.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * _______ ___ ___ ___ ___ 3 | * / || \/ | / \ / \ 4 | * | (---- | \ / | / ^ \ / ^ \ 5 | * \ \ | |\/| | / /_\ \ / /_\ \ 6 | * ----) | | | | | / _____ \ / _____ \ 7 | * |_______/ |__| |__| /__/ \__\ /__/ \__\ 8 | * 9 | * E N H A N C E D 10 | * S U B P I X E L M O R P H O L O G I C A L A N T I A L I A S I N G 11 | * 12 | * for ReShade 3.0+ 13 | */ 14 | 15 | //------------------- Preprocessor Settings ------------------- 16 | 17 | #if !defined(SMAA_PRESET_LOW) && !defined(SMAA_PRESET_MEDIUM) && !defined(SMAA_PRESET_HIGH) && !defined(SMAA_PRESET_ULTRA) 18 | #define SMAA_PRESET_CUSTOM // Do not use a quality preset by default 19 | #endif 20 | 21 | //----------------------- UI Variables ------------------------ 22 | 23 | #include "ReShadeUI.fxh" 24 | 25 | uniform int EdgeDetectionType < __UNIFORM_COMBO_INT1 26 | ui_items = "Luminance edge detection\0Color edge detection\0Depth edge detection\0"; 27 | ui_label = "Edge Detection Type"; 28 | > = 1; 29 | 30 | #ifdef SMAA_PRESET_CUSTOM 31 | uniform float EdgeDetectionThreshold < __UNIFORM_DRAG_FLOAT1 32 | ui_min = 0.05; ui_max = 0.20; ui_step = 0.001; 33 | ui_tooltip = "Edge detection threshold. If SMAA misses some edges try lowering this slightly."; 34 | ui_label = "Edge Detection Threshold"; 35 | > = 0.10; 36 | 37 | uniform float DepthEdgeDetectionThreshold < __UNIFORM_DRAG_FLOAT1 38 | ui_min = 0.001; ui_max = 0.10; ui_step = 0.001; 39 | ui_tooltip = "Depth Edge detection threshold. If SMAA misses some edges try lowering this slightly."; 40 | ui_label = "Depth Edge Detection Threshold"; 41 | > = 0.01; 42 | 43 | uniform int MaxSearchSteps < __UNIFORM_SLIDER_INT1 44 | ui_min = 0; ui_max = 112; 45 | ui_label = "Max Search Steps"; 46 | ui_tooltip = "Determines the radius SMAA will search for aliased edges."; 47 | > = 32; 48 | 49 | uniform int MaxSearchStepsDiagonal < __UNIFORM_SLIDER_INT1 50 | ui_min = 0; ui_max = 20; 51 | ui_label = "Max Search Steps Diagonal"; 52 | ui_tooltip = "Determines the radius SMAA will search for diagonal aliased edges"; 53 | > = 16; 54 | 55 | uniform int CornerRounding < __UNIFORM_SLIDER_INT1 56 | ui_min = 0; ui_max = 100; 57 | ui_label = "Corner Rounding"; 58 | ui_tooltip = "Determines the percent of anti-aliasing to apply to corners."; 59 | > = 25; 60 | 61 | uniform bool PredicationEnabled < __UNIFORM_INPUT_BOOL1 62 | ui_label = "Enable Predicated Thresholding"; 63 | > = false; 64 | 65 | uniform float PredicationThreshold < __UNIFORM_DRAG_FLOAT1 66 | ui_min = 0.005; ui_max = 1.00; ui_step = 0.01; 67 | ui_tooltip = "Threshold to be used in the additional predication buffer."; 68 | ui_label = "Predication Threshold"; 69 | > = 0.01; 70 | 71 | uniform float PredicationScale < __UNIFORM_SLIDER_FLOAT1 72 | ui_min = 1; ui_max = 8; 73 | ui_tooltip = "How much to scale the global threshold used for luma or color edge."; 74 | ui_label = "Predication Scale"; 75 | > = 2.0; 76 | 77 | uniform float PredicationStrength < __UNIFORM_SLIDER_FLOAT1 78 | ui_min = 0; ui_max = 4; 79 | ui_tooltip = "How much to locally decrease the threshold."; 80 | ui_label = "Predication Strength"; 81 | > = 0.4; 82 | #endif 83 | 84 | uniform int DebugOutput < __UNIFORM_COMBO_INT1 85 | ui_items = "None\0View edges\0View weights\0"; 86 | ui_label = "Debug Output"; 87 | > = false; 88 | 89 | #ifdef SMAA_PRESET_CUSTOM 90 | #define SMAA_PREDICATION PredicationEnabled 91 | #define SMAA_THRESHOLD EdgeDetectionThreshold 92 | #define SMAA_DEPTH_THRESHOLD DepthEdgeDetectionThreshold 93 | #define SMAA_MAX_SEARCH_STEPS MaxSearchSteps 94 | #define SMAA_MAX_SEARCH_STEPS_DIAG MaxSearchStepsDiagonal 95 | #define SMAA_CORNER_ROUNDING CornerRounding 96 | #define SMAA_PREDICATION_THRESHOLD PredicationThreshold 97 | #define SMAA_PREDICATION_SCALE PredicationScale 98 | #define SMAA_PREDICATION_STRENGTH PredicationStrength 99 | #endif 100 | 101 | #define SMAA_RT_METRICS float4(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT, BUFFER_WIDTH, BUFFER_HEIGHT) 102 | #define SMAA_CUSTOM_SL 1 103 | 104 | #define SMAATexture2D(tex) sampler tex 105 | #define SMAATexturePass2D(tex) tex 106 | #define SMAASampleLevelZero(tex, coord) tex2Dlod(tex, float4(coord, coord)) 107 | #define SMAASampleLevelZeroPoint(tex, coord) SMAASampleLevelZero(tex, coord) 108 | #define SMAASampleLevelZeroOffset(tex, coord, offset) tex2Dlodoffset(tex, float4(coord, coord), offset) 109 | #define SMAASample(tex, coord) tex2D(tex, coord) 110 | #define SMAASamplePoint(tex, coord) SMAASample(tex, coord) 111 | #define SMAASampleOffset(tex, coord, offset) tex2Doffset(tex, coord, offset) 112 | #define SMAA_BRANCH [branch] 113 | #define SMAA_FLATTEN [flatten] 114 | 115 | #if (__RENDERER__ == 0xb000 || __RENDERER__ == 0xb100) 116 | #define SMAAGather(tex, coord) tex2Dgather(tex, coord, 0) 117 | #endif 118 | 119 | #include "SMAA.fxh" 120 | #include "ReShade.fxh" 121 | 122 | // Textures 123 | 124 | texture depthTex < pooled = true; > 125 | { 126 | Width = BUFFER_WIDTH; 127 | Height = BUFFER_HEIGHT; 128 | Format = R16F; 129 | }; 130 | 131 | texture edgesTex < pooled = true; > 132 | { 133 | Width = BUFFER_WIDTH; 134 | Height = BUFFER_HEIGHT; 135 | Format = RG8; 136 | }; 137 | texture blendTex < pooled = true; > 138 | { 139 | Width = BUFFER_WIDTH; 140 | Height = BUFFER_HEIGHT; 141 | Format = RGBA8; 142 | }; 143 | 144 | texture areaTex < source = "AreaTex.png"; > 145 | { 146 | Width = 160; 147 | Height = 560; 148 | Format = RG8; 149 | }; 150 | texture searchTex < source = "SearchTex.png"; > 151 | { 152 | Width = 64; 153 | Height = 16; 154 | Format = R8; 155 | }; 156 | 157 | // Samplers 158 | 159 | sampler depthLinearSampler 160 | { 161 | Texture = depthTex; 162 | }; 163 | 164 | sampler colorGammaSampler 165 | { 166 | Texture = ReShade::BackBufferTex; 167 | AddressU = Clamp; AddressV = Clamp; 168 | MipFilter = Point; MinFilter = Linear; MagFilter = Linear; 169 | SRGBTexture = false; 170 | }; 171 | sampler colorLinearSampler 172 | { 173 | Texture = ReShade::BackBufferTex; 174 | AddressU = Clamp; AddressV = Clamp; 175 | MipFilter = Point; MinFilter = Linear; MagFilter = Linear; 176 | SRGBTexture = true; 177 | }; 178 | sampler edgesSampler 179 | { 180 | Texture = edgesTex; 181 | AddressU = Clamp; AddressV = Clamp; 182 | MipFilter = Linear; MinFilter = Linear; MagFilter = Linear; 183 | SRGBTexture = false; 184 | }; 185 | sampler blendSampler 186 | { 187 | Texture = blendTex; 188 | AddressU = Clamp; AddressV = Clamp; 189 | MipFilter = Linear; MinFilter = Linear; MagFilter = Linear; 190 | SRGBTexture = false; 191 | }; 192 | sampler areaSampler 193 | { 194 | Texture = areaTex; 195 | AddressU = Clamp; AddressV = Clamp; AddressW = Clamp; 196 | MipFilter = Linear; MinFilter = Linear; MagFilter = Linear; 197 | SRGBTexture = false; 198 | }; 199 | sampler searchSampler 200 | { 201 | Texture = searchTex; 202 | AddressU = Clamp; AddressV = Clamp; AddressW = Clamp; 203 | MipFilter = Point; MinFilter = Point; MagFilter = Point; 204 | SRGBTexture = false; 205 | }; 206 | 207 | // Vertex shaders 208 | 209 | void SMAAEdgeDetectionWrapVS( 210 | in uint id : SV_VertexID, 211 | out float4 position : SV_Position, 212 | out float2 texcoord : TEXCOORD0, 213 | out float4 offset[3] : TEXCOORD1) 214 | { 215 | PostProcessVS(id, position, texcoord); 216 | SMAAEdgeDetectionVS(texcoord, offset); 217 | } 218 | void SMAABlendingWeightCalculationWrapVS( 219 | in uint id : SV_VertexID, 220 | out float4 position : SV_Position, 221 | out float2 texcoord : TEXCOORD0, 222 | out float2 pixcoord : TEXCOORD1, 223 | out float4 offset[3] : TEXCOORD2) 224 | { 225 | PostProcessVS(id, position, texcoord); 226 | SMAABlendingWeightCalculationVS(texcoord, pixcoord, offset); 227 | } 228 | void SMAANeighborhoodBlendingWrapVS( 229 | in uint id : SV_VertexID, 230 | out float4 position : SV_Position, 231 | out float2 texcoord : TEXCOORD0, 232 | out float4 offset : TEXCOORD1) 233 | { 234 | PostProcessVS(id, position, texcoord); 235 | SMAANeighborhoodBlendingVS(texcoord, offset); 236 | } 237 | 238 | // Pixel shaders 239 | 240 | float SMAADepthLinearizationPS( 241 | float4 position : SV_Position, 242 | float2 texcoord : TEXCOORD) : SV_Target 243 | { 244 | return ReShade::GetLinearizedDepth(texcoord); 245 | } 246 | 247 | float2 SMAAEdgeDetectionWrapPS( 248 | float4 position : SV_Position, 249 | float2 texcoord : TEXCOORD0, 250 | float4 offset[3] : TEXCOORD1) : SV_Target 251 | { 252 | if (EdgeDetectionType == 0 && SMAA_PREDICATION == true) 253 | return SMAALumaEdgePredicationDetectionPS(texcoord, offset, colorGammaSampler, depthLinearSampler); 254 | else if (EdgeDetectionType == 0) 255 | return SMAALumaEdgeDetectionPS(texcoord, offset, colorGammaSampler); 256 | 257 | if (EdgeDetectionType == 2) 258 | return SMAADepthEdgeDetectionPS(texcoord, offset, depthLinearSampler); 259 | 260 | if (SMAA_PREDICATION) 261 | return SMAAColorEdgePredicationDetectionPS(texcoord, offset, colorGammaSampler, depthLinearSampler); 262 | else 263 | return SMAAColorEdgeDetectionPS(texcoord, offset, colorGammaSampler); 264 | } 265 | float4 SMAABlendingWeightCalculationWrapPS( 266 | float4 position : SV_Position, 267 | float2 texcoord : TEXCOORD0, 268 | float2 pixcoord : TEXCOORD1, 269 | float4 offset[3] : TEXCOORD2) : SV_Target 270 | { 271 | return SMAABlendingWeightCalculationPS(texcoord, pixcoord, offset, edgesSampler, areaSampler, searchSampler, 0.0); 272 | } 273 | 274 | float3 SMAANeighborhoodBlendingWrapPS( 275 | float4 position : SV_Position, 276 | float2 texcoord : TEXCOORD0, 277 | float4 offset : TEXCOORD1) : SV_Target 278 | { 279 | if (DebugOutput == 1) 280 | return tex2D(edgesSampler, texcoord).rgb; 281 | if (DebugOutput == 2) 282 | return tex2D(blendSampler, texcoord).rgb; 283 | 284 | return SMAANeighborhoodBlendingPS(texcoord, offset, colorLinearSampler, blendSampler).rgb; 285 | } 286 | 287 | // Rendering passes 288 | 289 | technique SMAA 290 | { 291 | pass LinearizeDepthPass 292 | { 293 | VertexShader = PostProcessVS; 294 | PixelShader = SMAADepthLinearizationPS; 295 | RenderTarget = depthTex; 296 | } 297 | pass EdgeDetectionPass 298 | { 299 | VertexShader = SMAAEdgeDetectionWrapVS; 300 | PixelShader = SMAAEdgeDetectionWrapPS; 301 | RenderTarget = edgesTex; 302 | ClearRenderTargets = true; 303 | StencilEnable = true; 304 | StencilPass = REPLACE; 305 | StencilRef = 1; 306 | } 307 | pass BlendWeightCalculationPass 308 | { 309 | VertexShader = SMAABlendingWeightCalculationWrapVS; 310 | PixelShader = SMAABlendingWeightCalculationWrapPS; 311 | RenderTarget = blendTex; 312 | ClearRenderTargets = true; 313 | StencilEnable = true; 314 | StencilPass = KEEP; 315 | StencilFunc = EQUAL; 316 | StencilRef = 1; 317 | } 318 | pass NeighborhoodBlendingPass 319 | { 320 | VertexShader = SMAANeighborhoodBlendingWrapVS; 321 | PixelShader = SMAANeighborhoodBlendingWrapPS; 322 | StencilEnable = false; 323 | SRGBWriteEnable = true; 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /Shaders/SMAA.fxh: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2013 Jorge Jimenez (jorge@iryoku.com) 3 | * Copyright (C) 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com) 4 | * Copyright (C) 2013 Belen Masia (bmasia@unizar.es) 5 | * Copyright (C) 2013 Fernando Navarro (fernandn@microsoft.com) 6 | * Copyright (C) 2013 Diego Gutierrez (diegog@unizar.es) 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * this software and associated documentation files (the "Software"), to deal in 10 | * the Software without restriction, including without limitation the rights to 11 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 | * of the Software, and to permit persons to whom the Software is furnished to 13 | * 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. As clarification, there 17 | * is no requirement that the copyright notice and permission be included in 18 | * binary distributions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | 30 | /** 31 | * _______ ___ ___ ___ ___ 32 | * / || \/ | / \ / \ 33 | * | (---- | \ / | / ^ \ / ^ \ 34 | * \ \ | |\/| | / /_\ \ / /_\ \ 35 | * ----) | | | | | / _____ \ / _____ \ 36 | * |_______/ |__| |__| /__/ \__\ /__/ \__\ 37 | * 38 | * E N H A N C E D 39 | * S U B P I X E L M O R P H O L O G I C A L A N T I A L I A S I N G 40 | * 41 | * http://www.iryoku.com/smaa/ 42 | * 43 | * Hi, welcome aboard! 44 | * 45 | * Here you'll find instructions to get the shader up and running as fast as 46 | * possible. 47 | * 48 | * IMPORTANTE NOTICE: when updating, remember to update both this file and the 49 | * precomputed textures! They may change from version to version. 50 | * 51 | * The shader has three passes, chained together as follows: 52 | * 53 | * |input|------------------+ 54 | * v | 55 | * [ SMAA*EdgeDetection ] | 56 | * v | 57 | * |edgesTex| | 58 | * v | 59 | * [ SMAABlendingWeightCalculation ] | 60 | * v | 61 | * |blendTex| | 62 | * v | 63 | * [ SMAANeighborhoodBlending ] <------+ 64 | * v 65 | * |output| 66 | * 67 | * Note that each [pass] has its own vertex and pixel shader. Remember to use 68 | * oversized triangles instead of quads to avoid overshading along the 69 | * diagonal. 70 | * 71 | * You've three edge detection methods to choose from: luma, color or depth. 72 | * They represent different quality/performance and anti-aliasing/sharpness 73 | * tradeoffs, so our recommendation is for you to choose the one that best 74 | * suits your particular scenario: 75 | * 76 | * - Depth edge detection is usually the fastest but it may miss some edges. 77 | * 78 | * - Luma edge detection is usually more expensive than depth edge detection, 79 | * but catches visible edges that depth edge detection can miss. 80 | * 81 | * - Color edge detection is usually the most expensive one but catches 82 | * chroma-only edges. 83 | * 84 | * For quickstarters: just use luma edge detection. 85 | * 86 | * The general advice is to not rush the integration process and ensure each 87 | * step is done correctly (don't try to integrate SMAA T2x with predicated edge 88 | * detection from the start!). Ok then, let's go! 89 | * 90 | * 1. The first step is to create two RGBA temporal render targets for holding 91 | * |edgesTex| and |blendTex|. 92 | * 93 | * In DX10 or DX11, you can use a RG render target for the edges texture. 94 | * In the case of NVIDIA GPUs, using RG render targets seems to actually be 95 | * slower. 96 | * 97 | * On the Xbox 360, you can use the same render target for resolving both 98 | * |edgesTex| and |blendTex|, as they aren't needed simultaneously. 99 | * 100 | * 2. Both temporal render targets |edgesTex| and |blendTex| must be cleared 101 | * each frame. Do not forget to clear the alpha channel! 102 | * 103 | * 3. The next step is loading the two supporting precalculated textures, 104 | * 'areaTex' and 'searchTex'. You'll find them in the 'Textures' folder as 105 | * C++ headers, and also as regular DDS files. They'll be needed for the 106 | * 'SMAABlendingWeightCalculation' pass. 107 | * 108 | * If you use the C++ headers, be sure to load them in the format specified 109 | * inside of them. 110 | * 111 | * You can also compress 'areaTex' and 'searchTex' using BC5 and BC4 112 | * respectively, if you have that option in your content processor pipeline. 113 | * When compressing then, you get a non-perceptible quality decrease, and a 114 | * marginal performance increase. 115 | * 116 | * 4. All samplers must be set to linear filtering and clamp. 117 | * 118 | * After you get the technique working, remember that 64-bit inputs have 119 | * half-rate linear filtering on GCN. 120 | * 121 | * If SMAA is applied to 64-bit color buffers, switching to point filtering 122 | * when accesing them will increase the performance. Search for 123 | * 'SMAASamplePoint' to see which textures may benefit from point 124 | * filtering, and where (which is basically the color input in the edge 125 | * detection and resolve passes). 126 | * 127 | * 5. All texture reads and buffer writes must be non-sRGB, with the exception 128 | * of the input read and the output write in 129 | * 'SMAANeighborhoodBlending' (and only in this pass!). If sRGB reads in 130 | * this last pass are not possible, the technique will work anyway, but 131 | * will perform antialiasing in gamma space. 132 | * 133 | * IMPORTANT: for best results the input read for the color/luma edge 134 | * detection should *NOT* be sRGB. 135 | * 136 | * 6. Before including SMAA.h you'll have to setup the render target metrics, 137 | * the target and any optional configuration defines. Optionally you can 138 | * use a preset. 139 | * 140 | * You have the following targets available: 141 | * SMAA_HLSL_3 142 | * SMAA_HLSL_4 143 | * SMAA_HLSL_4_1 144 | * SMAA_GLSL_3 * 145 | * SMAA_GLSL_4 * 146 | * 147 | * * (See SMAA_INCLUDE_VS and SMAA_INCLUDE_PS below). 148 | * 149 | * And four presets: 150 | * SMAA_PRESET_LOW (%60 of the quality) 151 | * SMAA_PRESET_MEDIUM (%80 of the quality) 152 | * SMAA_PRESET_HIGH (%95 of the quality) 153 | * SMAA_PRESET_ULTRA (%99 of the quality) 154 | * 155 | * For example: 156 | * #define SMAA_RT_METRICS float4(1.0 / 1280.0, 1.0 / 720.0, 1280.0, 720.0) 157 | * #define SMAA_HLSL_4 158 | * #define SMAA_PRESET_HIGH 159 | * #include "SMAA.h" 160 | * 161 | * Note that SMAA_RT_METRICS doesn't need to be a macro, it can be a 162 | * uniform variable. The code is designed to minimize the impact of not 163 | * using a constant value, but it is still better to hardcode it. 164 | * 165 | * Depending on how you encoded 'areaTex' and 'searchTex', you may have to 166 | * add (and customize) the following defines before including SMAA.h: 167 | * #define SMAA_AREATEX_SELECT(sample) sample.rg 168 | * #define SMAA_SEARCHTEX_SELECT(sample) sample.r 169 | * 170 | * If your engine is already using porting macros, you can define 171 | * SMAA_CUSTOM_SL, and define the porting functions by yourself. 172 | * 173 | * 7. Then, you'll have to setup the passes as indicated in the scheme above. 174 | * You can take a look into SMAA.fx, to see how we did it for our demo. 175 | * Checkout the function wrappers, you may want to copy-paste them! 176 | * 177 | * 8. It's recommended to validate the produced |edgesTex| and |blendTex|. 178 | * You can use a screenshot from your engine to compare the |edgesTex| 179 | * and |blendTex| produced inside of the engine with the results obtained 180 | * with the reference demo. 181 | * 182 | * 9. After you get the last pass to work, it's time to optimize. You'll have 183 | * to initialize a stencil buffer in the first pass (discard is already in 184 | * the code), then mask execution by using it the second pass. The last 185 | * pass should be executed in all pixels. 186 | * 187 | * 188 | * After this point you can choose to enable predicated thresholding, 189 | * temporal supersampling and motion blur integration: 190 | * 191 | * a) If you want to use predicated thresholding, take a look into 192 | * SMAA_PREDICATION; you'll need to pass an extra texture in the edge 193 | * detection pass. 194 | * 195 | * b) If you want to enable temporal supersampling (SMAA T2x): 196 | * 197 | * 1. The first step is to render using subpixel jitters. I won't go into 198 | * detail, but it's as simple as moving each vertex position in the 199 | * vertex shader, you can check how we do it in our DX10 demo. 200 | * 201 | * 2. Then, you must setup the temporal resolve. You may want to take a look 202 | * into SMAAResolve for resolving 2x modes. After you get it working, you'll 203 | * probably see ghosting everywhere. But fear not, you can enable the 204 | * CryENGINE temporal reprojection by setting the SMAA_REPROJECTION macro. 205 | * Check out SMAA_DECODE_VELOCITY if your velocity buffer is encoded. 206 | * 207 | * 3. The next step is to apply SMAA to each subpixel jittered frame, just as 208 | * done for 1x. 209 | * 210 | * 4. At this point you should already have something usable, but for best 211 | * results the proper area textures must be set depending on current jitter. 212 | * For this, the parameter 'subsampleIndices' of 213 | * 'SMAABlendingWeightCalculationPS' must be set as follows, for our T2x 214 | * mode: 215 | * 216 | * @SUBSAMPLE_INDICES 217 | * 218 | * | S# | Camera Jitter | subsampleIndices | 219 | * +----+------------------+---------------------+ 220 | * | 0 | ( 0.25, -0.25) | float4(1, 1, 1, 0) | 221 | * | 1 | (-0.25, 0.25) | float4(2, 2, 2, 0) | 222 | * 223 | * These jitter positions assume a bottom-to-top y axis. S# stands for the 224 | * sample number. 225 | * 226 | * More information about temporal supersampling here: 227 | * http://iryoku.com/aacourse/downloads/13-Anti-Aliasing-Methods-in-CryENGINE-3.pdf 228 | * 229 | * c) If you want to enable spatial multisampling (SMAA S2x): 230 | * 231 | * 1. The scene must be rendered using MSAA 2x. The MSAA 2x buffer must be 232 | * created with: 233 | * - DX10: see below (*) 234 | * - DX10.1: D3D10_STANDARD_MULTISAMPLE_PATTERN or 235 | * - DX11: D3D11_STANDARD_MULTISAMPLE_PATTERN 236 | * 237 | * This allows to ensure that the subsample order matches the table in 238 | * @SUBSAMPLE_INDICES. 239 | * 240 | * (*) In the case of DX10, we refer the reader to: 241 | * - SMAA::detectMSAAOrder and 242 | * - SMAA::msaaReorder 243 | * 244 | * These functions allow to match the standard multisample patterns by 245 | * detecting the subsample order for a specific GPU, and reordering 246 | * them appropriately. 247 | * 248 | * 2. A shader must be run to output each subsample into a separate buffer 249 | * (DX10 is required). You can use SMAASeparate for this purpose, or just do 250 | * it in an existing pass (for example, in the tone mapping pass, which has 251 | * the advantage of feeding tone mapped subsamples to SMAA, which will yield 252 | * better results). 253 | * 254 | * 3. The full SMAA 1x pipeline must be run for each separated buffer, storing 255 | * the results in the final buffer. The second run should alpha blend with 256 | * the existing final buffer using a blending factor of 0.5. 257 | * 'subsampleIndices' must be adjusted as in the SMAA T2x case (see point 258 | * b). 259 | * 260 | * d) If you want to enable temporal supersampling on top of SMAA S2x 261 | * (which actually is SMAA 4x): 262 | * 263 | * 1. SMAA 4x consists on temporally jittering SMAA S2x, so the first step is 264 | * to calculate SMAA S2x for current frame. In this case, 'subsampleIndices' 265 | * must be set as follows: 266 | * 267 | * | F# | S# | Camera Jitter | Net Jitter | subsampleIndices | 268 | * +----+----+--------------------+-------------------+----------------------+ 269 | * | 0 | 0 | ( 0.125, 0.125) | ( 0.375, -0.125) | float4(5, 3, 1, 3) | 270 | * | 0 | 1 | ( 0.125, 0.125) | (-0.125, 0.375) | float4(4, 6, 2, 3) | 271 | * +----+----+--------------------+-------------------+----------------------+ 272 | * | 1 | 2 | (-0.125, -0.125) | ( 0.125, -0.375) | float4(3, 5, 1, 4) | 273 | * | 1 | 3 | (-0.125, -0.125) | (-0.375, 0.125) | float4(6, 4, 2, 4) | 274 | * 275 | * These jitter positions assume a bottom-to-top y axis. F# stands for the 276 | * frame number. S# stands for the sample number. 277 | * 278 | * 2. After calculating SMAA S2x for current frame (with the new subsample 279 | * indices), previous frame must be reprojected as in SMAA T2x mode (see 280 | * point b). 281 | * 282 | * e) If motion blur is used, you may want to do the edge detection pass 283 | * together with motion blur. This has two advantages: 284 | * 285 | * 1. Pixels under heavy motion can be omitted from the edge detection process. 286 | * For these pixels we can just store "no edge", as motion blur will take 287 | * care of them. 288 | * 2. The center pixel tap is reused. 289 | * 290 | * Note that in this case depth testing should be used instead of stenciling, 291 | * as we have to write all the pixels in the motion blur pass. 292 | * 293 | * That's it! 294 | */ 295 | 296 | //----------------------------------------------------------------------------- 297 | // SMAA Presets 298 | 299 | /** 300 | * Note that if you use one of these presets, the following configuration 301 | * macros will be ignored if set in the "Configurable Defines" section. 302 | */ 303 | 304 | #if defined(SMAA_PRESET_LOW) 305 | #define SMAA_THRESHOLD 0.15 306 | #define SMAA_MAX_SEARCH_STEPS 4 307 | #define SMAA_DISABLE_DIAG_DETECTION 308 | #define SMAA_DISABLE_CORNER_DETECTION 309 | #elif defined(SMAA_PRESET_MEDIUM) 310 | #define SMAA_THRESHOLD 0.1 311 | #define SMAA_MAX_SEARCH_STEPS 8 312 | #define SMAA_DISABLE_DIAG_DETECTION 313 | #define SMAA_DISABLE_CORNER_DETECTION 314 | #elif defined(SMAA_PRESET_HIGH) 315 | #define SMAA_THRESHOLD 0.1 316 | #define SMAA_MAX_SEARCH_STEPS 16 317 | #define SMAA_MAX_SEARCH_STEPS_DIAG 8 318 | #define SMAA_CORNER_ROUNDING 25 319 | #elif defined(SMAA_PRESET_ULTRA) 320 | #define SMAA_THRESHOLD 0.05 321 | #define SMAA_MAX_SEARCH_STEPS 32 322 | #define SMAA_MAX_SEARCH_STEPS_DIAG 16 323 | #define SMAA_CORNER_ROUNDING 25 324 | #endif 325 | 326 | //----------------------------------------------------------------------------- 327 | // Configurable Defines 328 | 329 | /** 330 | * SMAA_THRESHOLD specifies the threshold or sensitivity to edges. 331 | * Lowering this value you will be able to detect more edges at the expense of 332 | * performance. 333 | * 334 | * Range: [0, 0.5] 335 | * 0.1 is a reasonable value, and allows to catch most visible edges. 336 | * 0.05 is a rather overkill value, that allows to catch 'em all. 337 | * 338 | * If temporal supersampling is used, 0.2 could be a reasonable value, as low 339 | * contrast edges are properly filtered by just 2x. 340 | */ 341 | #ifndef SMAA_THRESHOLD 342 | #define SMAA_THRESHOLD 0.1 343 | #endif 344 | 345 | /** 346 | * SMAA_DEPTH_THRESHOLD specifies the threshold for depth edge detection. 347 | * 348 | * Range: depends on the depth range of the scene. 349 | */ 350 | #ifndef SMAA_DEPTH_THRESHOLD 351 | #define SMAA_DEPTH_THRESHOLD (0.1 * SMAA_THRESHOLD) 352 | #endif 353 | 354 | /** 355 | * SMAA_MAX_SEARCH_STEPS specifies the maximum steps performed in the 356 | * horizontal/vertical pattern searches, at each side of the pixel. 357 | * 358 | * In number of pixels, it's actually the double. So the maximum line length 359 | * perfectly handled by, for example 16, is 64 (by perfectly, we meant that 360 | * longer lines won't look as good, but still antialiased). 361 | * 362 | * Range: [0, 112] 363 | */ 364 | #ifndef SMAA_MAX_SEARCH_STEPS 365 | #define SMAA_MAX_SEARCH_STEPS 16 366 | #endif 367 | 368 | /** 369 | * SMAA_MAX_SEARCH_STEPS_DIAG specifies the maximum steps performed in the 370 | * diagonal pattern searches, at each side of the pixel. In this case we jump 371 | * one pixel at time, instead of two. 372 | * 373 | * Range: [0, 20] 374 | * 375 | * On high-end machines it is cheap (between a 0.8x and 0.9x slower for 16 376 | * steps), but it can have a significant impact on older machines. 377 | * 378 | * Define SMAA_DISABLE_DIAG_DETECTION to disable diagonal processing. 379 | */ 380 | #ifndef SMAA_MAX_SEARCH_STEPS_DIAG 381 | #define SMAA_MAX_SEARCH_STEPS_DIAG 8 382 | #endif 383 | 384 | /** 385 | * SMAA_CORNER_ROUNDING specifies how much sharp corners will be rounded. 386 | * 387 | * Range: [0, 100] 388 | * 389 | * Define SMAA_DISABLE_CORNER_DETECTION to disable corner processing. 390 | */ 391 | #ifndef SMAA_CORNER_ROUNDING 392 | #define SMAA_CORNER_ROUNDING 25 393 | #endif 394 | 395 | /** 396 | * If there is an neighbor edge that has SMAA_LOCAL_CONTRAST_FACTOR times 397 | * bigger contrast than current edge, current edge will be discarded. 398 | * 399 | * This allows to eliminate spurious crossing edges, and is based on the fact 400 | * that, if there is too much contrast in a direction, that will hide 401 | * perceptually contrast in the other neighbors. 402 | */ 403 | #ifndef SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR 404 | #define SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR 2.0 405 | #endif 406 | 407 | /** 408 | * Predicated thresholding allows to better preserve texture details and to 409 | * improve performance, by decreasing the number of detected edges using an 410 | * additional buffer like the light accumulation buffer, object ids or even the 411 | * depth buffer (the depth buffer usage may be limited to indoor or short range 412 | * scenes). 413 | * 414 | * It locally decreases the luma or color threshold if an edge is found in an 415 | * additional buffer (so the global threshold can be higher). 416 | * 417 | * This method was developed by Playstation EDGE MLAA team, and used in 418 | * Killzone 3, by using the light accumulation buffer. More information here: 419 | * http://iryoku.com/aacourse/downloads/06-MLAA-on-PS3.pptx 420 | */ 421 | #ifndef SMAA_PREDICATION 422 | #define SMAA_PREDICATION 0 423 | #endif 424 | 425 | /** 426 | * Threshold to be used in the additional predication buffer. 427 | * 428 | * Range: depends on the input, so you'll have to find the magic number that 429 | * works for you. 430 | */ 431 | #ifndef SMAA_PREDICATION_THRESHOLD 432 | #define SMAA_PREDICATION_THRESHOLD 0.01 433 | #endif 434 | 435 | /** 436 | * How much to scale the global threshold used for luma or color edge 437 | * detection when using predication. 438 | * 439 | * Range: [1, 16] 440 | */ 441 | #ifndef SMAA_PREDICATION_SCALE 442 | #define SMAA_PREDICATION_SCALE 2.0 443 | #endif 444 | 445 | /** 446 | * How much to locally decrease the threshold. 447 | * 448 | * Range: [0, 4] 449 | */ 450 | #ifndef SMAA_PREDICATION_STRENGTH 451 | #define SMAA_PREDICATION_STRENGTH 0.4 452 | #endif 453 | 454 | /** 455 | * Temporal reprojection allows to remove ghosting artifacts when using 456 | * temporal supersampling. We use the CryEngine 3 method which also introduces 457 | * velocity weighting. This feature is of extreme importance for totally 458 | * removing ghosting. More information here: 459 | * http://iryoku.com/aacourse/downloads/13-Anti-Aliasing-Methods-in-CryENGINE-3.pdf 460 | * 461 | * Note that you'll need to setup a velocity buffer for enabling reprojection. 462 | * For static geometry, saving the previous depth buffer is a viable 463 | * alternative. 464 | */ 465 | #ifndef SMAA_REPROJECTION 466 | #define SMAA_REPROJECTION 0 467 | #endif 468 | 469 | /** 470 | * SMAA_REPROJECTION_WEIGHT_SCALE controls the velocity weighting. It allows to 471 | * remove ghosting trails behind the moving object, which are not removed by 472 | * just using reprojection. Using low values will exhibit ghosting, while using 473 | * high values will disable temporal supersampling under motion. 474 | * 475 | * Behind the scenes, velocity weighting removes temporal supersampling when 476 | * the velocity of the subsamples differs (meaning they are different objects). 477 | * 478 | * Range: [0, 80] 479 | */ 480 | #ifndef SMAA_REPROJECTION_WEIGHT_SCALE 481 | #define SMAA_REPROJECTION_WEIGHT_SCALE 30.0 482 | #endif 483 | 484 | /** 485 | * On some compilers, discard cannot be used in vertex shaders. Thus, they need 486 | * to be compiled separately. 487 | */ 488 | #ifndef SMAA_INCLUDE_VS 489 | #define SMAA_INCLUDE_VS 1 490 | #endif 491 | #ifndef SMAA_INCLUDE_PS 492 | #define SMAA_INCLUDE_PS 1 493 | #endif 494 | 495 | //----------------------------------------------------------------------------- 496 | // Texture Access Defines 497 | 498 | #ifndef SMAA_AREATEX_SELECT 499 | #if defined(SMAA_HLSL_3) 500 | #define SMAA_AREATEX_SELECT(sample) sample.ra 501 | #else 502 | #define SMAA_AREATEX_SELECT(sample) sample.rg 503 | #endif 504 | #endif 505 | 506 | #ifndef SMAA_SEARCHTEX_SELECT 507 | #define SMAA_SEARCHTEX_SELECT(sample) sample.r 508 | #endif 509 | 510 | #ifndef SMAA_DECODE_VELOCITY 511 | #define SMAA_DECODE_VELOCITY(sample) sample.rg 512 | #endif 513 | 514 | //----------------------------------------------------------------------------- 515 | // Non-Configurable Defines 516 | 517 | #define SMAA_AREATEX_MAX_DISTANCE 16 518 | #define SMAA_AREATEX_MAX_DISTANCE_DIAG 20 519 | #define SMAA_AREATEX_PIXEL_SIZE (1.0 / float2(160.0, 560.0)) 520 | #define SMAA_AREATEX_SUBTEX_SIZE (1.0 / 7.0) 521 | #define SMAA_SEARCHTEX_SIZE float2(66.0, 33.0) 522 | #define SMAA_SEARCHTEX_PACKED_SIZE float2(64.0, 16.0) 523 | #define SMAA_CORNER_ROUNDING_NORM (float(SMAA_CORNER_ROUNDING) / 100.0) 524 | 525 | //----------------------------------------------------------------------------- 526 | // Porting Functions 527 | 528 | #if defined(SMAA_HLSL_3) 529 | #define SMAATexture2D(tex) sampler2D tex 530 | #define SMAATexturePass2D(tex) tex 531 | #define SMAASampleLevelZero(tex, coord) tex2Dlod(tex, float4(coord, 0.0, 0.0)) 532 | #define SMAASampleLevelZeroPoint(tex, coord) tex2Dlod(tex, float4(coord, 0.0, 0.0)) 533 | #define SMAASampleLevelZeroOffset(tex, coord, offset) tex2Dlod(tex, float4(coord + offset * SMAA_RT_METRICS.xy, 0.0, 0.0)) 534 | #define SMAASample(tex, coord) tex2D(tex, coord) 535 | #define SMAASamplePoint(tex, coord) tex2D(tex, coord) 536 | #define SMAASampleOffset(tex, coord, offset) tex2D(tex, coord + offset * SMAA_RT_METRICS.xy) 537 | #define SMAA_FLATTEN [flatten] 538 | #define SMAA_BRANCH [branch] 539 | #endif 540 | #if defined(SMAA_HLSL_4) || defined(SMAA_HLSL_4_1) 541 | SamplerState LinearSampler { Filter = MIN_MAG_LINEAR_MIP_POINT; AddressU = Clamp; AddressV = Clamp; }; 542 | SamplerState PointSampler { Filter = MIN_MAG_MIP_POINT; AddressU = Clamp; AddressV = Clamp; }; 543 | #define SMAATexture2D(tex) Texture2D tex 544 | #define SMAATexturePass2D(tex) tex 545 | #define SMAASampleLevelZero(tex, coord) tex.SampleLevel(LinearSampler, coord, 0) 546 | #define SMAASampleLevelZeroPoint(tex, coord) tex.SampleLevel(PointSampler, coord, 0) 547 | #define SMAASampleLevelZeroOffset(tex, coord, offset) tex.SampleLevel(LinearSampler, coord, 0, offset) 548 | #define SMAASample(tex, coord) tex.Sample(LinearSampler, coord) 549 | #define SMAASamplePoint(tex, coord) tex.Sample(PointSampler, coord) 550 | #define SMAASampleOffset(tex, coord, offset) tex.Sample(LinearSampler, coord, offset) 551 | #define SMAA_FLATTEN [flatten] 552 | #define SMAA_BRANCH [branch] 553 | #define SMAATexture2DMS2(tex) Texture2DMS tex 554 | #define SMAALoad(tex, pos, sample) tex.Load(pos, sample) 555 | #if defined(SMAA_HLSL_4_1) 556 | #define SMAAGather(tex, coord) tex.Gather(LinearSampler, coord, 0) 557 | #endif 558 | #endif 559 | #if defined(SMAA_GLSL_3) || defined(SMAA_GLSL_4) 560 | #define SMAATexture2D(tex) sampler2D tex 561 | #define SMAATexturePass2D(tex) tex 562 | #define SMAASampleLevelZero(tex, coord) textureLod(tex, coord, 0.0) 563 | #define SMAASampleLevelZeroPoint(tex, coord) textureLod(tex, coord, 0.0) 564 | #define SMAASampleLevelZeroOffset(tex, coord, offset) textureLodOffset(tex, coord, 0.0, offset) 565 | #define SMAASample(tex, coord) texture(tex, coord) 566 | #define SMAASamplePoint(tex, coord) texture(tex, coord) 567 | #define SMAASampleOffset(tex, coord, offset) texture(tex, coord, offset) 568 | #define SMAA_FLATTEN 569 | #define SMAA_BRANCH 570 | #define lerp(a, b, t) mix(a, b, t) 571 | #define saturate(a) clamp(a, 0.0, 1.0) 572 | #if defined(SMAA_GLSL_4) 573 | #define mad(a, b, c) fma(a, b, c) 574 | #define SMAAGather(tex, coord) textureGather(tex, coord) 575 | #else 576 | #define mad(a, b, c) (a * b + c) 577 | #endif 578 | #define float2 vec2 579 | #define float3 vec3 580 | #define float4 vec4 581 | #define int2 ivec2 582 | #define int3 ivec3 583 | #define int4 ivec4 584 | #define bool2 bvec2 585 | #define bool3 bvec3 586 | #define bool4 bvec4 587 | #endif 588 | 589 | #if !defined(SMAA_HLSL_3) && !defined(SMAA_HLSL_4) && !defined(SMAA_HLSL_4_1) && !defined(SMAA_GLSL_3) && !defined(SMAA_GLSL_4) && !defined(SMAA_CUSTOM_SL) 590 | #error you must define the shading language: SMAA_HLSL_*, SMAA_GLSL_* or SMAA_CUSTOM_SL 591 | #endif 592 | 593 | //----------------------------------------------------------------------------- 594 | // Misc functions 595 | 596 | /** 597 | * Gathers current pixel, and the top-left neighbors. 598 | */ 599 | float3 SMAAGatherNeighbours(float2 texcoord, 600 | float4 offset[3], 601 | SMAATexture2D(tex)) { 602 | #ifdef SMAAGather 603 | return SMAAGather(tex, texcoord + SMAA_RT_METRICS.xy * float2(-0.5, -0.5)).grb; 604 | #else 605 | float P = SMAASamplePoint(tex, texcoord).r; 606 | float Pleft = SMAASamplePoint(tex, offset[0].xy).r; 607 | float Ptop = SMAASamplePoint(tex, offset[0].zw).r; 608 | return float3(P, Pleft, Ptop); 609 | #endif 610 | } 611 | 612 | /** 613 | * Adjusts the threshold by means of predication. 614 | */ 615 | float2 SMAACalculatePredicatedThreshold(float2 texcoord, 616 | float4 offset[3], 617 | SMAATexture2D(predicationTex)) { 618 | float3 neighbours = SMAAGatherNeighbours(texcoord, offset, SMAATexturePass2D(predicationTex)); 619 | float2 delta = abs(neighbours.xx - neighbours.yz); 620 | float2 edges = step(SMAA_PREDICATION_THRESHOLD, delta); 621 | return SMAA_PREDICATION_SCALE * SMAA_THRESHOLD * (1.0 - SMAA_PREDICATION_STRENGTH * edges); 622 | } 623 | 624 | /** 625 | * Conditional move: 626 | */ 627 | void SMAAMovc(bool2 cond, inout float2 variable, float2 value) { 628 | SMAA_FLATTEN if (cond.x) variable.x = value.x; 629 | SMAA_FLATTEN if (cond.y) variable.y = value.y; 630 | } 631 | 632 | void SMAAMovc(bool4 cond, inout float4 variable, float4 value) { 633 | SMAAMovc(cond.xy, variable.xy, value.xy); 634 | SMAAMovc(cond.zw, variable.zw, value.zw); 635 | } 636 | 637 | 638 | #if SMAA_INCLUDE_VS 639 | //----------------------------------------------------------------------------- 640 | // Vertex Shaders 641 | 642 | /** 643 | * Edge Detection Vertex Shader 644 | */ 645 | void SMAAEdgeDetectionVS(float2 texcoord, 646 | out float4 offset[3]) { 647 | offset[0] = mad(SMAA_RT_METRICS.xyxy, float4(-1.0, 0.0, 0.0, -1.0), texcoord.xyxy); 648 | offset[1] = mad(SMAA_RT_METRICS.xyxy, float4( 1.0, 0.0, 0.0, 1.0), texcoord.xyxy); 649 | offset[2] = mad(SMAA_RT_METRICS.xyxy, float4(-2.0, 0.0, 0.0, -2.0), texcoord.xyxy); 650 | } 651 | 652 | /** 653 | * Blend Weight Calculation Vertex Shader 654 | */ 655 | void SMAABlendingWeightCalculationVS(float2 texcoord, 656 | out float2 pixcoord, 657 | out float4 offset[3]) { 658 | pixcoord = texcoord * SMAA_RT_METRICS.zw; 659 | 660 | // We will use these offsets for the searches later on (see @PSEUDO_GATHER4): 661 | offset[0] = mad(SMAA_RT_METRICS.xyxy, float4(-0.25, -0.125, 1.25, -0.125), texcoord.xyxy); 662 | offset[1] = mad(SMAA_RT_METRICS.xyxy, float4(-0.125, -0.25, -0.125, 1.25), texcoord.xyxy); 663 | 664 | // And these for the searches, they indicate the ends of the loops: 665 | offset[2] = mad(SMAA_RT_METRICS.xxyy, 666 | float4(-2.0, 2.0, -2.0, 2.0) * float(SMAA_MAX_SEARCH_STEPS), 667 | float4(offset[0].xz, offset[1].yw)); 668 | } 669 | 670 | /** 671 | * Neighborhood Blending Vertex Shader 672 | */ 673 | void SMAANeighborhoodBlendingVS(float2 texcoord, 674 | out float4 offset) { 675 | offset = mad(SMAA_RT_METRICS.xyxy, float4( 1.0, 0.0, 0.0, 1.0), texcoord.xyxy); 676 | } 677 | #endif // SMAA_INCLUDE_VS 678 | 679 | #if SMAA_INCLUDE_PS 680 | //----------------------------------------------------------------------------- 681 | // Edge Detection Pixel Shaders (First Pass) 682 | 683 | /** 684 | * Luma Edge Detection 685 | * 686 | * IMPORTANT NOTICE: luma edge detection requires gamma-corrected colors, and 687 | * thus 'colorTex' should be a non-sRGB texture. 688 | */ 689 | float2 SMAALumaEdgeDetectionPS(float2 texcoord, 690 | float4 offset[3], 691 | SMAATexture2D(colorTex) 692 | ) { 693 | // Calculate the threshold: 694 | float2 threshold = float2(SMAA_THRESHOLD, SMAA_THRESHOLD); 695 | 696 | // Calculate lumas: 697 | float3 weights = float3(0.2126, 0.7152, 0.0722); 698 | float L = dot(SMAASamplePoint(colorTex, texcoord).rgb, weights); 699 | 700 | float Lleft = dot(SMAASamplePoint(colorTex, offset[0].xy).rgb, weights); 701 | float Ltop = dot(SMAASamplePoint(colorTex, offset[0].zw).rgb, weights); 702 | 703 | // We do the usual threshold: 704 | float4 delta; 705 | delta.xy = abs(L - float2(Lleft, Ltop)); 706 | float2 edges = step(threshold, delta.xy); 707 | 708 | // Then discard if there is no edge: 709 | if (dot(edges, float2(1.0, 1.0)) == 0.0) 710 | discard; 711 | 712 | // Calculate right and bottom deltas: 713 | float Lright = dot(SMAASamplePoint(colorTex, offset[1].xy).rgb, weights); 714 | float Lbottom = dot(SMAASamplePoint(colorTex, offset[1].zw).rgb, weights); 715 | delta.zw = abs(L - float2(Lright, Lbottom)); 716 | 717 | // Calculate the maximum delta in the direct neighborhood: 718 | float2 maxDelta = max(delta.xy, delta.zw); 719 | 720 | // Calculate left-left and top-top deltas: 721 | float Lleftleft = dot(SMAASamplePoint(colorTex, offset[2].xy).rgb, weights); 722 | float Ltoptop = dot(SMAASamplePoint(colorTex, offset[2].zw).rgb, weights); 723 | delta.zw = abs(float2(Lleft, Ltop) - float2(Lleftleft, Ltoptop)); 724 | 725 | // Calculate the final maximum delta: 726 | maxDelta = max(maxDelta.xy, delta.zw); 727 | float finalDelta = max(maxDelta.x, maxDelta.y); 728 | 729 | // Local contrast adaptation: 730 | edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy); 731 | 732 | return edges; 733 | } 734 | 735 | float2 SMAALumaEdgePredicationDetectionPS(float2 texcoord, 736 | float4 offset[3], 737 | SMAATexture2D(colorTex) 738 | , SMAATexture2D(predicationTex) 739 | ) { 740 | // Calculate the threshold: 741 | float2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, SMAATexturePass2D(predicationTex)); 742 | 743 | // Calculate lumas: 744 | float3 weights = float3(0.2126, 0.7152, 0.0722); 745 | float L = dot(SMAASamplePoint(colorTex, texcoord).rgb, weights); 746 | 747 | float Lleft = dot(SMAASamplePoint(colorTex, offset[0].xy).rgb, weights); 748 | float Ltop = dot(SMAASamplePoint(colorTex, offset[0].zw).rgb, weights); 749 | 750 | // We do the usual threshold: 751 | float4 delta; 752 | delta.xy = abs(L - float2(Lleft, Ltop)); 753 | float2 edges = step(threshold, delta.xy); 754 | 755 | // Then discard if there is no edge: 756 | if (dot(edges, float2(1.0, 1.0)) == 0.0) 757 | discard; 758 | 759 | // Calculate right and bottom deltas: 760 | float Lright = dot(SMAASamplePoint(colorTex, offset[1].xy).rgb, weights); 761 | float Lbottom = dot(SMAASamplePoint(colorTex, offset[1].zw).rgb, weights); 762 | delta.zw = abs(L - float2(Lright, Lbottom)); 763 | 764 | // Calculate the maximum delta in the direct neighborhood: 765 | float2 maxDelta = max(delta.xy, delta.zw); 766 | 767 | // Calculate left-left and top-top deltas: 768 | float Lleftleft = dot(SMAASamplePoint(colorTex, offset[2].xy).rgb, weights); 769 | float Ltoptop = dot(SMAASamplePoint(colorTex, offset[2].zw).rgb, weights); 770 | delta.zw = abs(float2(Lleft, Ltop) - float2(Lleftleft, Ltoptop)); 771 | 772 | // Calculate the final maximum delta: 773 | maxDelta = max(maxDelta.xy, delta.zw); 774 | float finalDelta = max(maxDelta.x, maxDelta.y); 775 | 776 | // Local contrast adaptation: 777 | edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy); 778 | 779 | return edges; 780 | } 781 | 782 | /** 783 | * Color Edge Detection 784 | * 785 | * IMPORTANT NOTICE: color edge detection requires gamma-corrected colors, and 786 | * thus 'colorTex' should be a non-sRGB texture. 787 | */ 788 | float2 SMAAColorEdgeDetectionPS(float2 texcoord, 789 | float4 offset[3], 790 | SMAATexture2D(colorTex) 791 | ) { 792 | // Calculate the threshold: 793 | float2 threshold = float2(SMAA_THRESHOLD, SMAA_THRESHOLD); 794 | 795 | // Calculate color deltas: 796 | float4 delta; 797 | float3 C = SMAASamplePoint(colorTex, texcoord).rgb; 798 | 799 | float3 Cleft = SMAASamplePoint(colorTex, offset[0].xy).rgb; 800 | float3 t = abs(C - Cleft); 801 | delta.x = max(max(t.r, t.g), t.b); 802 | 803 | float3 Ctop = SMAASamplePoint(colorTex, offset[0].zw).rgb; 804 | t = abs(C - Ctop); 805 | delta.y = max(max(t.r, t.g), t.b); 806 | 807 | // We do the usual threshold: 808 | float2 edges = step(threshold, delta.xy); 809 | 810 | // Then discard if there is no edge: 811 | if (dot(edges, float2(1.0, 1.0)) == 0.0) 812 | discard; 813 | 814 | // Calculate right and bottom deltas: 815 | float3 Cright = SMAASamplePoint(colorTex, offset[1].xy).rgb; 816 | t = abs(C - Cright); 817 | delta.z = max(max(t.r, t.g), t.b); 818 | 819 | float3 Cbottom = SMAASamplePoint(colorTex, offset[1].zw).rgb; 820 | t = abs(C - Cbottom); 821 | delta.w = max(max(t.r, t.g), t.b); 822 | 823 | // Calculate the maximum delta in the direct neighborhood: 824 | float2 maxDelta = max(delta.xy, delta.zw); 825 | 826 | // Calculate left-left and top-top deltas: 827 | float3 Cleftleft = SMAASamplePoint(colorTex, offset[2].xy).rgb; 828 | t = abs(Cleft - Cleftleft); 829 | delta.z = max(max(t.r, t.g), t.b); 830 | 831 | float3 Ctoptop = SMAASamplePoint(colorTex, offset[2].zw).rgb; 832 | t = abs(Ctop - Ctoptop); 833 | delta.w = max(max(t.r, t.g), t.b); 834 | 835 | // Calculate the final maximum delta: 836 | maxDelta = max(maxDelta.xy, delta.zw); 837 | float finalDelta = max(maxDelta.x, maxDelta.y); 838 | 839 | // Local contrast adaptation: 840 | edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy); 841 | 842 | return edges; 843 | } 844 | 845 | float2 SMAAColorEdgePredicationDetectionPS(float2 texcoord, 846 | float4 offset[3], 847 | SMAATexture2D(colorTex) 848 | , SMAATexture2D(predicationTex) 849 | ) { 850 | // Calculate the threshold: 851 | float2 threshold = SMAACalculatePredicatedThreshold(texcoord, offset, predicationTex); 852 | 853 | // Calculate color deltas: 854 | float4 delta; 855 | float3 C = SMAASamplePoint(colorTex, texcoord).rgb; 856 | 857 | float3 Cleft = SMAASamplePoint(colorTex, offset[0].xy).rgb; 858 | float3 t = abs(C - Cleft); 859 | delta.x = max(max(t.r, t.g), t.b); 860 | 861 | float3 Ctop = SMAASamplePoint(colorTex, offset[0].zw).rgb; 862 | t = abs(C - Ctop); 863 | delta.y = max(max(t.r, t.g), t.b); 864 | 865 | // We do the usual threshold: 866 | float2 edges = step(threshold, delta.xy); 867 | 868 | // Then discard if there is no edge: 869 | if (dot(edges, float2(1.0, 1.0)) == 0.0) 870 | discard; 871 | 872 | // Calculate right and bottom deltas: 873 | float3 Cright = SMAASamplePoint(colorTex, offset[1].xy).rgb; 874 | t = abs(C - Cright); 875 | delta.z = max(max(t.r, t.g), t.b); 876 | 877 | float3 Cbottom = SMAASamplePoint(colorTex, offset[1].zw).rgb; 878 | t = abs(C - Cbottom); 879 | delta.w = max(max(t.r, t.g), t.b); 880 | 881 | // Calculate the maximum delta in the direct neighborhood: 882 | float2 maxDelta = max(delta.xy, delta.zw); 883 | 884 | // Calculate left-left and top-top deltas: 885 | float3 Cleftleft = SMAASamplePoint(colorTex, offset[2].xy).rgb; 886 | t = abs(Cleft - Cleftleft); 887 | delta.z = max(max(t.r, t.g), t.b); 888 | 889 | float3 Ctoptop = SMAASamplePoint(colorTex, offset[2].zw).rgb; 890 | t = abs(Ctop - Ctoptop); 891 | delta.w = max(max(t.r, t.g), t.b); 892 | 893 | // Calculate the final maximum delta: 894 | maxDelta = max(maxDelta.xy, delta.zw); 895 | float finalDelta = max(maxDelta.x, maxDelta.y); 896 | 897 | // Local contrast adaptation: 898 | edges.xy *= step(finalDelta, SMAA_LOCAL_CONTRAST_ADAPTATION_FACTOR * delta.xy); 899 | 900 | return edges; 901 | } 902 | 903 | /** 904 | * Depth Edge Detection 905 | */ 906 | float2 SMAADepthEdgeDetectionPS(float2 texcoord, 907 | float4 offset[3], 908 | SMAATexture2D(depthTex)) { 909 | float3 neighbours = SMAAGatherNeighbours(texcoord, offset, SMAATexturePass2D(depthTex)); 910 | float2 delta = abs(neighbours.xx - float2(neighbours.y, neighbours.z)); 911 | float2 edges = step(SMAA_DEPTH_THRESHOLD, delta); 912 | 913 | if (dot(edges, float2(1.0, 1.0)) == 0.0) 914 | discard; 915 | 916 | return edges; 917 | } 918 | 919 | //----------------------------------------------------------------------------- 920 | // Diagonal Search Functions 921 | 922 | #if !defined(SMAA_DISABLE_DIAG_DETECTION) 923 | 924 | /** 925 | * Allows to decode two binary values from a bilinear-filtered access. 926 | */ 927 | float2 SMAADecodeDiagBilinearAccess(float2 e) { 928 | // Bilinear access for fetching 'e' have a 0.25 offset, and we are 929 | // interested in the R and G edges: 930 | // 931 | // +---G---+-------+ 932 | // | x o R x | 933 | // +-------+-------+ 934 | // 935 | // Then, if one of these edge is enabled: 936 | // Red: (0.75 * X + 0.25 * 1) => 0.25 or 1.0 937 | // Green: (0.75 * 1 + 0.25 * X) => 0.75 or 1.0 938 | // 939 | // This function will unpack the values (mad + mul + round): 940 | // wolframalpha.com: round(x * abs(5 * x - 5 * 0.75)) plot 0 to 1 941 | e.r = e.r * abs(5.0 * e.r - 5.0 * 0.75); 942 | return round(e); 943 | } 944 | 945 | float4 SMAADecodeDiagBilinearAccess(float4 e) { 946 | e.rb = e.rb * abs(5.0 * e.rb - 5.0 * 0.75); 947 | return round(e); 948 | } 949 | 950 | /** 951 | * These functions allows to perform diagonal pattern searches. 952 | */ 953 | float2 SMAASearchDiag1(SMAATexture2D(edgesTex), float2 texcoord, float2 dir, out float2 e) { 954 | float4 coord = float4(texcoord, -1.0, 1.0); 955 | float3 t = float3(SMAA_RT_METRICS.xy, 1.0); 956 | while (coord.z < float(SMAA_MAX_SEARCH_STEPS_DIAG - 1) && 957 | coord.w > 0.9) { 958 | coord.xyz = mad(t, float3(dir, 1.0), coord.xyz); 959 | e = SMAASampleLevelZero(edgesTex, coord.xy).rg; 960 | coord.w = dot(e, float2(0.5, 0.5)); 961 | } 962 | return coord.zw; 963 | } 964 | 965 | float2 SMAASearchDiag2(SMAATexture2D(edgesTex), float2 texcoord, float2 dir, out float2 e) { 966 | float4 coord = float4(texcoord, -1.0, 1.0); 967 | coord.x += 0.25 * SMAA_RT_METRICS.x; // See @SearchDiag2Optimization 968 | float3 t = float3(SMAA_RT_METRICS.xy, 1.0); 969 | while (coord.z < float(SMAA_MAX_SEARCH_STEPS_DIAG - 1) && 970 | coord.w > 0.9) { 971 | coord.xyz = mad(t, float3(dir, 1.0), coord.xyz); 972 | 973 | // @SearchDiag2Optimization 974 | // Fetch both edges at once using bilinear filtering: 975 | e = SMAASampleLevelZero(edgesTex, coord.xy).rg; 976 | e = SMAADecodeDiagBilinearAccess(e); 977 | 978 | // Non-optimized version: 979 | // e.g = SMAASampleLevelZero(edgesTex, coord.xy).g; 980 | // e.r = SMAASampleLevelZeroOffset(edgesTex, coord.xy, int2(1, 0)).r; 981 | 982 | coord.w = dot(e, float2(0.5, 0.5)); 983 | } 984 | return coord.zw; 985 | } 986 | 987 | /** 988 | * Similar to SMAAArea, this calculates the area corresponding to a certain 989 | * diagonal distance and crossing edges 'e'. 990 | */ 991 | float2 SMAAAreaDiag(SMAATexture2D(areaTex), float2 dist, float2 e, float offset) { 992 | float2 texcoord = mad(float2(SMAA_AREATEX_MAX_DISTANCE_DIAG, SMAA_AREATEX_MAX_DISTANCE_DIAG), e, dist); 993 | 994 | // We do a scale and bias for mapping to texel space: 995 | texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5 * SMAA_AREATEX_PIXEL_SIZE); 996 | 997 | // Diagonal areas are on the second half of the texture: 998 | texcoord.x += 0.5; 999 | 1000 | // Move to proper place, according to the subpixel offset: 1001 | texcoord.y += SMAA_AREATEX_SUBTEX_SIZE * offset; 1002 | 1003 | // Do it! 1004 | return SMAA_AREATEX_SELECT(SMAASampleLevelZero(areaTex, texcoord)); 1005 | } 1006 | 1007 | /** 1008 | * This searches for diagonal patterns and returns the corresponding weights. 1009 | */ 1010 | float2 SMAACalculateDiagWeights(SMAATexture2D(edgesTex), SMAATexture2D(areaTex), float2 texcoord, float2 e, float4 subsampleIndices) { 1011 | float2 weights = float2(0.0, 0.0); 1012 | 1013 | // Search for the line ends: 1014 | float4 d; 1015 | float2 end; 1016 | if (e.r > 0.0) { 1017 | d.xz = SMAASearchDiag1(SMAATexturePass2D(edgesTex), texcoord, float2(-1.0, 1.0), end); 1018 | d.x += float(end.y > 0.9); 1019 | } else 1020 | d.xz = float2(0.0, 0.0); 1021 | d.yw = SMAASearchDiag1(SMAATexturePass2D(edgesTex), texcoord, float2(1.0, -1.0), end); 1022 | 1023 | SMAA_BRANCH 1024 | if (d.x + d.y > 2.0) { // d.x + d.y + 1 > 3 1025 | // Fetch the crossing edges: 1026 | float4 coords = mad(float4(-d.x + 0.25, d.x, d.y, -d.y - 0.25), SMAA_RT_METRICS.xyxy, texcoord.xyxy); 1027 | float4 c; 1028 | c.xy = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0)).rg; 1029 | c.zw = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0)).rg; 1030 | c.yxwz = SMAADecodeDiagBilinearAccess(c.xyzw); 1031 | 1032 | // Non-optimized version: 1033 | // float4 coords = mad(float4(-d.x, d.x, d.y, -d.y), SMAA_RT_METRICS.xyxy, texcoord.xyxy); 1034 | // float4 c; 1035 | // c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0)).g; 1036 | // c.y = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2( 0, 0)).r; 1037 | // c.z = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0)).g; 1038 | // c.w = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, -1)).r; 1039 | 1040 | // Merge crossing edges at each side into a single value: 1041 | float2 cc = mad(float2(2.0, 2.0), c.xz, c.yw); 1042 | 1043 | // Remove the crossing edge if we didn't found the end of the line: 1044 | SMAAMovc(bool2(step(0.9, d.zw)), cc, float2(0.0, 0.0)); 1045 | 1046 | // Fetch the areas for this line: 1047 | weights += SMAAAreaDiag(SMAATexturePass2D(areaTex), d.xy, cc, subsampleIndices.z); 1048 | } 1049 | 1050 | // Search for the line ends: 1051 | d.xz = SMAASearchDiag2(SMAATexturePass2D(edgesTex), texcoord, float2(-1.0, -1.0), end); 1052 | if (SMAASampleLevelZeroOffset(edgesTex, texcoord, int2(1, 0)).r > 0.0) { 1053 | d.yw = SMAASearchDiag2(SMAATexturePass2D(edgesTex), texcoord, float2(1.0, 1.0), end); 1054 | d.y += float(end.y > 0.9); 1055 | } else 1056 | d.yw = float2(0.0, 0.0); 1057 | 1058 | SMAA_BRANCH 1059 | if (d.x + d.y > 2.0) { // d.x + d.y + 1 > 3 1060 | // Fetch the crossing edges: 1061 | float4 coords = mad(float4(-d.x, -d.x, d.y, d.y), SMAA_RT_METRICS.xyxy, texcoord.xyxy); 1062 | float4 c; 1063 | c.x = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2(-1, 0)).g; 1064 | c.y = SMAASampleLevelZeroOffset(edgesTex, coords.xy, int2( 0, -1)).r; 1065 | c.zw = SMAASampleLevelZeroOffset(edgesTex, coords.zw, int2( 1, 0)).gr; 1066 | float2 cc = mad(float2(2.0, 2.0), c.xz, c.yw); 1067 | 1068 | // Remove the crossing edge if we didn't found the end of the line: 1069 | SMAAMovc(bool2(step(0.9, d.zw)), cc, float2(0.0, 0.0)); 1070 | 1071 | // Fetch the areas for this line: 1072 | weights += SMAAAreaDiag(SMAATexturePass2D(areaTex), d.xy, cc, subsampleIndices.w).gr; 1073 | } 1074 | 1075 | return weights; 1076 | } 1077 | #endif 1078 | 1079 | //----------------------------------------------------------------------------- 1080 | // Horizontal/Vertical Search Functions 1081 | 1082 | /** 1083 | * This allows to determine how much length should we add in the last step 1084 | * of the searches. It takes the bilinearly interpolated edge (see 1085 | * @PSEUDO_GATHER4), and adds 0, 1 or 2, depending on which edges and 1086 | * crossing edges are active. 1087 | */ 1088 | float SMAASearchLength(SMAATexture2D(searchTex), float2 e, float offset) { 1089 | // The texture is flipped vertically, with left and right cases taking half 1090 | // of the space horizontally: 1091 | float2 scale = SMAA_SEARCHTEX_SIZE * float2(0.5, -1.0); 1092 | float2 bias = SMAA_SEARCHTEX_SIZE * float2(offset, 1.0); 1093 | 1094 | // Scale and bias to access texel centers: 1095 | scale += float2(-1.0, 1.0); 1096 | bias += float2( 0.5, -0.5); 1097 | 1098 | // Convert from pixel coordinates to texcoords: 1099 | // (We use SMAA_SEARCHTEX_PACKED_SIZE because the texture is cropped) 1100 | scale *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE; 1101 | bias *= 1.0 / SMAA_SEARCHTEX_PACKED_SIZE; 1102 | 1103 | // Lookup the search texture: 1104 | return SMAA_SEARCHTEX_SELECT(SMAASampleLevelZero(searchTex, mad(scale, e, bias))); 1105 | } 1106 | 1107 | /** 1108 | * Horizontal/vertical search functions for the 2nd pass. 1109 | */ 1110 | float SMAASearchXLeft(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { 1111 | /** 1112 | * @PSEUDO_GATHER4 1113 | * This texcoord has been offset by (-0.25, -0.125) in the vertex shader to 1114 | * sample between edge, thus fetching four edges in a row. 1115 | * Sampling with different offsets in each direction allows to disambiguate 1116 | * which edges are active from the four fetched ones. 1117 | */ 1118 | float2 e = float2(0.0, 1.0); 1119 | while (texcoord.x > end && 1120 | e.g > 0.8281 && // Is there some edge not activated? 1121 | e.r == 0.0) { // Or is there a crossing edge that breaks the line? 1122 | e = SMAASampleLevelZero(edgesTex, texcoord).rg; 1123 | texcoord = mad(-float2(2.0, 0.0), SMAA_RT_METRICS.xy, texcoord); 1124 | } 1125 | 1126 | float offset = mad(-(255.0 / 127.0), SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.0), 3.25); 1127 | return mad(SMAA_RT_METRICS.x, offset, texcoord.x); 1128 | 1129 | // Non-optimized version: 1130 | // We correct the previous (-0.25, -0.125) offset we applied: 1131 | // texcoord.x += 0.25 * SMAA_RT_METRICS.x; 1132 | 1133 | // The searches are bias by 1, so adjust the coords accordingly: 1134 | // texcoord.x += SMAA_RT_METRICS.x; 1135 | 1136 | // Disambiguate the length added by the last step: 1137 | // texcoord.x += 2.0 * SMAA_RT_METRICS.x; // Undo last step 1138 | // texcoord.x -= SMAA_RT_METRICS.x * (255.0 / 127.0) * SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.0); 1139 | // return mad(SMAA_RT_METRICS.x, offset, texcoord.x); 1140 | } 1141 | 1142 | float SMAASearchXRight(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { 1143 | float2 e = float2(0.0, 1.0); 1144 | while (texcoord.x < end && 1145 | e.g > 0.8281 && // Is there some edge not activated? 1146 | e.r == 0.0) { // Or is there a crossing edge that breaks the line? 1147 | e = SMAASampleLevelZero(edgesTex, texcoord).rg; 1148 | texcoord = mad(float2(2.0, 0.0), SMAA_RT_METRICS.xy, texcoord); 1149 | } 1150 | float offset = mad(-(255.0 / 127.0), SMAASearchLength(SMAATexturePass2D(searchTex), e, 0.5), 3.25); 1151 | return mad(-SMAA_RT_METRICS.x, offset, texcoord.x); 1152 | } 1153 | 1154 | float SMAASearchYUp(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { 1155 | float2 e = float2(1.0, 0.0); 1156 | while (texcoord.y > end && 1157 | e.r > 0.8281 && // Is there some edge not activated? 1158 | e.g == 0.0) { // Or is there a crossing edge that breaks the line? 1159 | e = SMAASampleLevelZero(edgesTex, texcoord).rg; 1160 | texcoord = mad(-float2(0.0, 2.0), SMAA_RT_METRICS.xy, texcoord); 1161 | } 1162 | float offset = mad(-(255.0 / 127.0), SMAASearchLength(SMAATexturePass2D(searchTex), e.gr, 0.0), 3.25); 1163 | return mad(SMAA_RT_METRICS.y, offset, texcoord.y); 1164 | } 1165 | 1166 | float SMAASearchYDown(SMAATexture2D(edgesTex), SMAATexture2D(searchTex), float2 texcoord, float end) { 1167 | float2 e = float2(1.0, 0.0); 1168 | while (texcoord.y < end && 1169 | e.r > 0.8281 && // Is there some edge not activated? 1170 | e.g == 0.0) { // Or is there a crossing edge that breaks the line? 1171 | e = SMAASampleLevelZero(edgesTex, texcoord).rg; 1172 | texcoord = mad(float2(0.0, 2.0), SMAA_RT_METRICS.xy, texcoord); 1173 | } 1174 | float offset = mad(-(255.0 / 127.0), SMAASearchLength(SMAATexturePass2D(searchTex), e.gr, 0.5), 3.25); 1175 | return mad(-SMAA_RT_METRICS.y, offset, texcoord.y); 1176 | } 1177 | 1178 | /** 1179 | * Ok, we have the distance and both crossing edges. So, what are the areas 1180 | * at each side of current edge? 1181 | */ 1182 | float2 SMAAArea(SMAATexture2D(areaTex), float2 dist, float e1, float e2, float offset) { 1183 | // Rounding prevents precision errors of bilinear filtering: 1184 | float2 texcoord = mad(float2(SMAA_AREATEX_MAX_DISTANCE, SMAA_AREATEX_MAX_DISTANCE), round(4.0 * float2(e1, e2)), dist); 1185 | 1186 | // We do a scale and bias for mapping to texel space: 1187 | texcoord = mad(SMAA_AREATEX_PIXEL_SIZE, texcoord, 0.5 * SMAA_AREATEX_PIXEL_SIZE); 1188 | 1189 | // Move to proper place, according to the subpixel offset: 1190 | texcoord.y = mad(SMAA_AREATEX_SUBTEX_SIZE, offset, texcoord.y); 1191 | 1192 | // Do it! 1193 | return SMAA_AREATEX_SELECT(SMAASampleLevelZero(areaTex, texcoord)); 1194 | } 1195 | 1196 | //----------------------------------------------------------------------------- 1197 | // Corner Detection Functions 1198 | 1199 | void SMAADetectHorizontalCornerPattern(SMAATexture2D(edgesTex), inout float2 weights, float4 texcoord, float2 d) { 1200 | #if !defined(SMAA_DISABLE_CORNER_DETECTION) 1201 | float2 leftRight = step(d.xy, d.yx); 1202 | float2 rounding = (1.0 - SMAA_CORNER_ROUNDING_NORM) * leftRight; 1203 | 1204 | rounding /= leftRight.x + leftRight.y; // Reduce blending for pixels in the center of a line. 1205 | 1206 | float2 factor = float2(1.0, 1.0); 1207 | factor.x -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, int2(0, 1)).r; 1208 | factor.x -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, int2(1, 1)).r; 1209 | factor.y -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, int2(0, -2)).r; 1210 | factor.y -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, int2(1, -2)).r; 1211 | 1212 | weights *= saturate(factor); 1213 | #endif 1214 | } 1215 | 1216 | void SMAADetectVerticalCornerPattern(SMAATexture2D(edgesTex), inout float2 weights, float4 texcoord, float2 d) { 1217 | #if !defined(SMAA_DISABLE_CORNER_DETECTION) 1218 | float2 leftRight = step(d.xy, d.yx); 1219 | float2 rounding = (1.0 - SMAA_CORNER_ROUNDING_NORM) * leftRight; 1220 | 1221 | rounding /= leftRight.x + leftRight.y; 1222 | 1223 | float2 factor = float2(1.0, 1.0); 1224 | factor.x -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, int2( 1, 0)).g; 1225 | factor.x -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, int2( 1, 1)).g; 1226 | factor.y -= rounding.x * SMAASampleLevelZeroOffset(edgesTex, texcoord.xy, int2(-2, 0)).g; 1227 | factor.y -= rounding.y * SMAASampleLevelZeroOffset(edgesTex, texcoord.zw, int2(-2, 1)).g; 1228 | 1229 | weights *= saturate(factor); 1230 | #endif 1231 | } 1232 | 1233 | //----------------------------------------------------------------------------- 1234 | // Blending Weight Calculation Pixel Shader (Second Pass) 1235 | 1236 | float4 SMAABlendingWeightCalculationPS(float2 texcoord, 1237 | float2 pixcoord, 1238 | float4 offset[3], 1239 | SMAATexture2D(edgesTex), 1240 | SMAATexture2D(areaTex), 1241 | SMAATexture2D(searchTex), 1242 | float4 subsampleIndices) { // Just pass zero for SMAA 1x, see @SUBSAMPLE_INDICES. 1243 | float4 weights = float4(0.0, 0.0, 0.0, 0.0); 1244 | 1245 | float2 e = SMAASample(edgesTex, texcoord).rg; 1246 | 1247 | SMAA_BRANCH 1248 | if (e.g > 0.0) { // Edge at north 1249 | #if !defined(SMAA_DISABLE_DIAG_DETECTION) 1250 | // Diagonals have both north and west edges, so searching for them in 1251 | // one of the boundaries is enough. 1252 | weights.rg = SMAACalculateDiagWeights(SMAATexturePass2D(edgesTex), SMAATexturePass2D(areaTex), texcoord, e, subsampleIndices); 1253 | 1254 | // We give priority to diagonals, so if we find a diagonal we skip 1255 | // horizontal/vertical processing. 1256 | SMAA_BRANCH 1257 | if (weights.r == -weights.g) { // weights.r + weights.g == 0.0 1258 | #endif 1259 | 1260 | float2 d; 1261 | 1262 | // Find the distance to the left: 1263 | float3 coords; 1264 | coords.x = SMAASearchXLeft(SMAATexturePass2D(edgesTex), SMAATexturePass2D(searchTex), offset[0].xy, offset[2].x); 1265 | coords.y = offset[1].y; // offset[1].y = texcoord.y - 0.25 * SMAA_RT_METRICS.y (@CROSSING_OFFSET) 1266 | d.x = coords.x; 1267 | 1268 | // Now fetch the left crossing edges, two at a time using bilinear 1269 | // filtering. Sampling at -0.25 (see @CROSSING_OFFSET) enables to 1270 | // discern what value each edge has: 1271 | float e1 = SMAASampleLevelZero(edgesTex, coords.xy).r; 1272 | 1273 | // Find the distance to the right: 1274 | coords.z = SMAASearchXRight(SMAATexturePass2D(edgesTex), SMAATexturePass2D(searchTex), offset[0].zw, offset[2].y); 1275 | d.y = coords.z; 1276 | 1277 | // We want the distances to be in pixel units (doing this here allow to 1278 | // better interleave arithmetic and memory accesses): 1279 | d = abs(round(mad(SMAA_RT_METRICS.zz, d, -pixcoord.xx))); 1280 | 1281 | // SMAAArea below needs a sqrt, as the areas texture is compressed 1282 | // quadratically: 1283 | float2 sqrt_d = sqrt(d); 1284 | 1285 | // Fetch the right crossing edges: 1286 | float e2 = SMAASampleLevelZeroOffset(edgesTex, coords.zy, int2(1, 0)).r; 1287 | 1288 | // Ok, we know how this pattern looks like, now it is time for getting 1289 | // the actual area: 1290 | weights.rg = SMAAArea(SMAATexturePass2D(areaTex), sqrt_d, e1, e2, subsampleIndices.y); 1291 | 1292 | // Fix corners: 1293 | coords.y = texcoord.y; 1294 | SMAADetectHorizontalCornerPattern(SMAATexturePass2D(edgesTex), weights.rg, coords.xyzy, d); 1295 | 1296 | #if !defined(SMAA_DISABLE_DIAG_DETECTION) 1297 | } else 1298 | e.r = 0.0; // Skip vertical processing. 1299 | #endif 1300 | } 1301 | 1302 | SMAA_BRANCH 1303 | if (e.r > 0.0) { // Edge at west 1304 | float2 d; 1305 | 1306 | // Find the distance to the top: 1307 | float3 coords; 1308 | coords.y = SMAASearchYUp(SMAATexturePass2D(edgesTex), SMAATexturePass2D(searchTex), offset[1].xy, offset[2].z); 1309 | coords.x = offset[0].x; // offset[1].x = texcoord.x - 0.25 * SMAA_RT_METRICS.x; 1310 | d.x = coords.y; 1311 | 1312 | // Fetch the top crossing edges: 1313 | float e1 = SMAASampleLevelZero(edgesTex, coords.xy).g; 1314 | 1315 | // Find the distance to the bottom: 1316 | coords.z = SMAASearchYDown(SMAATexturePass2D(edgesTex), SMAATexturePass2D(searchTex), offset[1].zw, offset[2].w); 1317 | d.y = coords.z; 1318 | 1319 | // We want the distances to be in pixel units: 1320 | d = abs(round(mad(SMAA_RT_METRICS.ww, d, -pixcoord.yy))); 1321 | 1322 | // SMAAArea below needs a sqrt, as the areas texture is compressed 1323 | // quadratically: 1324 | float2 sqrt_d = sqrt(d); 1325 | 1326 | // Fetch the bottom crossing edges: 1327 | float e2 = SMAASampleLevelZeroOffset(edgesTex, coords.xz, int2(0, 1)).g; 1328 | 1329 | // Get the area for this direction: 1330 | weights.ba = SMAAArea(SMAATexturePass2D(areaTex), sqrt_d, e1, e2, subsampleIndices.x); 1331 | 1332 | // Fix corners: 1333 | coords.x = texcoord.x; 1334 | SMAADetectVerticalCornerPattern(SMAATexturePass2D(edgesTex), weights.ba, coords.xyxz, d); 1335 | } 1336 | 1337 | return weights; 1338 | } 1339 | 1340 | //----------------------------------------------------------------------------- 1341 | // Neighborhood Blending Pixel Shader (Third Pass) 1342 | 1343 | float4 SMAANeighborhoodBlendingPS(float2 texcoord, 1344 | float4 offset, 1345 | SMAATexture2D(colorTex), 1346 | SMAATexture2D(blendTex) 1347 | #if SMAA_REPROJECTION 1348 | , SMAATexture2D(velocityTex) 1349 | #endif 1350 | ) { 1351 | // Fetch the blending weights for current pixel: 1352 | float4 a; 1353 | a.x = SMAASample(blendTex, offset.xy).a; // Right 1354 | a.y = SMAASample(blendTex, offset.zw).g; // Top 1355 | a.wz = SMAASample(blendTex, texcoord).xz; // Bottom / Left 1356 | 1357 | // Is there any blending weight with a value greater than 0.0? 1358 | SMAA_BRANCH 1359 | if (dot(a, float4(1.0, 1.0, 1.0, 1.0)) < 1e-5) { 1360 | float4 color = SMAASampleLevelZero(colorTex, texcoord); 1361 | 1362 | #if SMAA_REPROJECTION 1363 | float2 velocity = SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, texcoord)); 1364 | 1365 | // Pack velocity into the alpha channel: 1366 | color.a = sqrt(5.0 * length(velocity)); 1367 | #endif 1368 | 1369 | return color; 1370 | } else { 1371 | bool h = max(a.x, a.z) > max(a.y, a.w); // max(horizontal) > max(vertical) 1372 | 1373 | // Calculate the blending offsets: 1374 | float4 blendingOffset = float4(0.0, a.y, 0.0, a.w); 1375 | float2 blendingWeight = a.yw; 1376 | SMAAMovc(bool4(h, h, h, h), blendingOffset, float4(a.x, 0.0, a.z, 0.0)); 1377 | SMAAMovc(bool2(h, h), blendingWeight, a.xz); 1378 | blendingWeight /= dot(blendingWeight, float2(1.0, 1.0)); 1379 | 1380 | // Calculate the texture coordinates: 1381 | float4 blendingCoord = mad(blendingOffset, float4(SMAA_RT_METRICS.xy, -SMAA_RT_METRICS.xy), texcoord.xyxy); 1382 | 1383 | // We exploit bilinear filtering to mix current pixel with the chosen 1384 | // neighbor: 1385 | float4 color = blendingWeight.x * SMAASampleLevelZero(colorTex, blendingCoord.xy); 1386 | color += blendingWeight.y * SMAASampleLevelZero(colorTex, blendingCoord.zw); 1387 | 1388 | #if SMAA_REPROJECTION 1389 | // Antialias velocity for proper reprojection in a later stage: 1390 | float2 velocity = blendingWeight.x * SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, blendingCoord.xy)); 1391 | velocity += blendingWeight.y * SMAA_DECODE_VELOCITY(SMAASampleLevelZero(velocityTex, blendingCoord.zw)); 1392 | 1393 | // Pack velocity into the alpha channel: 1394 | color.a = sqrt(5.0 * length(velocity)); 1395 | #endif 1396 | 1397 | return color; 1398 | } 1399 | } 1400 | 1401 | //----------------------------------------------------------------------------- 1402 | // Temporal Resolve Pixel Shader (Optional Pass) 1403 | 1404 | float4 SMAAResolvePS(float2 texcoord, 1405 | SMAATexture2D(currentColorTex), 1406 | SMAATexture2D(previousColorTex) 1407 | #if SMAA_REPROJECTION 1408 | , SMAATexture2D(velocityTex) 1409 | #endif 1410 | ) { 1411 | #if SMAA_REPROJECTION 1412 | // Velocity is assumed to be calculated for motion blur, so we need to 1413 | // inverse it for reprojection: 1414 | float2 velocity = -SMAA_DECODE_VELOCITY(SMAASamplePoint(velocityTex, texcoord).rg); 1415 | 1416 | // Fetch current pixel: 1417 | float4 current = SMAASamplePoint(currentColorTex, texcoord); 1418 | 1419 | // Reproject current coordinates and fetch previous pixel: 1420 | float4 previous = SMAASamplePoint(previousColorTex, texcoord + velocity); 1421 | 1422 | // Attenuate the previous pixel if the velocity is different: 1423 | float delta = abs(current.a * current.a - previous.a * previous.a) / 5.0; 1424 | float weight = 0.5 * saturate(1.0 - sqrt(delta) * SMAA_REPROJECTION_WEIGHT_SCALE); 1425 | 1426 | // Blend the pixels according to the calculated weight: 1427 | return lerp(current, previous, weight); 1428 | #else 1429 | // Just blend the pixels: 1430 | float4 current = SMAASamplePoint(currentColorTex, texcoord); 1431 | float4 previous = SMAASamplePoint(previousColorTex, texcoord); 1432 | return lerp(current, previous, 0.5); 1433 | #endif 1434 | } 1435 | 1436 | //----------------------------------------------------------------------------- 1437 | // Separate Multisamples Pixel Shader (Optional Pass) 1438 | 1439 | #ifdef SMAALoad 1440 | void SMAASeparatePS(float4 position, 1441 | float2 texcoord, 1442 | out float4 target0, 1443 | out float4 target1, 1444 | SMAATexture2DMS2(colorTexMS)) { 1445 | int2 pos = int2(position.xy); 1446 | target0 = SMAALoad(colorTexMS, pos, 0); 1447 | target1 = SMAALoad(colorTexMS, pos, 1); 1448 | } 1449 | #endif 1450 | 1451 | //----------------------------------------------------------------------------- 1452 | #endif // SMAA_INCLUDE_PS 1453 | -------------------------------------------------------------------------------- /Shaders/Sepia.fx: -------------------------------------------------------------------------------- 1 | #include "ReShadeUI.fxh" 2 | 3 | uniform float3 Tint < __UNIFORM_COLOR_FLOAT3 4 | > = float3(0.55, 0.43, 0.42); 5 | 6 | uniform float Strength < __UNIFORM_SLIDER_FLOAT1 7 | ui_min = 0.0; ui_max = 1.0; 8 | ui_tooltip = "Adjust the strength of the effect."; 9 | > = 0.58; 10 | 11 | #include "ReShade.fxh" 12 | 13 | float3 TintPass(float4 vois : SV_Position, float2 texcoord : TexCoord) : SV_Target 14 | { 15 | float3 col = tex2D(ReShade::BackBuffer, texcoord).rgb; 16 | 17 | return lerp(col, col * Tint * 2.55, Strength); 18 | } 19 | 20 | technique Tint 21 | { 22 | pass 23 | { 24 | VertexShader = PostProcessVS; 25 | PixelShader = TintPass; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Shaders/Splitscreen.fx: -------------------------------------------------------------------------------- 1 | /*------------------. 2 | | :: Description :: | 3 | '-------------------/ 4 | 5 | Splitscreen (version 2.0) 6 | 7 | Author: CeeJay.dk 8 | License: MIT 9 | 10 | About: 11 | Displays the image before and after it has been modified by effects using a splitscreen 12 | 13 | 14 | Ideas for future improvement: 15 | * 16 | 17 | History: 18 | (*) Feature (+) Improvement (x) Bugfix (-) Information (!) Compatibility 19 | 20 | Version 1.0 21 | * Does a splitscreen before/after view 22 | 23 | Version 2.0 24 | * Ported to Reshade 3.x 25 | * Added UI settings. 26 | * Added Diagonal split mode 27 | - Removed curvy mode. I didn't like how it looked. 28 | - Threatened other modes to behave or they would be next. 29 | */ 30 | 31 | /*------------------. 32 | | :: UI Settings :: | 33 | '------------------*/ 34 | 35 | #include "ReShadeUI.fxh" 36 | 37 | uniform int splitscreen_mode < 38 | ui_type = "combo"; 39 | ui_label = "Mode"; 40 | ui_tooltip = "Choose a mode"; 41 | //ui_category = ""; 42 | ui_items = 43 | "Vertical 50/50 split\0" 44 | "Vertical 25/50/25 split\0" 45 | "Angled 50/50 split\0" 46 | "Angled 25/50/25 split\0" 47 | "Horizontal 50/50 split\0" 48 | "Horizontal 25/50/25 split\0" 49 | "Diagonal split\0" 50 | ; 51 | > = 0; 52 | 53 | /*---------------. 54 | | :: Includes :: | 55 | '---------------*/ 56 | 57 | #include "ReShade.fxh" 58 | 59 | 60 | /*-------------------------. 61 | | :: Texture and sampler:: | 62 | '-------------------------*/ 63 | 64 | texture Before { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; }; 65 | sampler Before_sampler { Texture = Before; }; 66 | 67 | 68 | /*-------------. 69 | | :: Effect :: | 70 | '-------------*/ 71 | 72 | float4 PS_Before(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target 73 | { 74 | return tex2D(ReShade::BackBuffer, texcoord); 75 | } 76 | 77 | float4 PS_After(float4 pos : SV_Position, float2 texcoord : TEXCOORD) : SV_Target 78 | { 79 | float4 color; 80 | 81 | // -- Vertical 50/50 split -- 82 | [branch] if (splitscreen_mode == 0) 83 | color = (texcoord.x < 0.5 ) ? tex2D(Before_sampler, texcoord) : tex2D(ReShade::BackBuffer, texcoord); 84 | 85 | // -- Vertical 25/50/25 split -- 86 | [branch] if (splitscreen_mode == 1) 87 | { 88 | //Calculate the distance from center 89 | float dist = abs(texcoord.x - 0.5); 90 | 91 | //Further than 1/4 away from center? 92 | dist = saturate(dist - 0.25); 93 | 94 | color = dist ? tex2D(Before_sampler, texcoord) : tex2D(ReShade::BackBuffer, texcoord); 95 | } 96 | 97 | // -- Angled 50/50 split -- 98 | [branch] if (splitscreen_mode == 2) 99 | { 100 | //Calculate the distance from center 101 | float dist = ((texcoord.x - 3.0/8.0) + (texcoord.y * 0.25)); 102 | 103 | //Further than 1/4 away from center? 104 | dist = saturate(dist - 0.25); 105 | 106 | color = dist ? tex2D(ReShade::BackBuffer, texcoord) : tex2D(Before_sampler, texcoord); 107 | } 108 | 109 | // -- Angled 25/50/25 split -- 110 | [branch] if (splitscreen_mode == 3) 111 | { 112 | //Calculate the distance from center 113 | float dist = ((texcoord.x - 3.0/8.0) + (texcoord.y * 0.25)); 114 | 115 | dist = abs(dist - 0.25); 116 | 117 | //Further than 1/4 away from center? 118 | dist = saturate(dist - 0.25); 119 | 120 | color = dist ? tex2D(Before_sampler, texcoord) : tex2D(ReShade::BackBuffer, texcoord); 121 | } 122 | 123 | // -- Horizontal 50/50 split -- 124 | [branch] if (splitscreen_mode == 4) 125 | color = (texcoord.y < 0.5) ? tex2D(Before_sampler, texcoord) : tex2D(ReShade::BackBuffer, texcoord); 126 | 127 | // -- Horizontal 25/50/25 split -- 128 | [branch] if (splitscreen_mode == 5) 129 | { 130 | //Calculate the distance from center 131 | float dist = abs(texcoord.y - 0.5); 132 | 133 | //Further than 1/4 away from center? 134 | dist = saturate(dist - 0.25); 135 | 136 | color = dist ? tex2D(Before_sampler, texcoord) : tex2D(ReShade::BackBuffer, texcoord); 137 | } 138 | 139 | // -- Diagonal split -- 140 | [branch] if (splitscreen_mode == 6) 141 | { 142 | //Calculate the distance from center 143 | float dist = (texcoord.x + texcoord.y); 144 | 145 | //Further than 1/2 away from center? 146 | //dist = saturate(dist - 1.0); 147 | 148 | color = (dist < 1.0) ? tex2D(Before_sampler, texcoord) : tex2D(ReShade::BackBuffer, texcoord); 149 | } 150 | 151 | return color; 152 | } 153 | 154 | 155 | /*-----------------. 156 | | :: Techniques :: | 157 | '-----------------*/ 158 | 159 | technique Before 160 | { 161 | pass 162 | { 163 | VertexShader = PostProcessVS; 164 | PixelShader = PS_Before; 165 | RenderTarget = Before; 166 | } 167 | } 168 | 169 | technique After 170 | { 171 | pass 172 | { 173 | VertexShader = PostProcessVS; 174 | PixelShader = PS_After; 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /Shaders/Technicolor.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * Technicolor version 1.1 3 | * Original by DKT70 4 | * Optimized by CeeJay.dk 5 | */ 6 | 7 | #include "ReShadeUI.fxh" 8 | 9 | uniform float Power < __UNIFORM_SLIDER_FLOAT1 10 | ui_min = 0.0; ui_max = 8.0; 11 | > = 4.0; 12 | uniform float3 RGBNegativeAmount < __UNIFORM_COLOR_FLOAT3 13 | > = float3(0.88, 0.88, 0.88); 14 | 15 | uniform float Strength < __UNIFORM_SLIDER_FLOAT1 16 | ui_min = 0.0; ui_max = 1.0; 17 | ui_tooltip = "Adjust the strength of the effect."; 18 | > = 0.4; 19 | 20 | #include "ReShade.fxh" 21 | 22 | float3 TechnicolorPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 23 | { 24 | const float3 cyanfilter = float3(0.0, 1.30, 1.0); 25 | const float3 magentafilter = float3(1.0, 0.0, 1.05); 26 | const float3 yellowfilter = float3(1.6, 1.6, 0.05); 27 | const float2 redorangefilter = float2(1.05, 0.620); // RG_ 28 | const float2 greenfilter = float2(0.30, 1.0); // RG_ 29 | const float2 magentafilter2 = magentafilter.rb; // R_B 30 | 31 | float3 tcol = tex2D(ReShade::BackBuffer, texcoord).rgb; 32 | 33 | float2 negative_mul_r = tcol.rg * (1.0 / (RGBNegativeAmount.r * Power)); 34 | float2 negative_mul_g = tcol.rg * (1.0 / (RGBNegativeAmount.g * Power)); 35 | float2 negative_mul_b = tcol.rb * (1.0 / (RGBNegativeAmount.b * Power)); 36 | float3 output_r = dot(redorangefilter, negative_mul_r).xxx + cyanfilter; 37 | float3 output_g = dot(greenfilter, negative_mul_g).xxx + magentafilter; 38 | float3 output_b = dot(magentafilter2, negative_mul_b).xxx + yellowfilter; 39 | 40 | return lerp(tcol, output_r * output_g * output_b, Strength); 41 | } 42 | 43 | technique Technicolor 44 | { 45 | pass 46 | { 47 | VertexShader = PostProcessVS; 48 | PixelShader = TechnicolorPass; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Shaders/Technicolor2.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * Technicolor2 version 1.0 3 | * Original by Prod80 4 | * Optimized by CeeJay.dk 5 | */ 6 | 7 | #include "ReShadeUI.fxh" 8 | 9 | uniform float3 ColorStrength < __UNIFORM_COLOR_FLOAT3 10 | ui_tooltip = "Higher means darker and more intense colors."; 11 | > = float3(0.2, 0.2, 0.2); 12 | 13 | uniform float Brightness < __UNIFORM_SLIDER_FLOAT1 14 | ui_min = 0.5; ui_max = 1.5; 15 | ui_tooltip = "Higher means brighter image."; 16 | > = 1.0; 17 | uniform float Saturation < __UNIFORM_SLIDER_FLOAT1 18 | ui_min = 0.0; ui_max = 1.5; 19 | ui_tooltip = "Additional saturation control since this effect tends to oversaturate the image."; 20 | > = 1.0; 21 | 22 | uniform float Strength < __UNIFORM_SLIDER_FLOAT1 23 | ui_min = 0.0; ui_max = 1.0; 24 | ui_tooltip = "Adjust the strength of the effect."; 25 | > = 1.0; 26 | 27 | #include "ReShade.fxh" 28 | 29 | float3 TechnicolorPass(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 30 | { 31 | float3 color = saturate(tex2D(ReShade::BackBuffer, texcoord).rgb); 32 | 33 | float3 temp = 1.0 - color; 34 | float3 target = temp.grg; 35 | float3 target2 = temp.bbr; 36 | float3 temp2 = color * target; 37 | temp2 *= target2; 38 | 39 | temp = temp2 * ColorStrength; 40 | temp2 *= Brightness; 41 | 42 | target = temp.grg; 43 | target2 = temp.bbr; 44 | 45 | temp = color - target; 46 | temp += temp2; 47 | temp2 = temp - target2; 48 | 49 | color = lerp(color, temp2, Strength); 50 | color = lerp(dot(color, 0.333), color, Saturation); 51 | 52 | return color; 53 | } 54 | 55 | technique Technicolor2 56 | { 57 | pass 58 | { 59 | VertexShader = PostProcessVS; 60 | PixelShader = TechnicolorPass; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Shaders/Tonemap.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * Tonemap version 1.1 3 | * by Christian Cann Schuldt Jensen ~ CeeJay.dk 4 | */ 5 | 6 | #include "ReShadeUI.fxh" 7 | 8 | uniform float Gamma < __UNIFORM_SLIDER_FLOAT1 9 | ui_min = 0.0; ui_max = 2.0; 10 | ui_tooltip = "Adjust midtones. 1.0 is neutral. This setting does exactly the same as the one in Lift Gamma Gain, only with less control."; 11 | > = 1.0; 12 | uniform float Exposure < __UNIFORM_SLIDER_FLOAT1 13 | ui_min = -1.0; ui_max = 1.0; 14 | ui_tooltip = "Adjust exposure"; 15 | > = 0.0; 16 | uniform float Saturation < __UNIFORM_SLIDER_FLOAT1 17 | ui_min = -1.0; ui_max = 1.0; 18 | ui_tooltip = "Adjust saturation"; 19 | > = 0.0; 20 | 21 | uniform float Bleach < __UNIFORM_SLIDER_FLOAT1 22 | ui_min = 0.0; ui_max = 1.0; 23 | ui_tooltip = "Brightens the shadows and fades the colors"; 24 | > = 0.0; 25 | 26 | uniform float Defog < __UNIFORM_SLIDER_FLOAT1 27 | ui_min = 0.0; ui_max = 1.0; 28 | ui_tooltip = "How much of the color tint to remove"; 29 | > = 0.0; 30 | uniform float3 FogColor < __UNIFORM_COLOR_FLOAT3 31 | ui_label = "Defog Color"; 32 | ui_tooltip = "Which color tint to remove"; 33 | > = float3(0.0, 0.0, 1.0); 34 | 35 | 36 | #include "ReShade.fxh" 37 | 38 | float3 TonemapPass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target 39 | { 40 | float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb; 41 | color = saturate(color - Defog * FogColor * 2.55); // Defog 42 | color *= pow(2.0f, Exposure); // Exposure 43 | color = pow(color, Gamma); // Gamma 44 | 45 | const float3 coefLuma = float3(0.2126, 0.7152, 0.0722); 46 | float lum = dot(coefLuma, color); 47 | 48 | float L = saturate(10.0 * (lum - 0.45)); 49 | float3 A2 = Bleach * color; 50 | 51 | float3 result1 = 2.0f * color * lum; 52 | float3 result2 = 1.0f - 2.0f * (1.0f - lum) * (1.0f - color); 53 | 54 | float3 newColor = lerp(result1, result2, L); 55 | float3 mixRGB = A2 * newColor; 56 | color += ((1.0f - A2) * mixRGB); 57 | 58 | float3 middlegray = dot(color, (1.0 / 3.0)); 59 | float3 diffcolor = color - middlegray; 60 | color = (color + diffcolor * Saturation) / (1 + (diffcolor * Saturation)); // Saturation 61 | 62 | return color; 63 | } 64 | 65 | technique Tonemap 66 | { 67 | pass 68 | { 69 | VertexShader = PostProcessVS; 70 | PixelShader = TonemapPass; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Shaders/Vibrance.fx: -------------------------------------------------------------------------------- 1 | /** 2 | Vibrance 3 | by Christian Cann Schuldt Jensen ~ CeeJay.dk 4 | 5 | Vibrance intelligently boosts the saturation of pixels so pixels that had little color get a larger boost than pixels that had a lot. 6 | This avoids oversaturation of pixels that were already very saturated. 7 | 8 | History: 9 | 10 | Version 1.0 by Ceejay.dk 11 | - Original 12 | Version 1.1 by CeeJay.dk 13 | - Introduced RBG balance to help colorblind users 14 | Version 1.1.1 15 | - Minor UI improvements for Reshade 3.x 16 | */ 17 | 18 | #include "ReShadeUI.fxh" 19 | 20 | uniform float Vibrance < __UNIFORM_SLIDER_FLOAT1 21 | ui_min = -1.0; ui_max = 1.0; 22 | ui_tooltip = "Intelligently saturates (or desaturates if you use negative values) the pixels depending on their original saturation."; 23 | > = 0.15; 24 | 25 | uniform float3 VibranceRGBBalance < 26 | ui_type = "drag"; 27 | ui_min = 0.0; ui_max = 10.0; 28 | ui_label = "RGB Balance"; 29 | ui_tooltip = "A per channel multiplier to the Vibrance strength so you can give more boost to certain colors over others.\nThis is handy if you are colorblind and less sensitive to a specific color.\nYou can then boost that color more than the others."; 30 | > = float3(1.0, 1.0, 1.0); 31 | 32 | /* 33 | uniform int Vibrance_Luma < 34 | ui_type = "combo"; 35 | ui_label = "Luma type"; 36 | ui_items = "Perceptual\0Even\0"; 37 | > = 0; 38 | */ 39 | 40 | #include "ReShade.fxh" 41 | 42 | float3 VibrancePass(float4 position : SV_Position, float2 texcoord : TexCoord) : SV_Target 43 | { 44 | float3 color = tex2D(ReShade::BackBuffer, texcoord).rgb; 45 | 46 | float3 coefLuma = float3(0.212656, 0.715158, 0.072186); 47 | 48 | /* 49 | if (Vibrance_Luma) 50 | coefLuma = float3(0.333333, 0.333334, 0.333333); 51 | */ 52 | 53 | float luma = dot(coefLuma, color); 54 | 55 | 56 | float max_color = max(color.r, max(color.g, color.b)); // Find the strongest color 57 | float min_color = min(color.r, min(color.g, color.b)); // Find the weakest color 58 | 59 | float color_saturation = max_color - min_color; // The difference between the two is the saturation 60 | 61 | // Extrapolate between luma and original by 1 + (1-saturation) - current 62 | float3 coeffVibrance = float3(VibranceRGBBalance * Vibrance); 63 | color = lerp(luma, color, 1.0 + (coeffVibrance * (1.0 - (sign(coeffVibrance) * color_saturation)))); 64 | 65 | return color; 66 | } 67 | 68 | technique Vibrance 69 | { 70 | pass 71 | { 72 | VertexShader = PostProcessVS; 73 | PixelShader = VibrancePass; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Shaders/Vignette.fx: -------------------------------------------------------------------------------- 1 | /** 2 | * Vignette version 1.3 3 | * by Christian Cann Schuldt Jensen ~ CeeJay.dk 4 | * 5 | * Darkens the edges of the image to make it look more like it was shot with a camera lens. 6 | * May cause banding artifacts. 7 | */ 8 | 9 | #include "ReShadeUI.fxh" 10 | 11 | uniform int Type < 12 | ui_type = "combo"; 13 | ui_items = "Original\0New\0TV style\0Untitled 1\0Untitled 2\0Untitled 3\0Untitled 4\0"; 14 | > = 0; 15 | uniform float Ratio < __UNIFORM_SLIDER_FLOAT1 16 | ui_min = 0.15; ui_max = 6.0; 17 | ui_tooltip = "Sets a width to height ratio. 1.00 (1/1) is perfectly round, while 1.60 (16/10) is 60 % wider than it's high."; 18 | > = 1.0; 19 | uniform float Radius < __UNIFORM_SLIDER_FLOAT1 20 | ui_min = -1.0; ui_max = 3.0; 21 | ui_tooltip = "lower values = stronger radial effect from center"; 22 | > = 2.0; 23 | uniform float Amount < __UNIFORM_SLIDER_FLOAT1 24 | ui_min = -2.0; ui_max = 1.0; 25 | ui_tooltip = "Strength of black. -2.00 = Max Black, 1.00 = Max White."; 26 | > = -1.0; 27 | uniform int Slope < __UNIFORM_SLIDER_INT1 28 | ui_min = 2; ui_max = 16; 29 | ui_tooltip = "How far away from the center the change should start to really grow strong (odd numbers cause a larger fps drop than even numbers)."; 30 | > = 2; 31 | uniform float2 Center < __UNIFORM_SLIDER_FLOAT2 32 | ui_min = 0.0; ui_max = 1.0; 33 | ui_tooltip = "Center of effect for 'Original' vignette type. 'New' and 'TV style' do not obey this setting."; 34 | > = float2(0.5, 0.5); 35 | 36 | #include "ReShade.fxh" 37 | 38 | float4 VignettePass(float4 vpos : SV_Position, float2 tex : TexCoord) : SV_Target 39 | { 40 | float4 color = tex2D(ReShade::BackBuffer, tex); 41 | 42 | if (Type == 0) 43 | { 44 | // Set the center 45 | float2 distance_xy = tex - Center; 46 | 47 | // Adjust the ratio 48 | distance_xy *= float2((BUFFER_RCP_HEIGHT / BUFFER_RCP_WIDTH), Ratio); 49 | 50 | // Calculate the distance 51 | distance_xy /= Radius; 52 | float distance = dot(distance_xy, distance_xy); 53 | 54 | // Apply the vignette 55 | color.rgb *= (1.0 + pow(distance, Slope * 0.5) * Amount); //pow - multiply 56 | } 57 | 58 | if (Type == 1) // New round (-x*x+x) + (-y*y+y) method. 59 | { 60 | tex = -tex * tex + tex; 61 | color.rgb = saturate(((BUFFER_RCP_HEIGHT / BUFFER_RCP_WIDTH)*(BUFFER_RCP_HEIGHT / BUFFER_RCP_WIDTH) * Ratio * tex.x + tex.y) * 4.0) * color.rgb; 62 | } 63 | 64 | if (Type == 2) // New (-x*x+x) * (-y*y+y) TV style method. 65 | { 66 | tex = -tex * tex + tex; 67 | color.rgb = saturate(tex.x * tex.y * 100.0) * color.rgb; 68 | } 69 | 70 | if (Type == 3) 71 | { 72 | tex = abs(tex - 0.5); 73 | float tc = dot(float4(-tex.x, -tex.x, tex.x, tex.y), float4(tex.y, tex.y, 1.0, 1.0)); //XOR 74 | 75 | tc = saturate(tc - 0.495); 76 | color.rgb *= (pow((1.0 - tc * 200), 4) + 0.25); //or maybe abs(tc*100-1) (-(tc*100)-1) 77 | } 78 | 79 | if (Type == 4) 80 | { 81 | tex = abs(tex - 0.5); 82 | float tc = dot(float4(-tex.x, -tex.x, tex.x, tex.y), float4(tex.y, tex.y, 1.0, 1.0)); //XOR 83 | 84 | tc = saturate(tc - 0.495) - 0.0002; 85 | color.rgb *= (pow((1.0 - tc * 200), 4) + 0.0); //or maybe abs(tc*100-1) (-(tc*100)-1) 86 | } 87 | 88 | if (Type == 5) // MAD version of 2 89 | { 90 | tex = abs(tex - 0.5); 91 | float tc = tex.x * (-2.0 * tex.y + 1.0) + tex.y; //XOR 92 | 93 | tc = saturate(tc - 0.495); 94 | color.rgb *= (pow((-tc * 200 + 1.0), 4) + 0.25); //or maybe abs(tc*100-1) (-(tc*100)-1) 95 | //color.rgb *= (pow(((tc*200.0)-1.0),4)); //or maybe abs(tc*100-1) (-(tc*100)-1) 96 | } 97 | 98 | if (Type == 6) // New round (-x*x+x) * (-y*y+y) method. 99 | { 100 | //tex.y /= float2((BUFFER_RCP_HEIGHT / BUFFER_RCP_WIDTH), Ratio); 101 | float tex_xy = dot(float4(tex, tex), float4(-tex, 1.0, 1.0)); //dot is actually slower 102 | color.rgb = saturate(tex_xy * 4.0) * color.rgb; 103 | } 104 | 105 | return color; 106 | } 107 | 108 | technique Vignette 109 | { 110 | pass 111 | { 112 | VertexShader = PostProcessVS; 113 | PixelShader = VignettePass; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /Textures/AreaTex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CeeJayDK/SweetFX/8d08f61ecb0727c486387b6ce78cf4eb33f55b41/Textures/AreaTex.png -------------------------------------------------------------------------------- /Textures/Layer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CeeJayDK/SweetFX/8d08f61ecb0727c486387b6ce78cf4eb33f55b41/Textures/Layer.png -------------------------------------------------------------------------------- /Textures/SearchTex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CeeJayDK/SweetFX/8d08f61ecb0727c486387b6ce78cf4eb33f55b41/Textures/SearchTex.png --------------------------------------------------------------------------------