├── AreaTex.png ├── SearchTex.png ├── README.md └── HQAALite.fx /AreaTex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lordbean-git/HQAA/HEAD/AreaTex.png -------------------------------------------------------------------------------- /SearchTex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lordbean-git/HQAA/HEAD/SearchTex.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HQAA 2 | Merges SMAA and FXAA aiming to balance both for high quality AA effect. 3 | This shader uses customized versions of SMAA and FXAA which have been 4 | built to detect edges in as many different scenarios as possible while 5 | still maintaining a very low rate of false positive detection. This 6 | allows HQAA to apply aggressive aliasing correction to the input 7 | scene while causing very few side effects (such as blur or artifacts). 8 | HQAA is a quality-focused shader and runs notably slower than SMAA or 9 | FXAA; however it is a very CPU-efficient shader as it is built to use 10 | operations that can be performed by hardware GPU math to the limit that 11 | it is possible. You will generally only see a framerate drop from HQAA 12 | if the game you are playing was being limited by your GPU rather than 13 | your CPU. For most older games, this means HQAA won't cause a noticeable 14 | difference in performance. 15 | 16 | You need the SMAA search textures (included here) placed in the ReShade 17 | texture search path for games you want to use HQAA with. 18 | -------------------------------------------------------------------------------- /HQAALite.fx: -------------------------------------------------------------------------------- 1 | /* HQAA for ReShade 3.1.1+ 2 | * 3 | * (Hybrid high-Quality Anti-Aliasing) 4 | * 5 | * 6 | * Smooshes FXAA and SMAA together as a single shader 7 | * 8 | * with customizations designed to maximize edge detection and 9 | * 10 | * minimize blurring 11 | * 12 | * by lordbean 13 | * 14 | */ 15 | 16 | // This shader includes code adapted from: 17 | 18 | /**============================================================================ 19 | 20 | 21 | NVIDIA FXAA 3.11 by TIMOTHY LOTTES 22 | 23 | 24 | ------------------------------------------------------------------------------ 25 | COPYRIGHT (C) 2010, 2011 NVIDIA CORPORATION. ALL RIGHTS RESERVED. 26 | ------------------------------------------------------------------------------*/ 27 | 28 | /* AMD CONTRAST ADAPTIVE SHARPENING 29 | // ======= 30 | // Copyright (c) 2017-2019 Advanced Micro Devices, Inc. All rights reserved. 31 | // ------- 32 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 33 | // files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 34 | // modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 35 | // Software is furnished to do so, subject to the following conditions: 36 | // ------- 37 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the 38 | // Software. 39 | // --------*/ 40 | 41 | /** SUBPIXEL MORPHOLOGICAL ANTI-ALIASING (SMAA) 42 | * Copyright (C) 2013 Jorge Jimenez (jorge@iryoku.com) 43 | * Copyright (C) 2013 Jose I. Echevarria (joseignacioechevarria@gmail.com) 44 | * Copyright (C) 2013 Belen Masia (bmasia@unizar.es) 45 | * Copyright (C) 2013 Fernando Navarro (fernandn@microsoft.com) 46 | * Copyright (C) 2013 Diego Gutierrez (diegog@unizar.es) 47 | **/ 48 | 49 | // All original code not attributed to the above authors is copyright (c) Derek Brush aka "lordbean" (derekbrush@gmail.com) 50 | 51 | /** Permission is hereby granted, free of charge, to any person obtaining a copy 52 | * this software and associated documentation files (the "Software"), to deal in 53 | * the Software without restriction, including without limitation the rights to 54 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 55 | * of the Software, and to permit persons to whom the Software is furnished to 56 | * do so, subject to the following conditions: 57 | * 58 | * The above copyright notice and this permission notice shall be included in 59 | * all copies or substantial portions of the Software. As clarification, there 60 | * is no requirement that the copyright notice and permission be included in 61 | * binary distributions of the Software. 62 | **/ 63 | 64 | /*------------------------------------------------------------------------------ 65 | * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 66 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 67 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 68 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 69 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 70 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 71 | * SOFTWARE. 72 | *-------------------------------------------------------------------------------*/ 73 | 74 | 75 | /*****************************************************************************************************************************************/ 76 | /*********************************************************** UI SETUP START **************************************************************/ 77 | /*****************************************************************************************************************************************/ 78 | 79 | #include "ReShadeUI.fxh" 80 | 81 | /////////////////////////////////////////////////////// CONFIGURABLE TOGGLES ////////////////////////////////////////////////////////////// 82 | 83 | #ifndef HQAAL_FXAA_MULTISAMPLING 84 | #define HQAAL_FXAA_MULTISAMPLING 2 85 | #endif 86 | #if HQAAL_FXAA_MULTISAMPLING > 6 || HQAAL_FXAA_MULTISAMPLING < 0 87 | #undef HQAAL_FXAA_MULTISAMPLING 88 | #define HQAAL_FXAA_MULTISAMPLING 2 89 | #endif 90 | 91 | #ifndef HQAAL_ADVANCED_MODE 92 | #define HQAAL_ADVANCED_MODE 0 93 | #endif 94 | #if HQAAL_ADVANCED_MODE > 1 || HQAAL_ADVANCED_MODE < 0 95 | #undef HQAAL_ADVANCED_MODE 96 | #define HQAAL_ADVANCED_MODE 0 97 | #endif 98 | 99 | uniform uint HqaaFramecounter < source = "framecount"; >; 100 | #define __HQAAL_ALT_FRAME ((HqaaFramecounter + HqaaSourceInterpolationOffset) % 2 == 0) 101 | #define __HQAAL_QUAD_FRAME ((HqaaFramecounter + HqaaSourceInterpolationOffset) % 4 == 1) 102 | #define __HQAAL_THIRD_FRAME (HqaaFramecounter % 3 == 1) 103 | 104 | /////////////////////////////////////////////////////// GLOBAL SETUP OPTIONS ////////////////////////////////////////////////////////////// 105 | 106 | uniform int HqaaAboutSTART < 107 | ui_type = "radio"; 108 | ui_label = " "; 109 | ui_text = "\n------------------------------- HQAA v28.19 Lite -------------------------------"; 110 | >; 111 | 112 | uniform int HQAAintroduction < 113 | ui_spacing = 3; 114 | ui_type = "radio"; 115 | ui_label = "Version: 28.19"; 116 | ui_text = "--------------------------------------------------------------------------------\n" 117 | "Hybrid high-Quality Anti-Aliasing, a shader by lordbean\n" 118 | "https://github.com/lordbean-git/HQAA/\n" 119 | "--------------------------------------------------------------------------------\n\n" 120 | 121 | "Currently Compiled Configuration:\n" 122 | #if HQAAL_ADVANCED_MODE 123 | "Advanced Mode: on *\n" 124 | #else 125 | "Advanced Mode: off\n" 126 | #endif 127 | #if HQAAL_FXAA_MULTISAMPLING < 2 128 | "FXAA Multisampling: off *\n" 129 | #elif HQAAL_FXAA_MULTISAMPLING > 5 130 | "FXAA Multisampling: on (6x) *\n" 131 | #elif HQAAL_FXAA_MULTISAMPLING > 4 132 | "FXAA Multisampling: on (5x) *\n" 133 | #elif HQAAL_FXAA_MULTISAMPLING > 3 134 | "FXAA Multisampling: on (4x) *\n" 135 | #elif HQAAL_FXAA_MULTISAMPLING > 2 136 | "FXAA Multisampling: on (3x) *\n" 137 | #elif HQAAL_FXAA_MULTISAMPLING > 1 138 | "FXAA Multisampling: on (2x)\n" 139 | #endif //HQAAL_FXAA_MULTISAMPLING 140 | 141 | "\n--------------------------------------------------------------------------------\n\n" 142 | 143 | "Remarks:\n" 144 | 145 | "\nFXAA Multisampling can be used to increase correction strength in cases such\n" 146 | "as edges with more than one color gradient or along objects that have highly\n" 147 | "irregular geometry. Costs some performance for each extra pass.\n" 148 | "Valid range: 1 to 6. Higher values are ignored.\n" 149 | 150 | "\n--------------------------------------------------------------------------------" 151 | "\nSee the 'Preprocessor definitions' section for color, feature, and mode toggles.\n" 152 | "--------------------------------------------------------------------------------"; 153 | ui_tooltip = "Lite Edition"; 154 | ui_category = "About"; 155 | ui_category_closed = true; 156 | >; 157 | 158 | uniform uint HqaaOutputMode < 159 | ui_type = "radio"; 160 | ui_spacing = 3; 161 | ui_label = " "; 162 | ui_items = "Normal (sRGB)\0HDR, Direct Nits Scale\0Perceptual Quantizer, Accurate (HDR10, scRGB)\0Perceptual Quantizer, Fast Transcode (HDR10, scRGB)\0"; 163 | ui_category = "Output Mode"; 164 | ui_category_closed = true; 165 | > = 0; 166 | 167 | uniform float HqaaHdrNits < 168 | ui_spacing = 3; 169 | ui_type = "slider"; 170 | ui_min = 300.0; ui_max = 10000.0; ui_step = 100.0; 171 | ui_label = "HDR Nits\n\n"; 172 | ui_tooltip = "If the scene brightness changes after HQAA runs, try\n" 173 | "adjusting this value up or down until it looks right.\n" 174 | "Only has effect when using the HDR Nits mode."; 175 | ui_category = "Output Mode"; 176 | ui_category_closed = true; 177 | > = 1000.0; 178 | 179 | uniform bool HqaaEnableSharpening < 180 | ui_spacing = 3; 181 | ui_label = "Enable Sharpening"; 182 | ui_tooltip = "Performs full-scene AMD Contrast-Adaptive Sharpening\n" 183 | "which uses SMAA edge data to reduce sharpen strength\n" 184 | "in regions containing edges. Automatically removed\n" 185 | "from the compiled shader when disabled and ReShade\n" 186 | "is in Performance Mode."; 187 | ui_category = "Sharpening"; 188 | ui_category_closed = true; 189 | > = true; 190 | 191 | uniform float HqaaSharpenerStrength < 192 | ui_type = "slider"; 193 | ui_spacing = 3; 194 | ui_min = 0; ui_max = 1; ui_step = 0.01; 195 | ui_label = "Sharpening Strength"; 196 | ui_tooltip = "Amount of sharpening to apply"; 197 | ui_category = "Sharpening"; 198 | ui_category_closed = true; 199 | > = 1.0; 200 | 201 | uniform float HqaaSharpenerAdaptation < 202 | ui_type = "slider"; 203 | ui_min = 0.0; ui_max = 1.0; ui_step = 0.01; 204 | ui_label = "Sharpening Contrast"; 205 | ui_tooltip = "Affects how much the CAS math will cause\ncontrasting details to stand out."; 206 | ui_category = "Sharpening"; 207 | ui_category_closed = true; 208 | > = 0.625; 209 | 210 | uniform float HqaaSharpenOffset < 211 | ui_type = "slider"; 212 | ui_min = 0.0; ui_max = 1.0; ui_step = 0.001; 213 | ui_label = "Sampling Offset"; 214 | ui_tooltip = "Scales the sample pattern up or down\n" 215 | "around the middle pixel. Helps to fine\n" 216 | "tune the overall CAS effect."; 217 | ui_category = "Sharpening"; 218 | ui_category_closed = true; 219 | > = 0.75; 220 | 221 | uniform float HqaaSharpenerClamping < 222 | ui_spacing = 3; 223 | ui_type = "slider"; 224 | ui_min = 0; ui_max = 1; ui_step = 0.001; 225 | ui_label = "Clamp Strength\n\n"; 226 | ui_tooltip = "How much to clamp sharpening strength when the pixel had AA applied to it\n" 227 | "Zero means no clamp applied, one means no sharpening applied"; 228 | ui_category = "Sharpening"; 229 | ui_category_closed = true; 230 | > = 0.5; 231 | 232 | uniform uint HqaaDebugMode < 233 | ui_type = "radio"; 234 | ui_category = "Debug"; 235 | ui_category_closed = true; 236 | ui_spacing = 3; 237 | ui_label = "Mouseover for info"; 238 | ui_text = "Debug Mode:"; 239 | ui_items = "Off\n\n\0Detected Edges\0SMAA Blend Weights\n\n\0FXAA Results\0FXAA Lumas\0FXAA Metrics\n\n\0Hysteresis Pattern\n\n\0Dynamic Threshold Usage\n\n\0Disable SMAA\0Disable FXAA\0\n\n"; 240 | ui_tooltip = "Useful primarily for learning what everything\n" 241 | "does when using advanced mode setup. Debug\n" 242 | "instructions are compiled out of the shader\n" 243 | "when 'Off' is selected and ReShade is in\n" 244 | "Performance Mode. You can find additional\n" 245 | "info on how to read each debug mode in the\n" 246 | "'DEBUG README' dropdown near the bottom."; 247 | > = 0; 248 | 249 | uniform int HqaaAboutEOF < 250 | ui_type = "radio"; 251 | ui_label = " "; 252 | ui_text = "\n--------------------------------------------------------------------------------"; 253 | >; 254 | 255 | #if !HQAAL_ADVANCED_MODE 256 | uniform uint HqaaPreset < 257 | ui_type = "combo"; 258 | ui_label = "Quality Preset"; 259 | ui_tooltip = "Quality of the Anti-Aliasing effect.\n" 260 | "Higher presets look better but take more\n" 261 | "GPU time to compute. Set HQAAL_ADVANCED_MODE\n" 262 | "to 1 to customize all options."; 263 | ui_items = "Low\0Medium\0High\0Ultra\0"; 264 | > = 2; 265 | 266 | static const float HqaaNoiseControlStrength = 20.; 267 | static const float HqaaLowLumaThreshold = 0.25; 268 | static const bool HqaaDoLumaHysteresis = true; 269 | static const bool HqaaFxEarlyExit = true; 270 | static const uint HqaaSourceInterpolation = 0; 271 | static const uint HqaaSourceInterpolationOffset = 0; 272 | 273 | #else 274 | uniform float HqaaEdgeThresholdCustom < 275 | ui_type = "slider"; 276 | ui_min = 0.0; ui_max = 1.0; 277 | ui_spacing = 3; 278 | ui_label = "Edge Detection Threshold"; 279 | ui_tooltip = "Local contrast required to be considered an edge"; 280 | ui_category = "Edge Detection"; 281 | ui_category_closed = true; 282 | > = 0.05; 283 | 284 | uniform float HqaaLowLumaThreshold < 285 | ui_type = "slider"; 286 | ui_min = 0.0; ui_max = 1.0; ui_step = 0.001; 287 | ui_label = "Low Luma Threshold"; 288 | ui_tooltip = "Luma level below which dynamic thresholding activates"; 289 | ui_spacing = 3; 290 | ui_category = "Edge Detection"; 291 | ui_category_closed = true; 292 | > = 0.25; 293 | 294 | uniform float HqaaDynamicThresholdCustom < 295 | ui_type = "slider"; 296 | ui_min = 0; ui_max = 100; ui_step = 1; 297 | ui_label = "% Dynamic Range"; 298 | ui_tooltip = "Maximum reduction of edge threshold (% base threshold)\n" 299 | "permitted when detecting low-brightness edges.\n" 300 | "Lower = faster, might miss low-contrast edges\n" 301 | "Higher = slower, catches more edges in dark scenes"; 302 | ui_category = "Edge Detection"; 303 | ui_category_closed = true; 304 | > = 75; 305 | 306 | uniform uint HqaaFxQualityCustom < 307 | ui_spacing = 3; 308 | ui_type = "slider"; 309 | ui_min = 5; ui_max = 100; ui_step = 1; 310 | ui_label = "Scan Distance"; 311 | ui_tooltip = "Maximum radius from center dot\nthat SMAA and FXAA will scan."; 312 | ui_category = "Edge Detection"; 313 | ui_category_closed = true; 314 | > = 64; 315 | 316 | uniform float HqaaNoiseControlStrength < 317 | ui_type = "slider"; 318 | ui_min = 0; ui_max = 100; ui_step = 1; 319 | ui_label = "Noise Control Strength"; 320 | ui_tooltip = "Controls how strongly AA blending will be clamped when\n" 321 | "the output would cause a high luma delta."; 322 | ui_category = "Edge Detection"; 323 | ui_category_closed = true; 324 | > = 20.; 325 | 326 | uniform uint HqaaSourceInterpolation < 327 | ui_type = "combo"; 328 | ui_spacing = 9; 329 | ui_label = "Edge Detection Interpolation"; 330 | ui_tooltip = "Offsets edge detection passes by either\n" 331 | "two or four frames when enabled. This is\n" 332 | "intended for specific usage cases where\n" 333 | "the game's framerate is interpolated from\n" 334 | "a low value to a higher one (eg capped 30\n" 335 | "interpolated to 60fps). For the vast\n" 336 | "majority of games, leave this setting off."; 337 | ui_items = "Off\0Single Interpolation\0Double Interpolation\0"; 338 | ui_category = "Edge Detection"; 339 | ui_category_closed = true; 340 | > = 0; 341 | 342 | uniform uint HqaaSourceInterpolationOffset < 343 | ui_type = "slider"; 344 | ui_min = 0; ui_max = 3; ui_step = 1; 345 | ui_label = "Frame Count Offset\n\n"; 346 | ui_tooltip = "Arbitrary offset applied when determining whether\n" 347 | "to run or skip edge detection when using interpolation.\n" 348 | "Adjust this if there seems to be synchronization\n" 349 | "problems visible in the output."; 350 | ui_category = "Edge Detection"; 351 | ui_category_closed = true; 352 | > = 0; 353 | 354 | uniform float HqaaSmCorneringCustom < 355 | ui_spacing = 3; 356 | ui_type = "slider"; 357 | ui_min = 0; ui_max = 100; ui_step = 1; 358 | ui_spacing = 2; 359 | ui_label = "% Corner Rounding\n\n"; 360 | ui_tooltip = "Affects the amount of blending performed when SMAA\ndetects crossing edges"; 361 | ui_category = "SMAA"; 362 | ui_category_closed = true; 363 | > = 50; 364 | 365 | uniform float HqaaFxTexelCustom < 366 | ui_type = "slider"; 367 | ui_min = 0.1; ui_max = 2.0; ui_step = 0.01; 368 | ui_spacing = 3; 369 | ui_label = "Edge Gradient Texel Size"; 370 | ui_tooltip = "Determines how far along an edge FXAA will move\nfrom one scan iteration to the next.\n\nLower = slower, more accurate\nHigher = faster, causes more blur"; 371 | ui_category = "FXAA"; 372 | ui_category_closed = true; 373 | > = 0.5; 374 | 375 | uniform float HqaaFxBlendCustom < 376 | ui_type = "slider"; 377 | ui_min = 0; ui_max = 100; ui_step = 1; 378 | ui_label = "% Blending Strength"; 379 | ui_tooltip = "Percentage of blending FXAA will apply to edges.\n" 380 | "Lower = sharper image, Higher = more AA effect"; 381 | ui_category = "FXAA"; 382 | ui_category_closed = true; 383 | > = 100; 384 | 385 | uniform bool HqaaFxEarlyExit < 386 | ui_label = "Allow Early Exit\n\n"; 387 | ui_tooltip = "Normally, FXAA will early-exit when the\n" 388 | "local contrast doesn't exceed the edge\n" 389 | "threshold. Uncheck this to force FXAA to\n" 390 | "process the entire scene."; 391 | ui_spacing = 3; 392 | ui_category = "FXAA"; 393 | ui_category_closed = true; 394 | > = true; 395 | 396 | uniform bool HqaaDoLumaHysteresis < 397 | ui_spacing = 3; 398 | ui_label = "Enable Hysteresis"; 399 | ui_tooltip = "Hysteresis measures the luma of each pixel\n" 400 | "before and affer changes are made to it and\n" 401 | "uses the delta to reconstruct detail from\n" 402 | "the original scene."; 403 | ui_category = "Hysteresis"; 404 | ui_category_closed = true; 405 | > = false; 406 | 407 | uniform float HqaaHysteresisStrength < 408 | ui_type = "slider"; 409 | ui_spacing = 3; 410 | ui_min = 0; ui_max = 100; ui_step = 0.1; 411 | ui_label = "% Strength"; 412 | ui_tooltip = "0% = Off (keep anti-aliasing result as-is)\n100% = Aggressive Correction"; 413 | ui_category = "Hysteresis"; 414 | ui_category_closed = true; 415 | > = 40.0; 416 | 417 | uniform float HqaaHysteresisFudgeFactor < 418 | ui_type = "slider"; 419 | ui_min = 0; ui_max = 25; ui_step = 0.01; 420 | ui_label = "% Fudge Factor\n\n"; 421 | ui_tooltip = "Ignore up to this much difference between the\noriginal pixel and the anti-aliasing result"; 422 | ui_category = "Hysteresis"; 423 | ui_category_closed = true; 424 | > = 0.0; 425 | #endif //HQAAL_ADVANCED_MODE 426 | 427 | uniform int HqaaOptionsEOF < 428 | ui_type = "radio"; 429 | ui_label = " "; 430 | ui_text = "\n--------------------------------------------------------------------------------"; 431 | >; 432 | 433 | uniform int HqaaDebugExplainer < 434 | ui_type = "radio"; 435 | ui_spacing = 3; 436 | ui_label = " "; 437 | ui_text = "----------------------------------------------------------------\n" 438 | "When viewing the detected edges, the colors shown in the texture\n" 439 | "are not related to the image on the screen directly, rather they\n" 440 | "are markers indicating the following:\n" 441 | "- Green = Probable Horizontal Edge Here\n" 442 | "- Red = Probable Vertical Edge Here\n" 443 | "- Yellow = Probable Diagonal Edge Here\n\n" 444 | "SMAA blending weights and FXAA results show what each related\n" 445 | "pass is rendering to the screen to produce its AA effect.\n\n" 446 | "The FXAA luma view compresses its calculated range to 0.25-1.0\n" 447 | "so that black pixels mean the shader didn't run in that area.\n" 448 | "Grayscale values represent edges detected using luma, red values\n" 449 | "represent edges detected using chroma.\n\n" 450 | "FXAA metrics draws a range of green to red where the selected\n" 451 | "pass ran, with green representing not much execution time used\n" 452 | "and red representing a lot of execution time used.\n\n" 453 | "The Hysteresis pattern is a representation of where and how\n" 454 | "strongly the hysteresis pass is performing corrections, but it\n" 455 | "does not directly indicate the color that it is blending (it is\n" 456 | "the absolute value of a difference calculation, meaning that\n" 457 | "decreases are the visual inversion of the actual blend color).\n\n" 458 | "Dynamic Threshold Usage displays black pixels if no reduction\n" 459 | "was applied and green pixels representing a lowered threshold,\n" 460 | "brighter dots indicating stronger reductions.\n" 461 | "----------------------------------------------------------------"; 462 | ui_category = "DEBUG README"; 463 | ui_category_closed = true; 464 | >; 465 | 466 | ///////////////////////////////////////////////// HUMAN+MACHINE PRESET REFERENCE ////////////////////////////////////////////////////////// 467 | 468 | #if HQAAL_ADVANCED_MODE 469 | uniform int HqaaPresetBreakdown < 470 | ui_type = "radio"; 471 | ui_label = " "; 472 | ui_text = "\n" 473 | "---------------------------------------------------------------------------------\n" 474 | "| | Edges | SMAA | FXAA | Hysteresis |\n" 475 | "|--Preset|-Threshold---Range---Dist-|-Corner-|-Texel---Blend-|-Strength---Fudge-|\n" 476 | "|--------|-----------|-------|------|--------|-------|-------|----------|-------|\n" 477 | "| Low| .12 | 66.7% | 16 | 0% | 1.0 | 75% | 50% | 6.0% |\n" 478 | "| Medium| .08 | 75.0% | 32 | 12% | 1/2 | 83% | 33% | 4.0% |\n" 479 | "| High| .06 | 66.7% | 48 | 20% | 1/3 | 87% | 20% | 3.0% |\n" 480 | "| Ultra| .04 | 75.0% | 64 | 25% | 1/4 | 90% | 12% | 2.0% |\n" 481 | "---------------------------------------------------------------------------------"; 482 | ui_category = "Click me to see what settings each preset uses!"; 483 | ui_category_closed = true; 484 | >; 485 | 486 | #define __HQAAL_EDGE_THRESHOLD (HqaaEdgeThresholdCustom) 487 | #define __HQAAL_DYNAMIC_RANGE (HqaaDynamicThresholdCustom / 100.0) 488 | #define __HQAAL_SM_CORNERS (HqaaSmCorneringCustom / 100.0) 489 | #define __HQAAL_FX_QUALITY (HqaaFxQualityCustom) 490 | #define __HQAAL_FX_TEXEL (HqaaFxTexelCustom) 491 | #define __HQAAL_FX_BLEND (HqaaFxBlendCustom / 100.0) 492 | #define __HQAAL_HYSTERESIS_STRENGTH (HqaaHysteresisStrength / 100.0) 493 | #define __HQAAL_HYSTERESIS_FUDGE (HqaaHysteresisFudgeFactor / 100.0) 494 | 495 | #else 496 | 497 | static const float HQAAL_THRESHOLD_PRESET[4] = {0.12, 0.08, 0.06, 0.04}; 498 | static const float HQAAL_DYNAMIC_RANGE_PRESET[4] = {0.666667, 0.75, 0.666667, 0.75}; 499 | static const uint HQAAL_FXAA_SCAN_ITERATIONS_PRESET[4] = {16, 32, 48, 64}; 500 | static const float HQAAL_SMAA_CORNER_ROUNDING_PRESET[4] = {0.0, 0.125, 0.2, 0.25}; 501 | static const float HQAAL_FXAA_TEXEL_SIZE_PRESET[4] = {1.0, 0.5, 0.333333, 0.25}; 502 | static const float HQAAL_SUBPIX_PRESET[4] = {0.75, 0.833333, 0.875, 0.9}; 503 | static const float HQAAL_HYSTERESIS_STRENGTH_PRESET[4] = {0.5, 0.333333, 0.2, 0.125}; 504 | static const float HQAAL_HYSTERESIS_FUDGE_PRESET[4] = {0.06, 0.04, 0.03, 0.02}; 505 | 506 | #define __HQAAL_EDGE_THRESHOLD (HQAAL_THRESHOLD_PRESET[HqaaPreset]) 507 | #define __HQAAL_DYNAMIC_RANGE (HQAAL_DYNAMIC_RANGE_PRESET[HqaaPreset]) 508 | #define __HQAAL_SM_CORNERS (HQAAL_SMAA_CORNER_ROUNDING_PRESET[HqaaPreset]) 509 | #define __HQAAL_FX_QUALITY (HQAAL_FXAA_SCAN_ITERATIONS_PRESET[HqaaPreset]) 510 | #define __HQAAL_FX_TEXEL (HQAAL_FXAA_TEXEL_SIZE_PRESET[HqaaPreset]) 511 | #define __HQAAL_FX_BLEND (HQAAL_SUBPIX_PRESET[HqaaPreset]) 512 | #define __HQAAL_HYSTERESIS_STRENGTH (HQAAL_HYSTERESIS_STRENGTH_PRESET[HqaaPreset]) 513 | #define __HQAAL_HYSTERESIS_FUDGE (HQAAL_HYSTERESIS_FUDGE_PRESET[HqaaPreset]) 514 | 515 | #endif //HQAAL_ADVANCED_MODE 516 | 517 | #define __HQAAL_SM_RADIUS float(__HQAAL_FX_QUALITY) 518 | #define __HQAAL_SM_AREATEX_RANGE_DIAG clamp(__HQAAL_SM_RADIUS, 0.0, 20.0) 519 | 520 | /*****************************************************************************************************************************************/ 521 | /*********************************************************** UI SETUP END ****************************************************************/ 522 | /*****************************************************************************************************************************************/ 523 | 524 | /*****************************************************************************************************************************************/ 525 | /******************************************************** SYNTAX SETUP START *************************************************************/ 526 | /*****************************************************************************************************************************************/ 527 | 528 | #define __HQAAL_SMALLEST_COLOR_STEP rcp(pow(2., BUFFER_COLOR_BIT_DEPTH)) 529 | #define __HQAAL_CONST_E 2.7182818284590452353602874713527 530 | #define __HQAAL_CONST_HALFROOT2 (sqrt(2.)/2.) 531 | #define __HQAAL_LUMA_REF float3(0.2126, 0.7152, 0.0722) 532 | #define __HQAAL_AVERAGE_REF float3(0.333333, 0.333334, 0.333333) 533 | #define __HQAAL_GREEN_LUMA float3(1./5., 7./10., 1./10.) 534 | #define __HQAAL_RED_LUMA float3(5./8., 1./4., 1./8.) 535 | #define __HQAAL_BLUE_LUMA float3(1./8., 3./8., 1./2.) 536 | 537 | #define __HQAAL_SM_BUFFERINFO float4(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT, BUFFER_WIDTH, BUFFER_HEIGHT) 538 | #define __HQAAL_SM_AREATEX_RANGE 16. 539 | #define __HQAAL_SM_AREATEX_TEXEL (1./float2(160., 560.)) 540 | #define __HQAAL_SM_AREATEX_SUBTEXEL (1./7.) 541 | #define __HQAAL_SM_SEARCHTEX_SIZE float2(66.0, 33.0) 542 | #define __HQAAL_SM_SEARCHTEX_SIZE_PACKED float2(64.0, 16.0) 543 | 544 | #define HQAAL_Tex2D(tex, coord) tex2Dlod(tex, (coord).xyxy) 545 | #define HQAAL_DecodeTex2D(tex, coord) ConditionalDecode(tex2Dlod(tex, (coord).xyxy)) 546 | 547 | #define HQAALmax3(x,y,z) max(max(x,y),z) 548 | #define HQAALmax4(w,x,y,z) max(max(w,x),max(y,z)) 549 | #define HQAALmax5(v,w,x,y,z) max(max(max(v,w),x),max(y,z)) 550 | #define HQAALmax6(u,v,w,x,y,z) max(max(max(u,v),max(w,x)),max(y,z)) 551 | #define HQAALmax7(t,u,v,w,x,y,z) max(max(max(t,u),max(v,w)),max(max(x,y),z)) 552 | #define HQAALmax8(s,t,u,v,w,x,y,z) max(max(max(s,t),max(u,v)),max(max(w,x),max(y,z))) 553 | #define HQAALmax9(r,s,t,u,v,w,x,y,z) max(max(max(max(r,s),t),max(u,v)),max(max(w,x),max(y,z))) 554 | #define HQAALmax10(q,r,s,t,u,v,w,x,y,z) max(max(max(max(q,r),max(s,t)),max(u,v)),max(max(w,x),max(y,z))) 555 | #define HQAALmax11(p,q,r,s,t,u,v,w,x,y,z) max(max(max(max(p,q),max(r,s)),max(max(t,u),v)),max(max(w,x),max(y,z))) 556 | #define HQAALmax12(o,p,q,r,s,t,u,v,w,x,y,z) max(max(max(max(o,p),max(q,r)),max(max(s,t),max(u,v))),max(max(w,x),max(y,z))) 557 | #define HQAALmax13(n,o,p,q,r,s,t,u,v,w,x,y,z) max(max(max(max(n,o),max(p,q)),max(max(r,s),max(t,u))),max(max(max(v,w),x),max(y,z))) 558 | #define HQAALmax14(m,n,o,p,q,r,s,t,u,v,w,x,y,z) max(max(max(max(m,n),max(o,p)),max(max(q,r),max(s,t))),max(max(max(u,v),max(w,x)),max(y,z))) 559 | 560 | #define HQAALmin3(x,y,z) min(min(x,y),z) 561 | #define HQAALmin4(w,x,y,z) min(min(w,x),min(y,z)) 562 | #define HQAALmin5(v,w,x,y,z) min(min(min(v,w),x),min(y,z)) 563 | #define HQAALmin6(u,v,w,x,y,z) min(min(min(u,v),min(w,x)),min(y,z)) 564 | #define HQAALmin7(t,u,v,w,x,y,z) min(min(min(t,u),min(v,w)),min(min(x,y),z)) 565 | #define HQAALmin8(s,t,u,v,w,x,y,z) min(min(min(s,t),min(u,v)),min(min(w,x),min(y,z))) 566 | #define HQAALmin9(r,s,t,u,v,w,x,y,z) min(min(min(min(r,s),t),min(u,v)),min(min(w,x),min(y,z))) 567 | #define HQAALmin10(q,r,s,t,u,v,w,x,y,z) min(min(min(min(q,r),min(s,t)),min(u,v)),min(min(w,x),min(y,z))) 568 | #define HQAALmin11(p,q,r,s,t,u,v,w,x,y,z) min(min(min(min(p,q),min(r,s)),min(min(t,u),v)),min(min(w,x),min(y,z))) 569 | #define HQAALmin12(o,p,q,r,s,t,u,v,w,x,y,z) min(min(min(min(o,p),min(q,r)),min(min(s,t),min(u,v))),min(min(w,x),min(y,z))) 570 | #define HQAALmin13(n,o,p,q,r,s,t,u,v,w,x,y,z) min(min(min(min(n,o),min(p,q)),min(min(r,s),min(t,u))),min(min(min(v,w),x),min(y,z))) 571 | #define HQAALmin14(m,n,o,p,q,r,s,t,u,v,w,x,y,z) min(min(min(min(m,n),min(o,p)),min(min(q,r),min(s,t))),min(min(min(u,v),min(w,x)),min(y,z))) 572 | 573 | /*****************************************************************************************************************************************/ 574 | /********************************************************* SYNTAX SETUP END **************************************************************/ 575 | /*****************************************************************************************************************************************/ 576 | 577 | /*****************************************************************************************************************************************/ 578 | /******************************************************** SUPPORT CODE START *************************************************************/ 579 | /*****************************************************************************************************************************************/ 580 | 581 | //////////////////////////////////////////////////////// HELPER FUNCTIONS //////////////////////////////////////////////////////////////// 582 | 583 | // vectorized multiple single-component max operations 584 | float max3(float a, float b, float c) 585 | { 586 | return max(max(a,b),c); 587 | } 588 | float max4(float a, float b, float c, float d) 589 | { 590 | float2 step1 = max(float2(a,b), float2(c,d)); 591 | return max(step1.x, step1.y); 592 | } 593 | float max5(float a, float b, float c, float d, float e) 594 | { 595 | float2 step1 = max(float2(a,b), float2(c,d)); 596 | return max(max(step1.x, step1.y), e); 597 | } 598 | float max6(float a, float b, float c, float d, float e, float f) 599 | { 600 | float2 step1 = max(max(float2(a,b), float2(c,d)), float2(e,f)); 601 | return max(step1.x, step1.y); 602 | } 603 | float max7(float a, float b, float c, float d, float e, float f, float g) 604 | { 605 | float2 step1 = max(max(float2(a,b), float2(c,d)), float2(e,f)); 606 | return max(max(step1.x, step1.y), g); 607 | } 608 | float max8(float a, float b, float c, float d, float e, float f, float g, float h) 609 | { 610 | float4 step1 = max(float4(a,b,c,d), float4(e,f,g,h)); 611 | float2 step2 = max(step1.xy, step1.zw); 612 | return max(step2.x, step2.y); 613 | } 614 | float max9(float a, float b, float c, float d, float e, float f, float g, float h, float i) 615 | { 616 | float4 step1 = max(float4(a,b,c,d), float4(e,f,g,h)); 617 | float2 step2 = max(step1.xy, step1.zw); 618 | return max(max(step2.x, step2.y), i); 619 | } 620 | float max10(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j) 621 | { 622 | float4 step1 = max(float4(a,b,c,d), float4(e,f,g,h)); 623 | float2 step2 = max(step1.xy, step1.zw); 624 | return max(max(step2.x, step2.y), max(i, j)); 625 | } 626 | float max11(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k) 627 | { 628 | float4 step1 = max(float4(a,b,c,d), float4(e,f,g,h)); 629 | float2 step2 = max(step1.xy, step1.zw); 630 | return max(max(max(step2.x, step2.y), max(i, j)), k); 631 | } 632 | float max12(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l) 633 | { 634 | float4 step1 = max(float4(a,b,c,d), float4(e,f,g,h)); 635 | float2 step2 = max(step1.xy, step1.zw); 636 | float2 step3 = max(float2(i,j), float2(k,l)); 637 | float2 step4 = max(step2, step3); 638 | return max(step4.x, step4.y); 639 | } 640 | float max13(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m) 641 | { 642 | float4 step1 = max(float4(a,b,c,d), float4(e,f,g,h)); 643 | float2 step2 = max(step1.xy, step1.zw); 644 | float2 step3 = max(float2(i,j), float2(k,l)); 645 | float2 step4 = max(step2, step3); 646 | return max(max(step4.x, step4.y), m); 647 | } 648 | float max14(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n) 649 | { 650 | float4 step1 = max(float4(a,b,c,d), float4(e,f,g,h)); 651 | float2 step2 = max(step1.xy, step1.zw); 652 | float2 step3 = max(float2(i,j), float2(k,l)); 653 | float2 step4 = max(step2, step3); 654 | return max(max(step4.x, step4.y), max(m, n)); 655 | } 656 | float max15(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o) 657 | { 658 | float4 step1 = max(float4(a,b,c,d), float4(e,f,g,h)); 659 | float2 step2 = max(step1.xy, step1.zw); 660 | float2 step3 = max(float2(i,j), float2(k,l)); 661 | float2 step4 = max(step2, step3); 662 | return max(max(step4.x, step4.y), max(m, max(n, o))); 663 | } 664 | float max16(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p) 665 | { 666 | float4 step1 = max(float4(a,b,c,d), float4(e,f,g,h)); 667 | float4 step2 = max(float4(i,j,k,l), float4(m,n,o,p)); 668 | float4 step3 = max(step1, step2); 669 | float2 step4 = max(step3.xy, step3.zw); 670 | return max(step4.x, step4.y); 671 | } 672 | 673 | // vectorized multiple single-component min operations 674 | float min3(float a, float b, float c) 675 | { 676 | return min(min(a,b),c); 677 | } 678 | float min4(float a, float b, float c, float d) 679 | { 680 | float2 step1 = min(float2(a,b), float2(c,d)); 681 | return min(step1.x, step1.y); 682 | } 683 | float min5(float a, float b, float c, float d, float e) 684 | { 685 | float2 step1 = min(float2(a,b), float2(c,d)); 686 | return min(min(step1.x, step1.y), e); 687 | } 688 | float min6(float a, float b, float c, float d, float e, float f) 689 | { 690 | float2 step1 = min(min(float2(a,b), float2(c,d)), float2(e,f)); 691 | return min(step1.x, step1.y); 692 | } 693 | float min7(float a, float b, float c, float d, float e, float f, float g) 694 | { 695 | float2 step1 = min(min(float2(a,b), float2(c,d)), float2(e,f)); 696 | return min(min(step1.x, step1.y), g); 697 | } 698 | float min8(float a, float b, float c, float d, float e, float f, float g, float h) 699 | { 700 | float4 step1 = min(float4(a,b,c,d), float4(e,f,g,h)); 701 | float2 step2 = min(step1.xy, step1.zw); 702 | return min(step2.x, step2.y); 703 | } 704 | float min9(float a, float b, float c, float d, float e, float f, float g, float h, float i) 705 | { 706 | float4 step1 = min(float4(a,b,c,d), float4(e,f,g,h)); 707 | float2 step2 = min(step1.xy, step1.zw); 708 | return min(min(step2.x, step2.y), i); 709 | } 710 | float min10(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j) 711 | { 712 | float4 step1 = min(float4(a,b,c,d), float4(e,f,g,h)); 713 | float2 step2 = min(step1.xy, step1.zw); 714 | return min(min(step2.x, step2.y), min(i, j)); 715 | } 716 | float min11(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k) 717 | { 718 | float4 step1 = min(float4(a,b,c,d), float4(e,f,g,h)); 719 | float2 step2 = min(step1.xy, step1.zw); 720 | return min(min(min(step2.x, step2.y), min(i, j)), k); 721 | } 722 | float min12(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l) 723 | { 724 | float4 step1 = min(float4(a,b,c,d), float4(e,f,g,h)); 725 | float2 step2 = min(step1.xy, step1.zw); 726 | float2 step3 = min(float2(i,j), float2(k,l)); 727 | float2 step4 = min(step2, step3); 728 | return min(step4.x, step4.y); 729 | } 730 | float min13(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m) 731 | { 732 | float4 step1 = min(float4(a,b,c,d), float4(e,f,g,h)); 733 | float2 step2 = min(step1.xy, step1.zw); 734 | float2 step3 = min(float2(i,j), float2(k,l)); 735 | float2 step4 = min(step2, step3); 736 | return min(min(step4.x, step4.y), m); 737 | } 738 | float min14(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n) 739 | { 740 | float4 step1 = min(float4(a,b,c,d), float4(e,f,g,h)); 741 | float2 step2 = min(step1.xy, step1.zw); 742 | float2 step3 = min(float2(i,j), float2(k,l)); 743 | float2 step4 = min(step2, step3); 744 | return min(min(step4.x, step4.y), min(m, n)); 745 | } 746 | float min15(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o) 747 | { 748 | float4 step1 = min(float4(a,b,c,d), float4(e,f,g,h)); 749 | float2 step2 = min(step1.xy, step1.zw); 750 | float2 step3 = min(float2(i,j), float2(k,l)); 751 | float2 step4 = min(step2, step3); 752 | return min(min(step4.x, step4.y), min(m, min(n, o))); 753 | } 754 | float min16(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l, float m, float n, float o, float p) 755 | { 756 | float4 step1 = min(float4(a,b,c,d), float4(e,f,g,h)); 757 | float4 step2 = min(float4(i,j,k,l), float4(m,n,o,p)); 758 | float4 step3 = min(step1, step2); 759 | float2 step4 = min(step3.xy, step3.zw); 760 | return min(step4.x, step4.y); 761 | } 762 | 763 | // color delta calculator 764 | float chromadelta(float3 pixel1, float3 pixel2) 765 | { 766 | return dot(abs(pixel1 - pixel2), __HQAAL_AVERAGE_REF); 767 | } 768 | 769 | // non-bitwise logical operators 770 | float lxor(float x, float y) 771 | { 772 | bool valid = (x == 0.0) ? ((y == 0.0) ? false : true) : ((y == 0.0) ? true : false); 773 | if (valid) return x + y; 774 | else return 0.0; 775 | } 776 | float2 lxor(float2 x, float2 y) 777 | { 778 | return float2(lxor(x.x, y.x), lxor(x.y, y.y)); 779 | } 780 | float3 lxor(float3 x, float3 y) 781 | { 782 | return float3(lxor(x.x, y.x), lxor(x.yz, y.yz)); 783 | } 784 | float4 lxor(float4 x, float4 y) 785 | { 786 | return float4(lxor(x.xy, y.xy), lxor(x.zw, y.zw)); 787 | } 788 | 789 | float lnand(float x, float y) 790 | { 791 | return y == 0.0 ? x : 0.0; 792 | } 793 | float2 lnand(float2 x, float2 y) 794 | { 795 | return float2(lnand(x.x, y.x), lnand(x.y, y.y)); 796 | } 797 | float3 lnand(float3 x, float3 y) 798 | { 799 | return float3(lnand(x.x, y.x), lnand(x.yz, y.yz)); 800 | } 801 | float4 lnand(float4 x, float4 y) 802 | { 803 | return float4(lnand(x.xy, y.xy), lnand(x.zw, y.zw)); 804 | } 805 | 806 | /////////////////////////////////////////////////////// TRANSFER FUNCTIONS //////////////////////////////////////////////////////////////// 807 | 808 | float encodePQ(float x) 809 | { 810 | /* float nits = 10000.0 811 | float m2rcp = rcp(2523/32) 812 | float m1rcp = rcp(1305/8192) 813 | float c1 = 107 / 128 814 | float c2 = 2413 / 128 815 | float c3 = 2392 / 128 816 | */ 817 | float xpm2rcp = pow(saturate(x), rcp(2523./32.)); 818 | float numerator = max(xpm2rcp - 107./128., 0.0); 819 | float denominator = 2413./128. - ((2392./128.) * xpm2rcp); 820 | 821 | float output = pow(abs(numerator / denominator), rcp(1305./8192.)); 822 | if (BUFFER_COLOR_BIT_DEPTH == 10) output *= 500.0; 823 | else output *= 10000.0; 824 | return output; 825 | } 826 | float2 encodePQ(float2 x) 827 | { 828 | float2 xpm2rcp = pow(saturate(x), rcp(2523./32.)); 829 | float2 numerator = max(xpm2rcp - 107./128., 0.0); 830 | float2 denominator = 2413./128. - ((2392./128.) * xpm2rcp); 831 | 832 | float2 output = pow(abs(numerator / denominator), rcp(1305./8192.)); 833 | if (BUFFER_COLOR_BIT_DEPTH == 10) output *= 500.0; 834 | else output *= 10000.0; 835 | return output; 836 | } 837 | float3 encodePQ(float3 x) 838 | { 839 | float3 xpm2rcp = pow(saturate(x), rcp(2523./32.)); 840 | float3 numerator = max(xpm2rcp - 107./128., 0.0); 841 | float3 denominator = 2413./128. - ((2392./128.) * xpm2rcp); 842 | 843 | float3 output = pow(abs(numerator / denominator), rcp(1305./8192.)); 844 | if (BUFFER_COLOR_BIT_DEPTH == 10) output *= 500.0; 845 | else output *= 10000.0; 846 | return output; 847 | } 848 | float4 encodePQ(float4 x) 849 | { 850 | float4 xpm2rcp = pow(saturate(x), rcp(2523./32.)); 851 | float4 numerator = max(xpm2rcp - 107./128., 0.0); 852 | float4 denominator = 2413./128. - ((2392./128.) * xpm2rcp); 853 | 854 | float4 output = pow(abs(numerator / denominator), rcp(1305./8192.)); 855 | if (BUFFER_COLOR_BIT_DEPTH == 10) output *= 500.0; 856 | else output *= 10000.0; 857 | return output; 858 | } 859 | 860 | float decodePQ(float x) 861 | { 862 | /* float nits = 10000.0; 863 | float m2 = 2523 / 32 864 | float m1 = 1305 / 8192 865 | float c1 = 107 / 128 866 | float c2 = 2413 / 128 867 | float c3 = 2392 / 128 868 | */ 869 | float xpm1; 870 | if (BUFFER_COLOR_BIT_DEPTH == 10) xpm1 = pow(saturate(x / 500.0), 1305./8192.); 871 | else xpm1 = pow(saturate(x / 10000.0), 1305./8192.); 872 | float numerator = 107./128. + ((2413./128.) * xpm1); 873 | float denominator = 1.0 + ((2392./128.) * xpm1); 874 | 875 | return saturate(pow(abs(numerator / denominator), 2523./32.)); 876 | } 877 | float2 decodePQ(float2 x) 878 | { 879 | float2 xpm1; 880 | if (BUFFER_COLOR_BIT_DEPTH == 10) xpm1 = pow(saturate(x / 500.0), 1305./8192.); 881 | else xpm1 = pow(saturate(x / 10000.0), 1305./8192.); 882 | float2 numerator = 107./128. + ((2413./128.) * xpm1); 883 | float2 denominator = 1.0 + ((2392./128.) * xpm1); 884 | 885 | return saturate(pow(abs(numerator / denominator), 2523./32.)); 886 | } 887 | float3 decodePQ(float3 x) 888 | { 889 | float3 xpm1; 890 | if (BUFFER_COLOR_BIT_DEPTH == 10) xpm1 = pow(saturate(x / 500.0), 1305./8192.); 891 | else xpm1 = pow(saturate(x / 10000.0), 1305./8192.); 892 | float3 numerator = 107./128. + ((2413./128.) * xpm1); 893 | float3 denominator = 1.0 + ((2392./128.) * xpm1); 894 | 895 | return saturate(pow(abs(numerator / denominator), 2523./32.)); 896 | } 897 | float4 decodePQ(float4 x) 898 | { 899 | float4 xpm1; 900 | if (BUFFER_COLOR_BIT_DEPTH == 10) xpm1 = pow(saturate(x / 500.0), 1305./8192.); 901 | else xpm1 = pow(saturate(x / 10000.0), 1305./8192.); 902 | float4 numerator = 107./128. + ((2413./128.) * xpm1); 903 | float4 denominator = 1.0 + ((2392./128.) * xpm1); 904 | 905 | return saturate(pow(abs(numerator / denominator), 2523./32.)); 906 | } 907 | 908 | float fastencodePQ(float x) 909 | { 910 | float y; 911 | float z; 912 | if (BUFFER_COLOR_BIT_DEPTH == 10) {y = saturate(x) * 4.728708; z = 500.0;} 913 | else {y = saturate(x) * 10.0; z = 10000.0;} 914 | y *= y; 915 | y *= y; 916 | return clamp(y, 0.0, z); 917 | } 918 | float2 fastencodePQ(float2 x) 919 | { 920 | float2 y; 921 | float z; 922 | if (BUFFER_COLOR_BIT_DEPTH == 10) {y = saturate(x) * 4.728708; z = 500.0;} 923 | else {y = saturate(x) * 10.0; z = 10000.0;} 924 | y *= y; 925 | y *= y; 926 | return clamp(y, 0.0, z); 927 | } 928 | float3 fastencodePQ(float3 x) 929 | { 930 | float3 y; 931 | float z; 932 | if (BUFFER_COLOR_BIT_DEPTH == 10) {y = saturate(x) * 4.728708; z = 500.0;} 933 | else {y = saturate(x) * 10.0; z = 10000.0;} 934 | y *= y; 935 | y *= y; 936 | return clamp(y, 0.0, z); 937 | } 938 | float4 fastencodePQ(float4 x) 939 | { 940 | float4 y; 941 | float z; 942 | if (BUFFER_COLOR_BIT_DEPTH == 10) {y = saturate(x) * 4.728708; z = 500.0;} 943 | else {y = saturate(x) * 10.0; z = 10000.0;} 944 | y *= y; 945 | y *= y; 946 | return clamp(y, 0.0, z); 947 | } 948 | 949 | float fastdecodePQ(float x) 950 | { 951 | return BUFFER_COLOR_BIT_DEPTH == 10 ? saturate((sqrt(sqrt(clamp(x, __HQAAL_SMALLEST_COLOR_STEP, 500.0))) / 4.7287080450158790665084805994361)) : saturate((sqrt(sqrt(clamp(x, __HQAAL_SMALLEST_COLOR_STEP, 10000.0))) / 10.0)); 952 | } 953 | float2 fastdecodePQ(float2 x) 954 | { 955 | return BUFFER_COLOR_BIT_DEPTH == 10 ? saturate((sqrt(sqrt(clamp(x, __HQAAL_SMALLEST_COLOR_STEP, 500.0))) / 4.7287080450158790665084805994361)) : saturate((sqrt(sqrt(clamp(x, __HQAAL_SMALLEST_COLOR_STEP, 10000.0))) / 10.0)); 956 | } 957 | float3 fastdecodePQ(float3 x) 958 | { 959 | return BUFFER_COLOR_BIT_DEPTH == 10 ? saturate((sqrt(sqrt(clamp(x, __HQAAL_SMALLEST_COLOR_STEP, 500.0))) / 4.7287080450158790665084805994361)) : saturate((sqrt(sqrt(clamp(x, __HQAAL_SMALLEST_COLOR_STEP, 10000.0))) / 10.0)); 960 | } 961 | float4 fastdecodePQ(float4 x) 962 | { 963 | return BUFFER_COLOR_BIT_DEPTH == 10 ? saturate((sqrt(sqrt(clamp(x, __HQAAL_SMALLEST_COLOR_STEP, 500.0))) / 4.7287080450158790665084805994361)) : saturate((sqrt(sqrt(clamp(x, __HQAAL_SMALLEST_COLOR_STEP, 10000.0))) / 10.0)); 964 | } 965 | 966 | float encodeHDR(float x) 967 | { 968 | return saturate(x) * HqaaHdrNits; 969 | } 970 | float2 encodeHDR(float2 x) 971 | { 972 | return saturate(x) * HqaaHdrNits; 973 | } 974 | float3 encodeHDR(float3 x) 975 | { 976 | return saturate(x) * HqaaHdrNits; 977 | } 978 | float4 encodeHDR(float4 x) 979 | { 980 | return saturate(x) * HqaaHdrNits; 981 | } 982 | 983 | float decodeHDR(float x) 984 | { 985 | return saturate(x / HqaaHdrNits); 986 | } 987 | float2 decodeHDR(float2 x) 988 | { 989 | return saturate(x / HqaaHdrNits); 990 | } 991 | float3 decodeHDR(float3 x) 992 | { 993 | return saturate(x / HqaaHdrNits); 994 | } 995 | float4 decodeHDR(float4 x) 996 | { 997 | return saturate(x / HqaaHdrNits); 998 | } 999 | 1000 | float ConditionalEncode(float x) 1001 | { 1002 | if (HqaaOutputMode == 1) return encodeHDR(x); 1003 | if (HqaaOutputMode == 2) return encodePQ(x); 1004 | if (HqaaOutputMode == 3) return fastencodePQ(x); 1005 | return x; 1006 | } 1007 | float2 ConditionalEncode(float2 x) 1008 | { 1009 | if (HqaaOutputMode == 1) return encodeHDR(x); 1010 | if (HqaaOutputMode == 2) return encodePQ(x); 1011 | if (HqaaOutputMode == 3) return fastencodePQ(x); 1012 | return x; 1013 | } 1014 | float3 ConditionalEncode(float3 x) 1015 | { 1016 | if (HqaaOutputMode == 1) return encodeHDR(x); 1017 | if (HqaaOutputMode == 2) return encodePQ(x); 1018 | if (HqaaOutputMode == 3) return fastencodePQ(x); 1019 | return x; 1020 | } 1021 | float4 ConditionalEncode(float4 x) 1022 | { 1023 | if (HqaaOutputMode == 1) return encodeHDR(x); 1024 | if (HqaaOutputMode == 2) return encodePQ(x); 1025 | if (HqaaOutputMode == 3) return fastencodePQ(x); 1026 | return x; 1027 | } 1028 | 1029 | float ConditionalDecode(float x) 1030 | { 1031 | if (HqaaOutputMode == 1) return decodeHDR(x); 1032 | if (HqaaOutputMode == 2) return decodePQ(x); 1033 | if (HqaaOutputMode == 3) return fastdecodePQ(x); 1034 | return x; 1035 | } 1036 | float2 ConditionalDecode(float2 x) 1037 | { 1038 | if (HqaaOutputMode == 1) return decodeHDR(x); 1039 | if (HqaaOutputMode == 2) return decodePQ(x); 1040 | if (HqaaOutputMode == 3) return fastdecodePQ(x); 1041 | return x; 1042 | } 1043 | float3 ConditionalDecode(float3 x) 1044 | { 1045 | if (HqaaOutputMode == 1) return decodeHDR(x); 1046 | if (HqaaOutputMode == 2) return decodePQ(x); 1047 | if (HqaaOutputMode == 3) return fastdecodePQ(x); 1048 | return x; 1049 | } 1050 | float4 ConditionalDecode(float4 x) 1051 | { 1052 | if (HqaaOutputMode == 1) return decodeHDR(x); 1053 | if (HqaaOutputMode == 2) return decodePQ(x); 1054 | if (HqaaOutputMode == 3) return fastdecodePQ(x); 1055 | return x; 1056 | } 1057 | 1058 | ///////////////////////////////////////////////////// SMAA HELPER FUNCTIONS /////////////////////////////////////////////////////////////// 1059 | 1060 | void HQAAMovc(bool2 cond, inout float2 variable, float2 value) 1061 | { 1062 | [flatten] if (cond.x) variable.x = value.x; 1063 | [flatten] if (cond.y) variable.y = value.y; 1064 | } 1065 | void HQAAMovc(bool4 cond, inout float4 variable, float4 value) 1066 | { 1067 | HQAAMovc(cond.xy, variable.xy, value.xy); 1068 | HQAAMovc(cond.zw, variable.zw, value.zw); 1069 | } 1070 | 1071 | float2 HQAADecodeDiagBilinearAccess(float2 e) 1072 | { 1073 | e.r = e.r * abs(5.0 * e.r - 5.0 * 0.75); 1074 | return round(e); 1075 | } 1076 | float4 HQAADecodeDiagBilinearAccess(float4 e) 1077 | { 1078 | e.rb = e.rb * abs(5.0 * e.rb - 5.0 * 0.75); 1079 | return round(e); 1080 | } 1081 | 1082 | float2 HQAASearchDiag(sampler2D HQAALedgesTex, float2 texcoord, float2 dir, out float2 e) 1083 | { 1084 | float4 coord = float4(texcoord, -1.0, 1.0); 1085 | float3 t = float3(__HQAAL_SM_BUFFERINFO.xy, 1.0); 1086 | [loop] while (coord.z < 20.0) 1087 | { 1088 | coord.xyz = mad(t, float3(dir, 1.0), coord.xyz); 1089 | e = tex2Dlod(HQAALedgesTex, coord.xyxy).rg; 1090 | coord.w = dot(e, float(0.5).xx); 1091 | if (coord.w < 0.9) break; 1092 | } 1093 | return coord.zw; 1094 | } 1095 | 1096 | float2 HQAAAreaDiag(sampler2D HQAALareaTex, float2 dist, float2 e) 1097 | { 1098 | float2 texcoord = mad(float(__HQAAL_SM_AREATEX_RANGE_DIAG).xx, e, dist); 1099 | 1100 | texcoord = mad(__HQAAL_SM_AREATEX_TEXEL, texcoord, 0.5 * __HQAAL_SM_AREATEX_TEXEL); 1101 | texcoord.x += 0.5; 1102 | 1103 | return tex2Dlod(HQAALareaTex, texcoord.xyxy).rg; 1104 | } 1105 | 1106 | float2 HQAACalculateDiagWeights(sampler2D HQAALedgesTex, sampler2D HQAALareaTex, float2 texcoord, float2 e) 1107 | { 1108 | float2 weights = float(0.0).xx; 1109 | float2 end; 1110 | float4 d; 1111 | d.ywxz = float4(HQAASearchDiag(HQAALedgesTex, texcoord, float2(1.0, -1.0), end), 0.0, 0.0); 1112 | 1113 | if (e.r > 0.0) 1114 | { 1115 | d.xz = HQAASearchDiag(HQAALedgesTex, texcoord, float2(-1.0, 1.0), end); 1116 | d.x += float(end.y > 0.9); 1117 | } 1118 | 1119 | if (d.x + d.y > 2.0) 1120 | { 1121 | float4 coords = mad(float4(-d.x + 0.25, d.x, d.y, -d.y - 0.25), __HQAAL_SM_BUFFERINFO.xyxy, texcoord.xyxy); 1122 | float4 c; 1123 | c.xy = tex2Dlodoffset(HQAALedgesTex, coords.xyxy, int2(-1, 0)).rg; 1124 | c.zw = tex2Dlodoffset(HQAALedgesTex, coords.zwzw, int2( 1, 0)).rg; 1125 | c.yxwz = HQAADecodeDiagBilinearAccess(c.xyzw); 1126 | 1127 | float2 cc = mad(float(2.0).xx, c.xz, c.yw); 1128 | 1129 | HQAAMovc(bool2(step(0.9, d.zw)), cc, float(0.0).xx); 1130 | 1131 | weights += HQAAAreaDiag(HQAALareaTex, d.xy, cc); 1132 | } 1133 | 1134 | d.xz = HQAASearchDiag(HQAALedgesTex, texcoord, float2(-1.0, -1.0), end); 1135 | d.yw = float(0.0).xx; 1136 | 1137 | if (HQAAL_Tex2D(HQAALedgesTex, texcoord + float2(BUFFER_RCP_WIDTH, 0)).r > 0.0) 1138 | { 1139 | d.yw = HQAASearchDiag(HQAALedgesTex, texcoord, float(1.0).xx, end); 1140 | d.y += float(end.y > 0.9); 1141 | } 1142 | 1143 | if (d.x + d.y > 2.0) 1144 | { 1145 | float4 coords = mad(float4(-d.x, -d.x, d.y, d.y), __HQAAL_SM_BUFFERINFO.xyxy, texcoord.xyxy); 1146 | float4 c; 1147 | c.x = tex2Dlodoffset(HQAALedgesTex, coords.xyxy, int2(-1, 0)).g; 1148 | c.y = tex2Dlodoffset(HQAALedgesTex, coords.xyxy, int2( 0, -1)).r; 1149 | c.zw = tex2Dlodoffset(HQAALedgesTex, coords.zwzw, int2( 1, 0)).gr; 1150 | float2 cc = mad(float(2.0).xx, c.xz, c.yw); 1151 | 1152 | HQAAMovc(bool2(step(0.9, d.zw)), cc, float(0.0).xx); 1153 | 1154 | weights += HQAAAreaDiag(HQAALareaTex, d.xy, cc).gr; 1155 | } 1156 | 1157 | return weights; 1158 | } 1159 | 1160 | float HQAASearchLength(sampler2D HQAALsearchTex, float2 e, float offset) 1161 | { 1162 | float2 scale = __HQAAL_SM_SEARCHTEX_SIZE * float2(0.5, -1.0); 1163 | float2 bias = __HQAAL_SM_SEARCHTEX_SIZE * float2(offset, 1.0); 1164 | 1165 | scale += float2(-1.0, 1.0); 1166 | bias += float2( 0.5, -0.5); 1167 | 1168 | scale *= 1.0 / __HQAAL_SM_SEARCHTEX_SIZE_PACKED; 1169 | bias *= 1.0 / __HQAAL_SM_SEARCHTEX_SIZE_PACKED; 1170 | 1171 | return tex2Dlod(HQAALsearchTex, mad(scale, e, bias).xyxy).r; 1172 | } 1173 | 1174 | float HQAASearchXLeft(sampler2D HQAALedgesTex, sampler2D HQAALsearchTex, float2 texcoord, float end) 1175 | { 1176 | float2 e = float2(0.0, 1.0); 1177 | [loop] while (texcoord.x > end) 1178 | { 1179 | e = tex2Dlod(HQAALedgesTex, texcoord.xyxy).rg; 1180 | texcoord = mad(-float2(2.0, 0.0), __HQAAL_SM_BUFFERINFO.xy, texcoord); 1181 | if (e.r > 0.0) break; 1182 | } 1183 | float offset = mad(-(255./127.), HQAASearchLength(HQAALsearchTex, e, 0.0), 3.25); 1184 | return mad(__HQAAL_SM_BUFFERINFO.x, offset, texcoord.x); 1185 | } 1186 | float HQAASearchXRight(sampler2D HQAALedgesTex, sampler2D HQAALsearchTex, float2 texcoord, float end) 1187 | { 1188 | float2 e = float2(0.0, 1.0); 1189 | [loop] while (texcoord.x < end) 1190 | { 1191 | e = tex2Dlod(HQAALedgesTex, texcoord.xyxy).rg; 1192 | texcoord = mad(float2(2.0, 0.0), __HQAAL_SM_BUFFERINFO.xy, texcoord); 1193 | if (e.r > 0.0) break; 1194 | } 1195 | float offset = mad(-(255./127.), HQAASearchLength(HQAALsearchTex, e, 0.5), 3.25); 1196 | return mad(-__HQAAL_SM_BUFFERINFO.x, offset, texcoord.x); 1197 | } 1198 | float HQAASearchYUp(sampler2D HQAALedgesTex, sampler2D HQAALsearchTex, float2 texcoord, float end) 1199 | { 1200 | float2 e = float2(1.0, 0.0); 1201 | [loop] while (texcoord.y > end) 1202 | { 1203 | e = tex2Dlod(HQAALedgesTex, texcoord.xyxy).rg; 1204 | texcoord = mad(-float2(0.0, 2.0), __HQAAL_SM_BUFFERINFO.xy, texcoord); 1205 | if (e.g > 0.0) break; 1206 | } 1207 | float offset = mad(-(255./127.), HQAASearchLength(HQAALsearchTex, e.gr, 0.0), 3.25); 1208 | return mad(__HQAAL_SM_BUFFERINFO.y, offset, texcoord.y); 1209 | } 1210 | float HQAASearchYDown(sampler2D HQAALedgesTex, sampler2D HQAALsearchTex, float2 texcoord, float end) 1211 | { 1212 | float2 e = float2(1.0, 0.0); 1213 | [loop] while (texcoord.y < end) 1214 | { 1215 | e = tex2Dlod(HQAALedgesTex, texcoord.xyxy).rg; 1216 | texcoord = mad(float2(0.0, 2.0), __HQAAL_SM_BUFFERINFO.xy, texcoord); 1217 | if (e.g > 0.0) break; 1218 | } 1219 | float offset = mad(-(255./127.), HQAASearchLength(HQAALsearchTex, e.gr, 0.5), 3.25); 1220 | return mad(-__HQAAL_SM_BUFFERINFO.y, offset, texcoord.y); 1221 | } 1222 | 1223 | float2 HQAAArea(sampler2D HQAALareaTex, float2 dist, float e1, float e2) 1224 | { 1225 | float2 texcoord = mad(float(__HQAAL_SM_AREATEX_RANGE).xx, 4.0 * float2(e1, e2), dist); 1226 | 1227 | texcoord = mad(__HQAAL_SM_AREATEX_TEXEL, texcoord, 0.5 * __HQAAL_SM_AREATEX_TEXEL); 1228 | 1229 | return tex2Dlod(HQAALareaTex, texcoord.xyxy).rg; 1230 | } 1231 | 1232 | void HQAADetectHorizontalCornerPattern(sampler2D HQAALedgesTex, inout float2 weights, float4 texcoord, float2 d) 1233 | { 1234 | float2 leftRight = step(d.xy, d.yx); 1235 | float2 rounding = (1.0 - __HQAAL_SM_CORNERS) * leftRight; 1236 | 1237 | float2 factor = float(1.0).xx; 1238 | factor.x -= rounding.x * tex2Dlodoffset(HQAALedgesTex, texcoord.xyxy, int2(0, 1)).r; 1239 | factor.x -= rounding.y * tex2Dlodoffset(HQAALedgesTex, texcoord.zwzw, int2(1, 1)).r; 1240 | factor.y -= rounding.x * tex2Dlodoffset(HQAALedgesTex, texcoord.xyxy, int2(0, -2)).r; 1241 | factor.y -= rounding.y * tex2Dlodoffset(HQAALedgesTex, texcoord.zwzw, int2(1, -2)).r; 1242 | 1243 | weights *= saturate(factor); 1244 | } 1245 | void HQAADetectVerticalCornerPattern(sampler2D HQAALedgesTex, inout float2 weights, float4 texcoord, float2 d) 1246 | { 1247 | float2 leftRight = step(d.xy, d.yx); 1248 | float2 rounding = (1.0 - __HQAAL_SM_CORNERS) * leftRight; 1249 | 1250 | float2 factor = float(1.0).xx; 1251 | factor.x -= rounding.x * tex2Dlodoffset(HQAALedgesTex, texcoord.xyxy, int2( 1, 0)).g; 1252 | factor.x -= rounding.y * tex2Dlodoffset(HQAALedgesTex, texcoord.zwzw, int2( 1, 1)).g; 1253 | factor.y -= rounding.x * tex2Dlodoffset(HQAALedgesTex, texcoord.xyxy, int2(-2, 0)).g; 1254 | factor.y -= rounding.y * tex2Dlodoffset(HQAALedgesTex, texcoord.zwzw, int2(-2, 1)).g; 1255 | 1256 | weights *= saturate(factor); 1257 | } 1258 | 1259 | /***************************************************************************************************************************************/ 1260 | /******************************************************** SUPPORT CODE END *************************************************************/ 1261 | /***************************************************************************************************************************************/ 1262 | 1263 | /***************************************************************************************************************************************/ 1264 | /*********************************************************** SHADER SETUP START ********************************************************/ 1265 | /***************************************************************************************************************************************/ 1266 | 1267 | #include "ReShade.fxh" 1268 | 1269 | 1270 | //////////////////////////////////////////////////////////// TEXTURES /////////////////////////////////////////////////////////////////// 1271 | 1272 | texture HQAALedgesTex 1273 | #if __RESHADE__ >= 50000 1274 | < pooled = true; > 1275 | #endif 1276 | { 1277 | Width = BUFFER_WIDTH; 1278 | Height = BUFFER_HEIGHT; 1279 | Format = RGBA16F; 1280 | }; 1281 | 1282 | texture HQAALblendTex 1283 | #if __RESHADE__ >= 50000 1284 | < pooled = true; > 1285 | #endif 1286 | { 1287 | Width = BUFFER_WIDTH; 1288 | Height = BUFFER_HEIGHT; 1289 | Format = RGBA16F; 1290 | }; 1291 | 1292 | texture HQAALareaTex < source = "AreaTex.png"; > 1293 | { 1294 | Width = 160; 1295 | Height = 560; 1296 | Format = RG8; 1297 | }; 1298 | 1299 | texture HQAALsearchTex < source = "SearchTex.png"; > 1300 | { 1301 | Width = 64; 1302 | Height = 16; 1303 | Format = R8; 1304 | }; 1305 | 1306 | //////////////////////////////////////////////////////////// SAMPLERS /////////////////////////////////////////////////////////////////// 1307 | 1308 | sampler HQAALsamplerAlphaEdges 1309 | { 1310 | Texture = HQAALedgesTex; 1311 | }; 1312 | 1313 | sampler HQAALsamplerSMweights 1314 | { 1315 | Texture = HQAALblendTex; 1316 | }; 1317 | 1318 | sampler HQAALsamplerSMarea 1319 | { 1320 | Texture = HQAALareaTex; 1321 | }; 1322 | 1323 | sampler HQAALsamplerSMsearch 1324 | { 1325 | Texture = HQAALsearchTex; 1326 | }; 1327 | 1328 | //////////////////////////////////////////////////////////// VERTEX SHADERS ///////////////////////////////////////////////////////////// 1329 | void HQAALBlendingWeightCalculationVS(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD0, out float2 pixcoord : TEXCOORD1, out float4 offset[3] : TEXCOORD2) 1330 | { 1331 | texcoord.x = (id == 2) ? 2.0 : 0.0; 1332 | texcoord.y = (id == 1) ? 2.0 : 0.0; 1333 | position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 1334 | pixcoord = texcoord * __HQAAL_SM_BUFFERINFO.zw; 1335 | 1336 | offset[0] = mad(__HQAAL_SM_BUFFERINFO.xyxy, float4(-0.25, -0.125, 1.25, -0.125), texcoord.xyxy); 1337 | offset[1] = mad(__HQAAL_SM_BUFFERINFO.xyxy, float4(-0.125, -0.25, -0.125, 1.25), texcoord.xyxy); 1338 | 1339 | float searchrange = __HQAAL_SM_RADIUS; 1340 | 1341 | offset[2] = mad(__HQAAL_SM_BUFFERINFO.xxyy, 1342 | float2(-2.0, 2.0).xyxy * searchrange, 1343 | float4(offset[0].xz, offset[1].yw)); 1344 | } 1345 | 1346 | void HQAALNeighborhoodBlendingVS(in uint id : SV_VertexID, out float4 position : SV_Position, out float2 texcoord : TEXCOORD0, out float4 offset : TEXCOORD1) 1347 | { 1348 | texcoord.x = (id == 2) ? 2.0 : 0.0; 1349 | texcoord.y = (id == 1) ? 2.0 : 0.0; 1350 | position = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0); 1351 | offset = mad(__HQAAL_SM_BUFFERINFO.xyxy, float4( 1.0, 0.0, 0.0, 1.0), texcoord.xyxy); 1352 | } 1353 | 1354 | /*****************************************************************************************************************************************/ 1355 | /*********************************************************** SHADER SETUP END ************************************************************/ 1356 | /*****************************************************************************************************************************************/ 1357 | 1358 | /*****************************************************************************************************************************************/ 1359 | /********************************************************** SMAA SHADER CODE START *******************************************************/ 1360 | /*****************************************************************************************************************************************/ 1361 | 1362 | //////////////////////////////////////////////////////// EDGE DETECTION /////////////////////////////////////////////////////////////////// 1363 | float4 HQAALHybridEdgeDetectionPS(float4 position : SV_Position, float2 texcoord : TEXCOORD) : SV_Target 1364 | { 1365 | if ((HqaaSourceInterpolation == 1) && __HQAAL_ALT_FRAME) discard; 1366 | if ((HqaaSourceInterpolation == 2) && !__HQAAL_QUAD_FRAME) discard; 1367 | 1368 | float3 middle = HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord).rgb; 1369 | float3 ref = __HQAAL_LUMA_REF; 1370 | float2 hvstep = __HQAAL_SM_BUFFERINFO.xy; 1371 | float2 diagstep = hvstep * __HQAAL_CONST_HALFROOT2; 1372 | 1373 | float L = dot(middle, ref); 1374 | float3 scan = HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord - float2(0, hvstep.y)).rgb; 1375 | float Dtop = chromadelta(middle, scan); 1376 | float Ltop = dot(scan, ref); 1377 | scan = HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord - float2(hvstep.x, 0)).rgb; 1378 | float Dleft = chromadelta(middle, scan); 1379 | float Lleft = dot(scan, ref); 1380 | scan = HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord + float2(hvstep.x, 0)).rgb; 1381 | float Dright = chromadelta(middle, scan); 1382 | float Lright = dot(scan, ref); 1383 | scan = HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord + float2(0, hvstep.y)).rgb; 1384 | float Dbottom = chromadelta(middle, scan); 1385 | float Lbottom = dot(scan, ref); 1386 | scan = HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord - diagstep).rgb; 1387 | float Dtopleft = chromadelta(middle, scan); 1388 | float Ltopleft = dot(scan, ref); 1389 | scan = HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord + diagstep).rgb; 1390 | float Dbottomright = chromadelta(middle, scan); 1391 | float Lbottomright = dot(scan, ref); 1392 | scan = HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord + float2(diagstep.x, -diagstep.y)).rgb; 1393 | float Dtopright = chromadelta(middle, scan); 1394 | float Ltopright = dot(scan, ref); 1395 | scan = HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord + float2(-diagstep.x, diagstep.y)).rgb; 1396 | float Dbottomleft = chromadelta(middle, scan); 1397 | float Lbottomleft = dot(scan, ref); 1398 | 1399 | float Lavg = sqrt(L * clamp(((Lleft + Ltop + Lright + Lbottom + Ltopleft + Ltopright + Lbottomleft + Lbottomright) / 8.0), __HQAAL_SMALLEST_COLOR_STEP, 1.0)); 1400 | float rangemult = 1.0 - log2(1.0 + clamp(log2(1.0 + Lavg), 0.0, HqaaLowLumaThreshold) * rcp(HqaaLowLumaThreshold)); 1401 | float edgethreshold = __HQAAL_EDGE_THRESHOLD; 1402 | edgethreshold = mad(rangemult, -(__HQAAL_DYNAMIC_RANGE * edgethreshold), edgethreshold); 1403 | float2 bufferdata = float2(L, edgethreshold); 1404 | 1405 | // delta 1406 | // * y * 1407 | // x * z 1408 | // * w * 1409 | 1410 | // diagdelta 1411 | // r * b 1412 | // * * * 1413 | // g * a 1414 | 1415 | float4 delta = step(edgethreshold, float4(Dleft, Dtop, Dright, Dbottom)); 1416 | float4 diagdelta = step(edgethreshold, float4(Dtopleft, Dbottomleft, Dtopright, Dbottomright)); 1417 | 1418 | float2 fulldiag = lxor(diagdelta.r * diagdelta.a, diagdelta.g * diagdelta.b).xx; 1419 | 1420 | float neardiag1 = saturate(lnand(diagdelta.b * delta.z * delta.w, diagdelta.a) + lnand(diagdelta.g * delta.x * delta.y, diagdelta.r)); 1421 | float neardiag2 = saturate(lnand(diagdelta.a * delta.z * delta.y, diagdelta.b) + lnand(diagdelta.r * delta.x * delta.w, diagdelta.g)); 1422 | float neardiag3 = saturate(lnand(diagdelta.b * delta.y * delta.x, diagdelta.r) + lnand(diagdelta.g * delta.w * delta.z, diagdelta.a)); 1423 | float neardiag4 = saturate(lnand(diagdelta.r * delta.y * delta.z, diagdelta.b) + lnand(diagdelta.a * delta.w * delta.x, diagdelta.g)); 1424 | float2 neardiag = lxor(lxor(neardiag1, neardiag2), lxor(neardiag3, neardiag4)).xx; 1425 | 1426 | /* 1427 | float2 hvedges = float2(delta.x * delta.z, delta.y * delta.w); 1428 | if (lxor(hvedges.x, hvedges.y) == 0.0) hvedges = 0.0.xx; 1429 | */ 1430 | float2 hvedges = saturate(float2(delta.x + delta.z, delta.y + delta.w)); 1431 | 1432 | float2 edges = 0.0.xx; 1433 | edges = neardiag; 1434 | if (!any(edges)) edges = hvedges; 1435 | if (!any(edges)) edges = fulldiag; 1436 | 1437 | return float4(edges, bufferdata); 1438 | } 1439 | 1440 | /////////////////////////////////////////////////// BLEND WEIGHT CALCULATION ////////////////////////////////////////////////////////////// 1441 | float4 HQAALBlendingWeightCalculationPS(float4 position : SV_Position, float2 texcoord : TEXCOORD0, float2 pixcoord : TEXCOORD1, float4 offset[3] : TEXCOORD2) : SV_Target 1442 | { 1443 | float4 weights = float(0.0).xxxx; 1444 | float2 e = HQAAL_Tex2D(HQAALsamplerAlphaEdges, texcoord).rg; 1445 | float2 diagweights; 1446 | if (all(e)) { diagweights = HQAACalculateDiagWeights(HQAALsamplerAlphaEdges, HQAALsamplerSMarea, texcoord, e); weights.rg = diagweights; } 1447 | [branch] if (e.g > 0.0) 1448 | { 1449 | float3 coords = float3(HQAASearchXLeft(HQAALsamplerAlphaEdges, HQAALsamplerSMsearch, offset[0].xy, offset[2].x), offset[1].y, HQAASearchXRight(HQAALsamplerAlphaEdges, HQAALsamplerSMsearch, offset[0].zw, offset[2].y)); 1450 | float e1 = HQAAL_Tex2D(HQAALsamplerAlphaEdges, coords.xy).r; 1451 | float2 d = coords.xz; 1452 | d = abs((mad(__HQAAL_SM_BUFFERINFO.zz, d, -pixcoord.xx))); 1453 | float e2 = HQAAL_Tex2D(HQAALsamplerAlphaEdges, coords.zy + float2(BUFFER_RCP_WIDTH, 0)).r; 1454 | weights.rg = max(HQAAArea(HQAALsamplerSMarea, sqrt(d), e1, e2), diagweights); 1455 | coords.y = texcoord.y; 1456 | HQAADetectHorizontalCornerPattern(HQAALsamplerAlphaEdges, weights.rg, coords.xyzy, d); 1457 | } 1458 | [branch] if (e.r > 0.0) 1459 | { 1460 | float3 coords = float3(offset[0].x, HQAASearchYUp(HQAALsamplerAlphaEdges, HQAALsamplerSMsearch, offset[1].xy, offset[2].z), HQAASearchYDown(HQAALsamplerAlphaEdges, HQAALsamplerSMsearch, offset[1].zw, offset[2].w)); 1461 | float e1 = HQAAL_Tex2D(HQAALsamplerAlphaEdges, coords.xy).g; 1462 | float2 d = coords.yz; 1463 | d = abs((mad(__HQAAL_SM_BUFFERINFO.ww, d, -pixcoord.yy))); 1464 | float e2 = HQAAL_Tex2D(HQAALsamplerAlphaEdges, coords.xz + float2(0, BUFFER_RCP_HEIGHT)).g; 1465 | weights.ba = HQAAArea(HQAALsamplerSMarea, sqrt(d), e1, e2); 1466 | coords.x = texcoord.x; 1467 | HQAADetectVerticalCornerPattern(HQAALsamplerAlphaEdges, weights.ba, coords.xyxz, d); 1468 | } 1469 | return weights; 1470 | } 1471 | 1472 | //////////////////////////////////////////////////// NEIGHBORHOOD BLENDING //////////////////////////////////////////////////////////////// 1473 | 1474 | float3 HQAALNeighborhoodBlendingPS(float4 position : SV_Position, float2 texcoord : TEXCOORD0, float4 offset : TEXCOORD1) : SV_Target 1475 | { 1476 | float3 resultAA = HQAAL_Tex2D(ReShade::BackBuffer, texcoord).rgb; 1477 | if (HqaaDebugMode == 8) return resultAA; 1478 | float4 m = float4(HQAAL_Tex2D(HQAALsamplerSMweights, offset.xy).a, HQAAL_Tex2D(HQAALsamplerSMweights, offset.zw).g, HQAAL_Tex2D(HQAALsamplerSMweights, texcoord).zx); 1479 | 1480 | [branch] if (any(m)) 1481 | { 1482 | resultAA = ConditionalDecode(resultAA); 1483 | float3 original = resultAA; 1484 | float Lpre = dot(resultAA, __HQAAL_LUMA_REF); 1485 | float maxweight = max(m.x + m.z, m.y + m.w); 1486 | float minweight = min(m.x + m.z, m.y + m.w); 1487 | float maxratio = maxweight / (minweight + maxweight); 1488 | float minratio = minweight / (minweight + maxweight); 1489 | bool horiz = (m.x + m.z) > (m.y + m.w); 1490 | 1491 | float4 blendingOffset = 0.0.xxxx; 1492 | float2 blendingWeight; 1493 | 1494 | HQAAMovc(bool4(horiz, !horiz, horiz, !horiz), blendingOffset, float4(m.x, m.y, m.z, m.w)); 1495 | HQAAMovc(bool(horiz).xx, blendingWeight, m.xz); 1496 | HQAAMovc(bool(!horiz).xx, blendingWeight, m.yw); 1497 | blendingWeight /= dot(blendingWeight, float(1.0).xx); 1498 | float4 blendingCoord = mad(blendingOffset, float4(__HQAAL_SM_BUFFERINFO.xy, -__HQAAL_SM_BUFFERINFO.xy), texcoord.xyxy); 1499 | resultAA = maxratio * blendingWeight.x * HQAAL_DecodeTex2D(ReShade::BackBuffer, blendingCoord.xy).rgb; 1500 | resultAA += maxratio * blendingWeight.y * HQAAL_DecodeTex2D(ReShade::BackBuffer, blendingCoord.zw).rgb; 1501 | 1502 | [branch] if (minratio != 0.0) 1503 | { 1504 | blendingOffset = 0.0.xxxx; 1505 | HQAAMovc(bool4(!horiz, horiz, !horiz, horiz), blendingOffset, float4(m.x, m.y, m.z, m.w)); 1506 | HQAAMovc(bool(!horiz).xx, blendingWeight, m.xz); 1507 | HQAAMovc(bool(horiz).xx, blendingWeight, m.yw); 1508 | blendingWeight /= dot(blendingWeight, float(1.0).xx); 1509 | blendingCoord = mad(blendingOffset, float4(__HQAAL_SM_BUFFERINFO.xy, -__HQAAL_SM_BUFFERINFO.xy), texcoord.xyxy); 1510 | resultAA += minratio * blendingWeight.x * HQAAL_DecodeTex2D(ReShade::BackBuffer, blendingCoord.xy).rgb; 1511 | resultAA += minratio * blendingWeight.y * HQAAL_DecodeTex2D(ReShade::BackBuffer, blendingCoord.zw).rgb; 1512 | } 1513 | 1514 | float Lpost = dot(resultAA, __HQAAL_LUMA_REF); 1515 | float resultingdelta = saturate(1.0 - abs(Lpost - Lpre) * (HqaaNoiseControlStrength / 100.)); 1516 | resultAA = lerp(original, resultAA, resultingdelta); 1517 | resultAA = ConditionalEncode(resultAA); 1518 | } 1519 | return resultAA; 1520 | } 1521 | 1522 | /***************************************************************************************************************************************/ 1523 | /********************************************************** SMAA SHADER CODE END *******************************************************/ 1524 | /***************************************************************************************************************************************/ 1525 | 1526 | /***************************************************************************************************************************************/ 1527 | /********************************************************** FXAA SHADER CODE START *****************************************************/ 1528 | /***************************************************************************************************************************************/ 1529 | 1530 | float3 HQAALFXPS(float4 position : SV_Position, float2 texcoord : TEXCOORD0, float4 offset : TEXCOORD1) : SV_Target 1531 | { 1532 | float3 original = HQAAL_Tex2D(ReShade::BackBuffer, texcoord).rgb; 1533 | if (HqaaDebugMode == 9) return original; 1534 | 1535 | float4 smaadata = HQAAL_Tex2D(HQAALsamplerAlphaEdges, texcoord); 1536 | float edgethreshold = smaadata.a; 1537 | float3 middle = ConditionalDecode(original); 1538 | float maxchannel = max3(middle.r, middle.g, middle.b); 1539 | float3 ref; 1540 | if (middle.g == maxchannel) ref = __HQAAL_GREEN_LUMA; 1541 | else if (middle.r == maxchannel) ref = __HQAAL_RED_LUMA; 1542 | else ref = __HQAAL_BLUE_LUMA; 1543 | float lumaM = dot(middle, ref); 1544 | float2 lengthSign = float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT); 1545 | 1546 | float lumaS = dot(HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord + float2(0, lengthSign.y)).rgb, ref); 1547 | float lumaE = dot(HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord + float2(lengthSign.x, 0)).rgb, ref); 1548 | float lumaN = dot(HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord - float2(0, lengthSign.y)).rgb, ref); 1549 | float lumaW = dot(HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord - float2(lengthSign.x, 0)).rgb, ref); 1550 | float4 crossdelta = abs(lumaM - float4(lumaS, lumaE, lumaN, lumaW)); 1551 | float2 weightsHV = float2(crossdelta.x + crossdelta.z, crossdelta.y + crossdelta.w); 1552 | 1553 | // pattern 1554 | // * z * 1555 | // w * y 1556 | // * x * 1557 | 1558 | float2 diagstep = lengthSign * __HQAAL_CONST_HALFROOT2; 1559 | float lumaNW = dot(HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord - diagstep).rgb, ref); 1560 | float lumaSE = dot(HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord + diagstep).rgb, ref); 1561 | float lumaNE = dot(HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord + float2(diagstep.x, -diagstep.y)).rgb, ref); 1562 | float lumaSW = dot(HQAAL_DecodeTex2D(ReShade::BackBuffer, texcoord + float2(-diagstep.x, diagstep.y)).rgb, ref); 1563 | float4 diagdelta = abs(lumaM - float4(lumaNW, lumaSE, lumaNE, lumaSW)); 1564 | float2 weightsDI = float2(diagdelta.w + diagdelta.z, diagdelta.x + diagdelta.y); 1565 | 1566 | // pattern 1567 | // x * z 1568 | // * * * 1569 | // w * y 1570 | 1571 | //detect edge pattern 1572 | bool diagSpan = max(weightsDI.x, weightsDI.y) * float(bool(lxor(weightsDI.x, weightsDI.y))) > max(weightsHV.x, weightsHV.y); 1573 | bool inverseDiag = diagSpan && (weightsDI.y > weightsDI.x); 1574 | bool horzSpan = weightsHV.x > weightsHV.y; 1575 | 1576 | // early exit check 1577 | float range = max8(crossdelta.x, crossdelta.y, crossdelta.z, crossdelta.w, diagdelta.x, diagdelta.y, diagdelta.z, diagdelta.w); 1578 | if (HqaaFxEarlyExit && (range < edgethreshold)) 1579 | if (clamp(HqaaDebugMode, 3, 5) == HqaaDebugMode) return float(0.0).xxx; 1580 | else return original; 1581 | 1582 | float2 lumaNP = float2(lumaN, lumaS); 1583 | HQAAMovc(!horzSpan.xx, lumaNP, float2(lumaW, lumaE)); 1584 | HQAAMovc(diagSpan.xx, lumaNP, float2(lumaNW, lumaSE)); 1585 | HQAAMovc((diagSpan && inverseDiag).xx, lumaNP, float2(lumaSW, lumaNE)); 1586 | float gradientN = abs(lumaNP.x - lumaM); 1587 | float gradientP = abs(lumaNP.y - lumaM); 1588 | float lumaNN = lumaNP.x + lumaM; 1589 | if (gradientN >= gradientP && !diagSpan) lengthSign = -lengthSign; 1590 | if (diagSpan && inverseDiag) lengthSign.y = -lengthSign.y; 1591 | if (gradientP > gradientN) lumaNN = lumaNP.y + lumaM; 1592 | float gradientScaled = max(gradientN, gradientP) * 0.25; 1593 | bool lumaMLTZero = mad(0.5, -lumaNN, lumaM) < 0.0; 1594 | 1595 | float2 posB = texcoord; 1596 | float texelsize = __HQAAL_FX_TEXEL; 1597 | float2 offNP = float2(0.0, BUFFER_RCP_HEIGHT * texelsize); 1598 | HQAAMovc(bool(horzSpan).xx, offNP, float2(BUFFER_RCP_WIDTH * texelsize, 0.0)); 1599 | HQAAMovc(bool(diagSpan).xx, offNP, float2(BUFFER_RCP_WIDTH * texelsize, BUFFER_RCP_HEIGHT * texelsize)); 1600 | if (diagSpan && inverseDiag) offNP.y = -offNP.y; 1601 | HQAAMovc(bool2(!horzSpan || diagSpan, horzSpan || diagSpan), posB, float2(posB.x + lengthSign.x * 0.333333, posB.y + lengthSign.y * 0.333333)); 1602 | float2 posN = posB - offNP; 1603 | float2 posP = posB + offNP; 1604 | float lumaEndN = dot(HQAAL_DecodeTex2D(ReShade::BackBuffer, posN).rgb, ref); 1605 | float lumaEndP = dot(HQAAL_DecodeTex2D(ReShade::BackBuffer, posP).rgb, ref); 1606 | 1607 | lumaNN *= 0.5; 1608 | lumaEndN -= lumaNN; 1609 | lumaEndP -= lumaNN; 1610 | 1611 | bool doneN = abs(lumaEndN) >= gradientScaled; 1612 | bool doneP = abs(lumaEndP) >= gradientScaled; 1613 | uint iterations = 0; 1614 | uint maxiterations = __HQAAL_FX_QUALITY; 1615 | 1616 | [loop] while (iterations < maxiterations) 1617 | { 1618 | if (doneN && doneP) break; 1619 | if (!doneN) 1620 | { 1621 | posN -= offNP; 1622 | lumaEndN = dot(HQAAL_DecodeTex2D(ReShade::BackBuffer, posN).rgb, ref); 1623 | lumaEndN -= lumaNN; 1624 | doneN = abs(lumaEndN) >= gradientScaled; 1625 | } 1626 | if (!doneP) 1627 | { 1628 | posP += offNP; 1629 | lumaEndP = dot(HQAAL_DecodeTex2D(ReShade::BackBuffer, posP).rgb, ref); 1630 | lumaEndP -= lumaNN; 1631 | doneP = abs(lumaEndP) >= gradientScaled; 1632 | } 1633 | iterations++; 1634 | } 1635 | 1636 | float2 dstNP = float2(texcoord.y - posN.y, posP.y - texcoord.y); 1637 | HQAAMovc(bool(horzSpan).xx, dstNP, float2(texcoord.x - posN.x, posP.x - texcoord.x)); 1638 | HQAAMovc(bool(diagSpan).xx, dstNP, float2(sqrt(pow(abs(texcoord.y - posN.y), 2.0) + pow(abs(texcoord.x - posN.x), 2.0)), sqrt(pow(abs(posP.y - texcoord.y), 2.0) + pow(abs(posP.x - texcoord.x), 2.0)))); 1639 | float endluma = (dstNP.x < dstNP.y) ? lumaEndN : lumaEndP; 1640 | bool goodSpan = endluma < 0.0 != lumaMLTZero; 1641 | float blendclamp = goodSpan ? 1.0 : (1.0 - abs(endluma - lumaM) * (HqaaNoiseControlStrength / 100.)); 1642 | float pixelOffset = abs(mad(-rcp(dstNP.y + dstNP.x), min(dstNP.x, dstNP.y), 0.5)) * clamp(__HQAAL_FX_BLEND, 0.0, blendclamp); 1643 | float subpixOut = 1.0; 1644 | 1645 | if (!goodSpan) // bad span 1646 | { 1647 | subpixOut = mad(mad(2.0, lumaS + lumaE + lumaN + lumaW, lumaNW + lumaSE + lumaNE + lumaSW), 0.083333, -lumaM) * rcp(range); //ABC 1648 | subpixOut = pow(saturate(mad(-2.0, subpixOut, 3.0) * (subpixOut * subpixOut)), 2.0); // DEFGH 1649 | } 1650 | subpixOut *= pixelOffset; 1651 | 1652 | float2 posM = texcoord; 1653 | HQAAMovc(bool2(!horzSpan || diagSpan, horzSpan || diagSpan), posM, float2(posM.x + lengthSign.x * subpixOut, posM.y + lengthSign.y * subpixOut)); 1654 | 1655 | // output selection 1656 | if (HqaaDebugMode == 4) 1657 | { 1658 | float3 debugout = ref * lumaM * 0.75 + 0.25; 1659 | return debugout; 1660 | } 1661 | if (HqaaDebugMode == 5) 1662 | { 1663 | // metrics output 1664 | float runtime = float(iterations / maxiterations) * 0.5; 1665 | float3 FxaaMetrics = float3(runtime, 0.5 - runtime, 0.0); 1666 | return FxaaMetrics; 1667 | } 1668 | 1669 | // normal output 1670 | return HQAAL_Tex2D(ReShade::BackBuffer, posM).rgb; 1671 | } 1672 | 1673 | /***************************************************************************************************************************************/ 1674 | /********************************************************** FXAA SHADER CODE END *******************************************************/ 1675 | /***************************************************************************************************************************************/ 1676 | 1677 | /***************************************************************************************************************************************/ 1678 | /****************************************************** HYSTERESIS SHADER CODE START ***************************************************/ 1679 | /***************************************************************************************************************************************/ 1680 | 1681 | float3 HQAALHysteresisPS(float4 position : SV_Position, float2 texcoord : TEXCOORD0, float4 offset : TEXCOORD1) : SV_Target 1682 | { 1683 | float3 pixel = HQAAL_Tex2D(ReShade::BackBuffer, texcoord).rgb; 1684 | float4 edgedata = HQAAL_Tex2D(HQAALsamplerAlphaEdges, texcoord); 1685 | float4 blendingdata = float4(HQAAL_Tex2D(HQAALsamplerSMweights, offset.xy).a, HQAAL_Tex2D(HQAALsamplerSMweights, offset.zw).g, HQAAL_Tex2D(HQAALsamplerSMweights, texcoord).zx); 1686 | 1687 | if (HqaaEnableSharpening && (HqaaDebugMode == 0)) 1688 | { 1689 | float3 casdot = pixel; 1690 | 1691 | float sharpening = HqaaSharpenerStrength; 1692 | 1693 | if (any(blendingdata)) sharpening *= (1.0 - HqaaSharpenerClamping); 1694 | 1695 | float2 hvstep = __HQAAL_SM_BUFFERINFO.xy * HqaaSharpenOffset; 1696 | float2 diagstep = hvstep * __HQAAL_CONST_HALFROOT2; 1697 | 1698 | float3 a = HQAAL_Tex2D(ReShade::BackBuffer, texcoord - diagstep).rgb; 1699 | float3 c = HQAAL_Tex2D(ReShade::BackBuffer, texcoord + float2(diagstep.x, -diagstep.y)).rgb; 1700 | float3 g = HQAAL_Tex2D(ReShade::BackBuffer, texcoord + float2(-diagstep.x, diagstep.y)).rgb; 1701 | float3 i = HQAAL_Tex2D(ReShade::BackBuffer, texcoord + diagstep).rgb; 1702 | float3 b = HQAAL_Tex2D(ReShade::BackBuffer, texcoord - float2(0.0, hvstep.y)).rgb; 1703 | float3 d = HQAAL_Tex2D(ReShade::BackBuffer, texcoord - float2(hvstep.x, 0.0)).rgb; 1704 | float3 f = HQAAL_Tex2D(ReShade::BackBuffer, texcoord + float2(hvstep.x, 0.0)).rgb; 1705 | float3 h = HQAAL_Tex2D(ReShade::BackBuffer, texcoord + float2(0.0, hvstep.y)).rgb; 1706 | 1707 | float3 mnRGB = HQAALmin5(d, casdot, f, b, h); 1708 | float3 mnRGB2 = HQAALmin5(mnRGB, a, c, g, i); 1709 | 1710 | float3 mxRGB = HQAALmax5(d, casdot, f, b, h); 1711 | float3 mxRGB2 = HQAALmax5(mxRGB, a, c, g, i); 1712 | 1713 | casdot = ConditionalDecode(casdot); 1714 | mnRGB = ConditionalDecode(mnRGB); 1715 | mnRGB2 = ConditionalDecode(mnRGB2); 1716 | mxRGB = ConditionalDecode(mxRGB); 1717 | mxRGB2 = ConditionalDecode(mxRGB2); 1718 | 1719 | mnRGB += mnRGB2; 1720 | mxRGB += mxRGB2; 1721 | 1722 | float3 ampRGB = 1.0 / sqrt(saturate(min(mnRGB, 2.0 - mxRGB) * (1.0 / mxRGB))); 1723 | float3 wRGB = -(1.0 / (ampRGB * mad(-3.0, HqaaSharpenerAdaptation, 8.0))); 1724 | float3 window = (b + d) + (f + h); 1725 | 1726 | float3 outColor = saturate(mad(window, wRGB, casdot) * (1.0 / mad(4.0, wRGB, 1.0))); 1727 | casdot = lerp(casdot, outColor, sharpening); 1728 | 1729 | pixel = ConditionalEncode(casdot); 1730 | } 1731 | 1732 | bool skiphysteresis = ((HqaaDebugMode == 0) && (!HqaaDoLumaHysteresis)); 1733 | if (skiphysteresis) return pixel; 1734 | 1735 | float safethreshold = max(__HQAAL_EDGE_THRESHOLD, __HQAAL_SMALLEST_COLOR_STEP); 1736 | 1737 | bool modifiedpixel = any(edgedata.rg); 1738 | if (HqaaDebugMode == 6 && !modifiedpixel) return float(0.0).xxx; 1739 | if (HqaaDebugMode == 1) return float3(edgedata.rg, 0.0); 1740 | if (HqaaDebugMode == 2) return blendingdata.rgb; 1741 | if (HqaaDebugMode == 7) { float usedthreshold = 1.0 - (edgedata.a / safethreshold); return float3(0.0, saturate(usedthreshold), 0.0); } 1742 | 1743 | float3 original = pixel; 1744 | bool altered = false; 1745 | pixel = ConditionalDecode(pixel); 1746 | bool3 truezero = lnand(1.0.xxx, pixel); 1747 | float3 AAdot = pixel; 1748 | 1749 | float blendweight = 1.0 - saturate(blendingdata.x + blendingdata.y + blendingdata.z + blendingdata.w); 1750 | float blendclamp = any(blendingdata) ? blendweight : 1.0; 1751 | float lowlumaclamp = min(edgedata.a, safethreshold) / safethreshold; 1752 | float blendstrength = __HQAAL_HYSTERESIS_STRENGTH * min(blendclamp, lowlumaclamp); 1753 | 1754 | float hysteresis = (dot(pixel, __HQAAL_LUMA_REF) - edgedata.b) * blendstrength; 1755 | if (abs(hysteresis) > __HQAAL_HYSTERESIS_FUDGE) 1756 | { 1757 | pixel = pow(abs(1.0 + hysteresis) * 2.0, log2(pixel)); 1758 | pixel = lnand(pixel, truezero); 1759 | altered = true; 1760 | } 1761 | 1762 | //output 1763 | if (HqaaDebugMode == 6) 1764 | { 1765 | // hysteresis pattern 1766 | return sqrt(abs(pixel - AAdot)); 1767 | } 1768 | else if (altered) return ConditionalEncode(pixel); 1769 | else return original; 1770 | } 1771 | 1772 | /***************************************************************************************************************************************/ 1773 | /******************************************************* HYSTERESIS SHADER CODE END ****************************************************/ 1774 | /***************************************************************************************************************************************/ 1775 | 1776 | technique HQAAL < 1777 | ui_tooltip = "============================================================\n" 1778 | "Hybrid high-Quality Anti-Aliasing combines techniques of\n" 1779 | "both SMAA and FXAA to produce best possible image quality\n" 1780 | "from using both. HQAA uses customized edge detection methods\n" 1781 | "designed for maximum possible aliasing detection.\n" 1782 | "============================================================"; 1783 | ui_label = "HQAA Lite"; 1784 | > 1785 | { 1786 | pass EdgeDetection 1787 | { 1788 | VertexShader = PostProcessVS; 1789 | PixelShader = HQAALHybridEdgeDetectionPS; 1790 | RenderTarget = HQAALedgesTex; 1791 | } 1792 | pass SMAABlendCalculation 1793 | { 1794 | VertexShader = HQAALBlendingWeightCalculationVS; 1795 | PixelShader = HQAALBlendingWeightCalculationPS; 1796 | RenderTarget = HQAALblendTex; 1797 | ClearRenderTargets = true; 1798 | } 1799 | pass FXAA 1800 | { 1801 | VertexShader = HQAALNeighborhoodBlendingVS; 1802 | PixelShader = HQAALFXPS; 1803 | } 1804 | pass SMAABlending 1805 | { 1806 | VertexShader = HQAALNeighborhoodBlendingVS; 1807 | PixelShader = HQAALNeighborhoodBlendingPS; 1808 | } 1809 | #if HQAAL_FXAA_MULTISAMPLING > 1 1810 | pass FXAA 1811 | { 1812 | VertexShader = HQAALNeighborhoodBlendingVS; 1813 | PixelShader = HQAALFXPS; 1814 | } 1815 | #endif 1816 | #if HQAAL_FXAA_MULTISAMPLING > 2 1817 | pass FXAA 1818 | { 1819 | VertexShader = HQAALNeighborhoodBlendingVS; 1820 | PixelShader = HQAALFXPS; 1821 | } 1822 | #endif 1823 | #if HQAAL_FXAA_MULTISAMPLING > 3 1824 | pass FXAA 1825 | { 1826 | VertexShader = HQAALNeighborhoodBlendingVS; 1827 | PixelShader = HQAALFXPS; 1828 | } 1829 | #endif 1830 | #if HQAAL_FXAA_MULTISAMPLING > 4 1831 | pass FXAA 1832 | { 1833 | VertexShader = HQAALNeighborhoodBlendingVS; 1834 | PixelShader = HQAALFXPS; 1835 | } 1836 | #endif 1837 | #if HQAAL_FXAA_MULTISAMPLING > 5 1838 | pass FXAA 1839 | { 1840 | VertexShader = HQAALNeighborhoodBlendingVS; 1841 | PixelShader = HQAALFXPS; 1842 | } 1843 | #endif 1844 | pass Hysteresis 1845 | { 1846 | VertexShader = HQAALNeighborhoodBlendingVS; 1847 | PixelShader = HQAALHysteresisPS; 1848 | } 1849 | } 1850 | --------------------------------------------------------------------------------