├── .github └── FUNDING.yml ├── LICENSE.md ├── README.md ├── Shaders ├── QuarkCommon.fxh ├── Quark_Continuity.fx ├── Quark_Fast_GI.fx ├── Quark_Film_Grain.fx ├── Quark_Local_Contrast.fx ├── Quark_Motion.fx └── Quark_Xenon_Bloom.fx └── Textures ├── QuarkBN.png └── QuarkDirt.png /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: Zenteon 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 15 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ### AGNYA License 2 | 3 | Copyright (C) 2024 Daniel Oren-Ibarra 4 | 5 | All rights reserved unless explicitly stated. Rev 1.3 6 | 7 | 8 | You may get a full copy of this license at https://github.com/nvb-uy/AGNYA-License 9 | 10 | 11 | ### TERMS AND CONDITIONS 12 | 13 | 14 | 0. Definitions. 15 | 16 | 17 | "Copyright" also means copyright-like laws that apply to other kinds of 18 | works, such as semiconductor masks. 19 | 20 | 21 | "The Project" refers to any copyrightable work licensed under this 22 | License. Each licensee is addressed as "you". "Licensees", "users" and 23 | "recipients" may be individuals or organizations. 24 | 25 | 26 | "The Author" or "Original Author" refers to the original creator of this project and its 27 | source code. 28 | 29 | 30 | To "modify" a work means to copy from or adapt all or part of the work 31 | in a fashion requiring copyright permission, other than the making of an 32 | exact copy. The resulting work is called a "modified version" of the 33 | earlier work or a work "based on" the earlier work. 34 | 35 | 36 | A "covered work" means either the unmodified Project or a work based 37 | on the Project. 38 | 39 | 40 | To "propagate" a work means to do anything with it that, without 41 | permission, would make you directly or secondarily liable for infringement 42 | under applicable copyright law, except executing it on a computer or 43 | modifying a private copy. Propagation includes copying, distribution 44 | (with or without modification), making available to the public, and in 45 | some countries other activities as well. 46 | 47 | 48 | To "convey" a work means any kind of propagation that enables other 49 | parties to make or receive copies. Mere interaction with a user through a 50 | computer network, with no transfer of a copy, is not conveying. 51 | 52 | 53 | To "contribute" refers to offering any form of material held to copyright to 54 | be used in the project. 55 | This could be in any way, such as, but not limited to: pull requests, explicitly 56 | sharing it with the author or giving permission for the use of it. 57 | 58 | 59 | 1. Redistribution 60 | 61 | 62 | Public propagation of this project or parts of it requires you to 63 | exclusively use the official links provided by the author. This means that 64 | independently hosting a copy of this project and propagating it using this 65 | hosted version is prohibited. The usage of link monetization services on 66 | redistribution is strictly prohibited. 67 | Websites and Blogs collecting projects similar to this project are 68 | required to ask for explicit permission before adding this project to 69 | its database. 70 | 71 | 72 | 2. Private Modifications 73 | 74 | 75 | Users are allowed to create private modifications of this project or its code 76 | without explicit permission. Redistribution of these modified versions 77 | however require explicit permission by the author of the original project. 78 | See section 3 for more information about public modifications. 79 | 80 | 81 | 3. Public Modifications 82 | 83 | 84 | Public redistribution of a modified version of this project or its code requires 85 | explicit permission from the original author. 86 | In order for the modification to be applicable for this it has to contain a certain amount 87 | of original work by the user. 88 | This modified version's source code must be publicly available unless explicit permission is given by the original author. 89 | The modification's license must not be changed unless explicit permission is given by the original author. 90 | Furthermore the original project and its author have to be clearly 91 | credited. Any means of monetization through this modified version is 92 | strictly prohibited unless explicit permission by the original project's 93 | author is given. 94 | 95 | 96 | 4. Usage of parts of this project as part of another, original project 97 | 98 | 99 | Using parts of this project's source code as part of another, original 100 | project requires explicit permission from this project's author. 101 | Furthermore this project, its author and the parts used have to be 102 | clearly credited. Additionally any means of monetization on this modified 103 | version are prohibited unless explicit permission is given. 104 | 105 | 106 | 5. Liability 107 | 108 | 109 | The project is provided "as is", without warranty of any kind, express 110 | or implied, including but not limited to the warranties of merchantability, 111 | fitness for a particular purpose and noninfringement. In no event shall the 112 | author or copyright holders be liable for any claim, damages or other 113 | liability, whether in an action of contract, tort or otherwise, arising from, 114 | out of or in connection with the project or the use or other dealings in the 115 | project. 116 | 117 | 118 | 6. Contribution 119 | 120 | 121 | All form of contribution on this project, let it be public or private, 122 | will be under the Creative Commons 0 1.0 Universal (CC0 1.0) License. 123 | By contributing, you agree that you hold all copyright rights of the material you are contributing. 124 | 125 | 126 | 7. Disclaimer 127 | 128 | 129 | This License and its terms are subject to change and review at any time 130 | by this project's author. 131 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QuarkFX 2 | **Quark Shaders for ReShade** 3 | 4 | Quark is a repository of efficient and high quality shaders meant to adhere closely to physical methods while maintaining a consistent artistic vision, and ignoring the restricting limitations of DirectX9. 5 | If you do wish to use Quark Shaders in older Dx9 games, it's recommended to use a wrapper such as DXVK or dgVoodoo2. 6 | 7 | **Current Effects** 8 | 9 | **Xenon:** 10 | 11 | Xenon is an artistic bloom meant to provide excellent point precision and ranges without overpowering the image. 12 | It uses a mixture of physically based and catered methods to create dramatic, but pleasing results. 13 | ![UnityEmpty3d 2024-05-22 08-06-36](https://github.com/Zenteon/QuarkFX/assets/162768653/b6460599-dc2d-48fd-b026-5730bdc2fc86) 14 | 15 | **Crystallis:** 16 | 17 | Crystallis is a fast physically based approximation of film grain that uses a few tricks to simulate hundreds of grains for the performance cost of just one per pixel. 18 | ![image](https://github.com/Zenteon/QuarkFX/assets/162768653/d232ce3c-0a26-469a-beb1-aff48835f810) 19 | -------------------------------------------------------------------------------- /Shaders/QuarkCommon.fxh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define RES float2(BUFFER_WIDTH, BUFFER_HEIGHT) 4 | #define FARPLANE RESHADE_DEPTH_LINEARIZATION_FAR_PLANE 5 | #define ASPECT_RATIO (RES.x/RES.y) 6 | #define IASPECT_RATIO float2(1.0, RES.x / RES.y) 7 | 8 | #define FULLTEX Width = RES.x; Height = RES.y 9 | #define HALFTEX Width = 0.5 * RES.x; Height = 0.5 * RES.y 10 | #define QUARTEX Width = 0.25 * RES.x; Height = 0.25 * RES.y 11 | #define WRAPMODE(WTYPE) AddressU = WTYPE; AddressV = WTYPE; AddressW = WTYPE 12 | #define FILTER(FTYPE) MagFilter = FTYPE; MinFilter = FTYPE; MipFilter = FTYPE 13 | 14 | #define DIVRES(DIVRES_RIV) Width = BUFFER_WIDTH / DIVRES_RIV; Height = BUFFER_HEIGHT / DIVRES_RIV 15 | 16 | #define IGNSCROLL 5.588238 17 | 18 | 19 | namespace Continuity { 20 | texture NormalTexture { FULLTEX; Format = RG8; MipLevels = 7; }; 21 | texture NorSamTexture { QUARTEX; Format = RG8; MipLevels = 7; }; 22 | texture DepSamTexture { QUARTEX; Format = R32F; MipLevels = 7; }; 23 | texture ColorTexture { FULLTEX; Format = RGBA8; MipLevels = 1; }; 24 | texture DepDerivTex { FULLTEX; Format = R16F; }; 25 | texture ThickTexture { FULLTEX; Format = R8; MipLevels = 7; }; 26 | //texture ThkSamTexture { QUARTEX; Format = R8; MipLevels = 7; }; 27 | 28 | sampler NormalBuffer { Texture = NormalTexture; FILTER(POINT); }; 29 | sampler NorSamBuffer { Texture = NorSamTexture; FILTER(POINT); }; 30 | sampler DepSamBuffer { Texture = DepSamTexture; FILTER(POINT); }; 31 | sampler ColorBuffer { Texture = ColorTexture; FILTER(POINT); }; 32 | sampler DepDeriv { Texture = DepDerivTex; FILTER(POINT); }; 33 | 34 | sampler ThickBuffer { Texture = ThickTexture; FILTER(POINT); }; 35 | //sampler ThkSamBuffer { Texture = ThkSamTexture; }; 36 | } 37 | 38 | 39 | 40 | //=================================================================================== 41 | //Projections 42 | //=================================================================================== 43 | 44 | #define FOVR 0.5 45 | 46 | #define FOV 1.39626 47 | 48 | #define prjf rcp(tan(0.5 * FOV)) 49 | #define projM float4x4( prjf / ASPECT_RATIO,0,0,0, 0,prjf,0,0, 0,0,-1,-1, 0,0,-2,0) 50 | #define iprojM float4x4( rcp(prjf / ASPECT_RATIO),0,0,0, 0,rcp(prjf),0,0, 0,0,-1,-1, 0,0,rcp(-2),0) 51 | 52 | float3 GetEyePos(float2 xy, float z) 53 | { 54 | //xy *= IASPECT_RATIO; 55 | float2 A = -rcp(prjf * IASPECT_RATIO); 56 | float3 M = float3(-2*A.xy,0); 57 | 58 | float3 xyz = (float3(xy.xy,0) * M + float3(A.xy,1)) * (z * FARPLANE + 1.0); 59 | return xyz; 60 | } 61 | 62 | float3 GetEyePos(float3 xyz) 63 | { 64 | //xyz.xy *= IASPECT_RATIO; 65 | float2 A = -rcp(prjf * IASPECT_RATIO); 66 | float3 M = float3(-2*A.xy,0); 67 | 68 | xyz = (float3(xyz.xy,0) * M + float3(A.xy,1)) * (xyz.z * FARPLANE + 1.0); 69 | return xyz; 70 | } 71 | 72 | float3 NorEyePos(float2 xy) 73 | { 74 | float z = ReShade::GetLinearizedDepth(xy); 75 | //xy *= IASPECT_RATIO; 76 | float2 A = -rcp(prjf * IASPECT_RATIO); 77 | float3 M = float3(-2*A.xy,0); 78 | 79 | float3 xyz = (float3(xy.xy,0) * M + float3(A.xy,1)) * (z * FARPLANE + 1.0); 80 | return xyz; 81 | 82 | } 83 | 84 | float3 GetScreenPos(float3 xyz) 85 | { 86 | float2 A = -rcp(prjf * IASPECT_RATIO); 87 | float3 M = float3(-2*A.xy,0); 88 | 89 | xyz /= xyz.z + 1.0; 90 | xyz = float3(xyz.xy, 0) / M - float3(A.xy,1)/float3(M.xy,1); 91 | return xyz; 92 | 93 | } 94 | 95 | 96 | 97 | float3 UVtoOCT(float2 xy) 98 | { 99 | float3 xyz = float3(2f * xy - 1f, 0.0); 100 | 101 | float2 posAbs = abs(xyz.xy); 102 | xyz.z = 1.0 - (posAbs.x + posAbs.y); 103 | 104 | if(xyz.z < 0) { 105 | xyz.xy = sign(xyz.xy) * (1.0 - posAbs.yx); 106 | } 107 | return xyz; //already normalized 108 | } 109 | 110 | float2 OCTtoUV(float3 xyz) { 111 | float3 octsn = sign(xyz); 112 | 113 | float sd = dot(xyz, octsn); 114 | float3 oct = xyz / sd; 115 | 116 | if(oct.z < 0) { 117 | float3 posAbs = abs(oct); 118 | oct.xy = octsn.xy * (1.0 - posAbs.yx); 119 | } 120 | return 0.5 + 0.5 * oct.xy; 121 | } 122 | 123 | //=================================================================================== 124 | //Encoding 125 | //=================================================================================== 126 | 127 | float2 OctWrap(float2 v) 128 | { 129 | return (1.0- abs(v.yx)) * (v.xy >= 0.0 ? 1.0 : -1.0); 130 | } 131 | 132 | float2 NormalEncode(float3 n) 133 | { 134 | return OCTtoUV(-n); 135 | //return 0.5 - 0.5 * normalize(n).xy; 136 | } 137 | 138 | float3 NormalDecode(float2 n) 139 | { 140 | /*n = -2f * n + 1f; 141 | float z = 1.0 - length(n); 142 | return float3(n.xy, -z);*/ 143 | return normalize(-UVtoOCT(n)); 144 | } 145 | 146 | //=================================================================================== 147 | //Sampling 148 | //=================================================================================== 149 | 150 | float GetDepDer(float2 xy) 151 | { 152 | return tex2Dlod(Continuity::DepDeriv, float4(xy, 0, 0)).x; 153 | } 154 | 155 | float3 GetNormal(float2 xy) 156 | { 157 | float2 n = tex2Dlod(Continuity::NormalBuffer, float4(xy, 0, 0)).xy; 158 | return NormalDecode(n); 159 | } 160 | 161 | float3 SampleNormal(float2 xy, float l) 162 | { 163 | float2 n = tex2Dlod(Continuity::NorSamBuffer, float4(xy, 0, l)).xy; 164 | return NormalDecode(n); 165 | } 166 | 167 | float GetDepth(float2 xy) 168 | { 169 | return ReShade::GetLinearizedDepth(xy); 170 | } 171 | 172 | float SampleDepth(float2 xy, float l) 173 | { 174 | return tex2Dlod(Continuity::DepSamBuffer, float4(xy, 0, l)).x; 175 | } 176 | 177 | float3 GetBackBuffer(float2 xy) 178 | { 179 | return tex2D(ReShade::BackBuffer, xy).rgb; 180 | } 181 | 182 | float3 GetAlbedo(float2 xy) 183 | { 184 | return tex2D(Continuity::ColorBuffer, xy).rgb; 185 | } 186 | 187 | float GetThickness(float2 xy) 188 | { 189 | return tex2Dlod(Continuity::ThickBuffer, float4(xy, 0, 0)).x; 190 | } 191 | 192 | 193 | //=================================================================================== 194 | //Functions 195 | //=================================================================================== 196 | 197 | float GetLuminance( float3 x) 198 | { 199 | return 0.2126 * x.r + 0.7152 * x.g + 0.0722 * x.b; 200 | } 201 | 202 | float3 ReinJ(float3 x, float HDR_RED, bool bypass, bool forceLinear) 203 | { 204 | if(bypass) return max( pow(x, 1.0 / (1.0 + 1.2 * forceLinear) ), 0.001); 205 | //float lum = dot(x, float3(0.2126, 0.7152, 0.0722)); 206 | //float3 tx = x / (x + 1.0); 207 | //float3 o = pow(HDR_RED * lerp(x / (lum + 1.0), tx, pow(tx, 1.0) ), 1.0 / 2.2); 208 | //return lerp( dot(o, float3(0.2126, 0.7152, 0.0722)), o, 1.0); 209 | return pow(HDR_RED * (x / (x + 1.0)), 1.0 / 2.2); 210 | } 211 | 212 | float3 IReinJ(float3 x, float HDR_RED, bool bypass, bool forceLinear) 213 | { 214 | if(bypass) return max( pow(x, 1.0 + 1.2 * forceLinear), 0.001); 215 | x = pow(x, 2.2); 216 | //float lum = dot(x, float3(0.2126, 0.7152, 0.0722)); 217 | //float3 tx = -x / (x - HDR_RED); 218 | //return lerp(tx, -lum / ((0.5 * x + 0.5 * lum) - HDR_RED), pow(x, 1.0) ); 219 | 220 | return -x / (x - HDR_RED); 221 | 222 | } 223 | 224 | float CalcDiffuse(float3 pos0, float3 nor0, float3 pos1, float3 nor1, float backface) 225 | { 226 | float diff0 = saturate(dot(nor0, normalize(pos1 - pos0)) - 0.0); 227 | 228 | //Option for backface lighting, looks bad 229 | float diff1 = abs(clamp((dot(nor1, normalize(pos0 - pos1)) - 0.0), -backface, 1.0)); 230 | return diff0 * pow(diff1, 1.0); 231 | } 232 | 233 | float CalcTransfer(float3 pos0, float3 nor0, float3 pos1, float3 nor1, float disDiv, float att, float backface) 234 | { 235 | float lumMult = pow(length(pos1) / (1.0 + disDiv) + 1.0, 2.0); 236 | float eyeMult = rcp( pow(length(pos0) / (1.0 + disDiv) + 1.0, 2.0) ); 237 | float dist = rcp( pow(att + distance(pos0, pos1) / (1.0 + disDiv) + 1.0, 2.0) ); 238 | float lamb = CalcDiffuse(pos0, nor0, pos1, nor1, backface); 239 | return max(lamb * eyeMult * lumMult * dist, 0.001); 240 | } 241 | 242 | 243 | float CalcSpecular(float3 pos0, float3 refl0, float3 pos1, float3 nor1, float disDiv, float att, float power) 244 | { 245 | float diff0 = pow(saturate(dot(refl0, normalize(pos1 - pos0)) - 0.1), power); 246 | float diff1 = saturate((dot(nor1, normalize(pos0 - pos1)) - 0.1)); 247 | 248 | float lumMult = pow(length(pos1) / (1.0 + disDiv) , 2.0); 249 | float eyeMult = rcp( pow(length(pos0) / (1.0 + disDiv) , 2.0 )); 250 | float dist = rcp( pow(att + distance(pos0, pos1) / disDiv, 2.0) ); 251 | float trns = diff0 * diff1; 252 | return max(power * trns * eyeMult * lumMult * dist, 0.00); 253 | } 254 | 255 | float CalcSSS(float thk, float3 viewV, float3 surfN, float3 lightV) 256 | { 257 | #define DISTORT 1.0 258 | #define POWER 1.0 259 | #define SCALE 1.0 260 | #define AMBIENT 0.2 261 | 262 | float3 thvLum = lightV + surfN * DISTORT; 263 | float thkDot = pow( saturate(dot(viewV, - thvLum)), POWER) * SCALE; 264 | float sss = (thkDot + AMBIENT) * thk; 265 | return sss; 266 | } 267 | 268 | -------------------------------------------------------------------------------- /Shaders/Quark_Continuity.fx: -------------------------------------------------------------------------------- 1 | #include "ReShade.fxh" 2 | #include "QuarkCommon.fxh" 3 | 4 | #if(__RENDERER__ != 0x9000) 5 | 6 | uniform int FRAME_COUNT < 7 | source = "framecount";>; 8 | 9 | uniform bool DO_SMOOTH < 10 | ui_label = "Smoothed Normals"; 11 | > = 0; 12 | 13 | uniform bool DO_TEX < 14 | ui_label = "Textured Normals"; 15 | > = 0; 16 | 17 | uniform float TEX_LEVEL < 18 | ui_type = "slider"; 19 | ui_label = "Textured Normals Intensity"; 20 | ui_min = 0.0; 21 | ui_max = 1.0; 22 | > = 0.5; 23 | 24 | uniform float SMTH_THRSH < 25 | ui_type = "slider"; 26 | ui_label = "Smoothed Normals Threshold"; 27 | ui_min = 0.0; 28 | ui_max = 1.0; 29 | > = 0.4; 30 | 31 | uniform float TEX_RAD < 32 | ui_type = "slider"; 33 | ui_label = "Textured Normals Width"; 34 | ui_min = 1.0; 35 | ui_max = 3.0; 36 | > = 1.0; 37 | //=================================================================================== 38 | //Textures/Samplers 39 | //=================================================================================== 40 | namespace Continuity { 41 | 42 | texture DownTex0 { HALFTEX; Format = RGBA8; MipLevels = 1; }; 43 | texture DownTex1 { QUARTEX; Format = RGBA8; MipLevels = 1; }; 44 | texture NorTex0 { FULLTEX; Format = RGBA16; MipLevels = 6; }; 45 | texture NorTex1 { FULLTEX; Format = RGBA16; MipLevels = 6; }; 46 | texture LumTex0 { FULLTEX; Format = R8; MipLevels = 1; }; 47 | 48 | texture HoleMask { FULLTEX; Format = R8; }; 49 | 50 | 51 | //texture LumTex1 { FULLTEX; Format = R8; MipLevels = 1; }; 52 | //texture DownTex { HALFTEX; Format = R8; MipLevels = 1; }; 53 | 54 | 55 | sampler DownSam0 { Texture = DownTex0; }; 56 | sampler DownSam1 { Texture = DownTex1; }; 57 | sampler LumSam0 { Texture = LumTex0; }; 58 | //sampler LumSam1 { Texture = LumTex1; }; 59 | //sampler DownSam { Texture = DownTex; }; 60 | sampler NorSam0 { Texture = NorTex0; }; 61 | sampler NorSam1 { Texture = NorTex1; }; 62 | 63 | sampler NorHole { Texture = HoleMask; FILTER(POINT); }; 64 | 65 | //=================================================================================== 66 | //LumKawase Blur Passes 67 | //=================================================================================== 68 | 69 | float LumDownSample(sampler TEX, float2 xy, float rdiv) 70 | { 71 | float2 res = float2(BUFFER_WIDTH, BUFFER_HEIGHT) / rdiv; 72 | float2 hp = 0.5 / res; 73 | float offset = 1.0; 74 | 75 | float acc = tex2D(TEX, xy).r * 4.0; 76 | acc += tex2D(TEX, xy - hp * offset).r; 77 | acc += tex2D(TEX, xy + hp * offset).r; 78 | acc += tex2D(TEX, xy + float2(hp.x, -hp.y) * offset).r; 79 | acc += tex2D(TEX, xy - float2(hp.x, -hp.y) * offset).r; 80 | 81 | return acc / 8.0; 82 | } 83 | 84 | float LumUpSample(sampler TEX, float2 xy, float rdiv) 85 | { 86 | float2 res = float2(BUFFER_WIDTH, BUFFER_HEIGHT) / rdiv; 87 | float2 hp = 0.5 / res; 88 | float offset = 1.0; 89 | float acc = tex2D(TEX, xy + float2(-hp.x * 2.0, 0.0) * offset).r; 90 | 91 | acc += tex2D(TEX, xy + float2(-hp.x, hp.y) * offset).r * 2.0; 92 | acc += tex2D(TEX, xy + float2(0.0, hp.y * 2.0) * offset).r; 93 | acc += tex2D(TEX, xy + float2(hp.x, hp.y) * offset).r * 2.0; 94 | acc += tex2D(TEX, xy + float2(hp.x * 2.0, 0.0) * offset).r; 95 | acc += tex2D(TEX, xy + float2(hp.x, -hp.y) * offset).r * 2.0; 96 | acc += tex2D(TEX, xy + float2(0.0, -hp.y * 2.0) * offset).r; 97 | acc += tex2D(TEX, xy + float2(-hp.x, -hp.y) * offset).r * 2.0; 98 | 99 | return acc / 12.0; 100 | } 101 | 102 | //=================================================================================== 103 | //Kawase Blur Passes 104 | //=================================================================================== 105 | 106 | float3 DownSample(sampler TEX, float2 xy, float rdiv) 107 | { 108 | float2 res = float2(BUFFER_WIDTH, BUFFER_HEIGHT) / rdiv; 109 | float2 hp = 0.5 / res; 110 | float offset = 1.0; 111 | 112 | float3 acc = tex2D(TEX, xy).rgb * 4.0; 113 | acc += tex2D(TEX, xy - hp * offset).rgb; 114 | acc += tex2D(TEX, xy + hp * offset).rgb; 115 | acc += tex2D(TEX, xy + float2(hp.x, -hp.y) * offset).rgb; 116 | acc += tex2D(TEX, xy - float2(hp.x, -hp.y) * offset).rgb; 117 | 118 | return acc / 8.0; 119 | } 120 | 121 | float3 UpSample(sampler TEX, float2 xy, float rdiv) 122 | { 123 | float2 res = float2(BUFFER_WIDTH, BUFFER_HEIGHT) / rdiv; 124 | float2 hp = 0.5 / res; 125 | float offset = 1.0; 126 | float3 acc = tex2D(TEX, xy + float2(-hp.x * 2.0, 0.0) * offset).rgb; 127 | 128 | acc += tex2D(TEX, xy + float2(-hp.x, hp.y) * offset).rgb * 2.0; 129 | acc += tex2D(TEX, xy + float2(0.0, hp.y * 2.0) * offset).rgb; 130 | acc += tex2D(TEX, xy + float2(hp.x, hp.y) * offset).rgb * 2.0; 131 | acc += tex2D(TEX, xy + float2(hp.x * 2.0, 0.0) * offset).rgb; 132 | acc += tex2D(TEX, xy + float2(hp.x, -hp.y) * offset).rgb * 2.0; 133 | acc += tex2D(TEX, xy + float2(0.0, -hp.y * 2.0) * offset).rgb; 134 | acc += tex2D(TEX, xy + float2(-hp.x, -hp.y) * offset).rgb * 2.0; 135 | 136 | return acc / 12.0; 137 | } 138 | 139 | float2 GetSobel(sampler input, float2 xy, float div, float3 nor) 140 | { 141 | 142 | //float dd = GetDepDer(xy); 143 | float3 pos = NorEyePos(xy); 144 | //float2 norOff = 1.0 - abs(nor.xy); 145 | float cd = 1.0 - GetDepth(xy); 146 | cd *= cd; 147 | float2 hp = div / (RES);// + (dd * 1.0 * FARPLANE)); 148 | //float3 viewV = normalize(pos); 149 | float nMul = 1.0;// / (abs(dot(nor, viewV)) + 0.05); 150 | 151 | 152 | float3 acc;//x, y, normalization value 153 | for(int i = -1; i <= 1; i++) for(int ii = -1; ii <= 1; ii++) 154 | { 155 | float2 offset = cd * hp * float2(i, ii); 156 | 157 | float3 tpos = NorEyePos(xy + offset); 158 | float wd = exp( -10.0 * abs( dot(nor, tpos - pos))); 159 | float xmul = 1.0;//0.5 * (abs(i) == 1.0); 160 | float ymul = 1.0;//0.5 * (abs(ii) == 1.0); 161 | 162 | acc += tex2D(input, xy + offset).r * float3(i, ii, 1.0 / (wd + 0.001) );// * exp( -distance(vpos, ovpos) ); 163 | 164 | } 165 | 166 | /*float2 acc = 0.25 * float2(-1.0, -1.0) * tex2D(input, xy + float2(-hp.x, -hp.y)).r; 167 | acc += float2(-1.0, 0.0) * tex2D(input, xy + float2(-hp.x, 0.0)).r; 168 | acc += 0.25 * float2(-1.0, 1.0) * tex2D(input, xy + float2(-hp.x, hp.y)).r; 169 | 170 | acc += float2(0.0, -1.0) * tex2D(input, xy + float2(0.0, -hp.y)).r; 171 | acc += float2(0.0, 0.0) * tex2D(input, xy + float2(0.0, 0.0)).r; 172 | acc += float2(0.0, 1.0) * tex2D(input, xy + float2(0.0, hp.y)).r; 173 | 174 | acc += 0.25 * float2(1.0, -1.0) * tex2D(input, xy + float2(hp.x, -hp.y)).r; 175 | acc += float2(1.0, 0.0) * tex2D(input, xy + float2(hp.x, 0.0)).r; 176 | acc += 0.25 * float2(1.0, 1.0) * tex2D(input, xy + float2(hp.x, hp.y)).r; 177 | */ 178 | 179 | acc.z /= 9.0; 180 | 181 | return 8.0 * TEX_LEVEL * TEX_LEVEL * nMul * acc.xy / (acc.z + 0.1);// * (1.0 + 10.0 * dd);//10.0 * acc * (1.0 + 20.0 * dd); 182 | } 183 | 184 | //=================================================================================== 185 | //Downscale Passes 186 | //=================================================================================== 187 | float4 Down0(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 188 | { return float4(DownSample(ReShade::BackBuffer, texcoord, 2.0), 1.0); } 189 | 190 | float4 Down1(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 191 | { return float4(DownSample(DownSam0, texcoord, 4.0), 1.0); } 192 | 193 | float4 Up0(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 194 | { return float4(UpSample(DownSam1, texcoord, 4.0), 1.0); } 195 | 196 | float4 Up1(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target { 197 | float3 blur = UpSample(DownSam0, texcoord, 2.0); 198 | float blurL = 0.2777 + 0.3 * (blur.r + blur.g + blur.b); 199 | float3 input = tex2D(ReShade::BackBuffer, texcoord).rgb; 200 | 201 | return float4(pow(input / blurL, 1.8) , 1.0);//float4(pow(0.8 * input / (blur + 0.2), 1.75), 1.0); 202 | } 203 | 204 | 205 | //=================================================================================== 206 | //Texture Passes 207 | //=================================================================================== 208 | 209 | float LuminBuffer(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 210 | { 211 | if(!DO_TEX) return 0; 212 | float2 hp = 0.5 / RES; 213 | float3 input = GetBackBuffer(xy);//0.5 * abs(GetBackBuffer(xy) + UpSample(ReShade::BackBuffer, xy, 1.5)); 214 | 215 | input = saturate(input); 216 | 217 | return pow( (0.2126 * input.r + 0.7152 * input.g + 0.0722 * input.b), 1.0); 218 | } 219 | 220 | 221 | 222 | void HeightNor(float4 vpos : SV_Position, float2 xy: TexCoord, out float2 cnor : SV_Target0, out float4 nor : SV_Target1) 223 | { 224 | //if(!DO_TEX) return NormalEncode(2f * tex2D(NorSam1, texcoord).xyz - 1f); 225 | /*float hm = 0.05; 226 | float dm = 1.0; 227 | float3 vc = float3(texcoord, hm * tex2D(LumSam0, texcoord).x); 228 | 229 | 230 | float2 xy = texcoord + float2(dm, 0) / RES; 231 | float3 vx0 = vc - float3(xy, hm * tex2D(LumSam0, xy).x); 232 | 233 | xy = texcoord + float2(0, dm) / RES; 234 | float3 vy0 = vc - float3(xy, hm * tex2D(LumSam0, xy).x); 235 | xy = texcoord - float2(dm, 0) / RES; 236 | float3 vx1 = -vc + float3(xy, hm * tex2D(LumSam0, xy).x); 237 | 238 | xy = texcoord - float2(0, dm) / RES; 239 | float3 vy1 = -vc + float3(xy, hm * tex2D(LumSam0, xy).x); 240 | 241 | float3 vx = abs(vx0.z) < abs(vx1.z) ? vx0 : vx1; 242 | float3 vy = abs(vy0.z) < abs(vy1.z) ? vy0 : vy1; 243 | 244 | float3 texN = normalize(cross(vy, vx)); 245 | */ 246 | 247 | float3 surfN = 2f * tex2D(NorSam1, xy).xyz - 1f; 248 | float3 viewV = normalize(NorEyePos(xy)); 249 | 250 | float2 sobel = GetSobel(LumSam0, xy, 0.5 * TEX_RAD, surfN); 251 | sobel += 0.5 * GetSobel(LumSam0, xy, 1.0 * TEX_RAD, surfN); 252 | //sobel += 0.5 * GetSobel(LumSam0, xy, 3.0 * TEX_RAD, surfN); 253 | //sobel += 0.5 * GetSobel(LumSam0, xy, 5.0 * TEX_RAD, surfN); 254 | //sobel += 0.5 * GetSobel(LumSam0, xy, 8.0 * TEX_RAD, surfN); 255 | //sobel += 0.5 * GetSobel(LumSam0, xy, 12.0 * TEX_RAD, surfN); 256 | 257 | float3 texN = normalize(float3(sobel, 1.0)); 258 | //dtexN = -normalize(-viewV + texN * dot(texN, -viewV) ); 259 | //texN *= -1.0; 260 | surfN *= -1.0; 261 | 262 | //surfN = -normalize(lerp(surfN, surfN + texN * dot(surfN, texN), 1.0 * TEX_LEVEL)); 263 | 264 | 265 | float3 n1 = surfN; 266 | float3 n2 = normalize(texN); 267 | 268 | float3x3 nBasis = float3x3( 269 | float3(n1.z, n1.y, -n1.x), // +90 degree rotation around y axis 270 | float3(n1.x, n1.z, -n1.y), // -90 degree rotation around x axis 271 | float3(n1.x, n1.y, n1.z)); 272 | 273 | float3 r = normalize(n2.x*nBasis[0] + n2.y*nBasis[1] + n2.z*nBasis[2]); 274 | //r*0.5 + 0.5; 275 | 276 | //surfN = normalize( float3(surfN.xy * texN.z + texN.xy * surfN.z, surfN.z * texN.z) );//normalize(texN * dot(surfN, texN) / texN.z - surfN); 277 | //surfN = normalize(texN * dot(surfN, texN) / texN.z - surfN); 278 | //texN.xy *= -1.0; 279 | //texN.xy /= texN.z; 280 | //texN.z = saturate(texN.z); 281 | //surfN.xy /= surfN.z; 282 | texN = lerp(float3(0.0, 0.0, 1.0), texN, 0.5); 283 | surfN = normalize(float3(surfN.xy + texN.xy, surfN.z * texN.z)); 284 | //surfN.z = saturate(surfN.z); 285 | //surfN = normalize(surfN); 286 | 287 | //float3 tempN = normalize(float3(surfN.xy / surfN.z + texN.xy / texN.z, 1.0)); 288 | 289 | //texN.z *= -1.0; 290 | //texN.xy *= -1.0;//normalize(float3(-texN.xy, saturate(texN.z)) ); 291 | cnor = NormalEncode(-surfN);//distance(surfN, texN).xx;//NormalEncode(texN); 292 | nor = float4(0.5 + 0.5 * texN, 1.0); 293 | } 294 | 295 | 296 | //=================================================================================== 297 | //Normals 298 | //=================================================================================== 299 | 300 | void GenNorBuffer(float4 vpos : SV_Position, float2 texcoord : TexCoord, out float4 normal : SV_Target0, out float depDeriv : SV_Target1) 301 | { 302 | float3 vc = NorEyePos(texcoord); 303 | 304 | float3 vx0 = vc - NorEyePos(texcoord + float2(1, 0) / RES); 305 | float3 vy0 = vc - NorEyePos(texcoord + float2(0, 1) / RES); 306 | 307 | float3 vx1 = -vc + NorEyePos(texcoord - float2(1, 0) / RES); 308 | float3 vy1 = -vc + NorEyePos(texcoord - float2(0, 1) / RES); 309 | 310 | float3 vx01 = vc - NorEyePos(texcoord + float2(2, 0) / RES); 311 | float3 vy01 = vc - NorEyePos(texcoord + float2(0, 2) / RES); 312 | 313 | float3 vx11 = -vc + NorEyePos(texcoord - float2(2, 0) / RES); 314 | float3 vy11 = -vc + NorEyePos(texcoord - float2(0, 2) / RES); 315 | 316 | float dx0 = abs(vx0.z + (vx0.z - vx01.z)); 317 | float dx1 = abs(vx1.z + (vx1.z - vx11.z)); 318 | 319 | float dy0 = abs(vy0.z + (vy0.z - vy01.z)); 320 | float dy1 = abs(vy1.z + (vy1.z - vy11.z)); 321 | 322 | float3 vx = dx0 < dx1 ? vx0 : vx1; 323 | float3 vy = dy0 < dy1 ? vy0 : vy1; 324 | //float3 vx = abs(vx0.z) < abs(vx1.z) ? vx0 : vx1; 325 | //float3 vy = abs(vy0.z) < abs(vy1.z) ? vy0 : vy1; 326 | 327 | float3 output = 0.5 + 0.5 * normalize(cross(vy, vx)); 328 | 329 | depDeriv = abs(vx.z + vy.z); 330 | normal = float4(output, 1.0); 331 | } 332 | 333 | //fill holes in normals 334 | void FillNorBuffer(float4 vpos : SV_Position, float2 xy : TexCoord, out float4 normal : SV_Target0, out float depDeriv : SV_Target1) 335 | { 336 | depDeriv = tex2D(NorHole, xy).x; 337 | normal = 2f * tex2D(NorSam0, xy) - 1f; 338 | 339 | 340 | 341 | float2 fp = 1.0 / RES; 342 | if(round(depDeriv + 0.4) > 0) 343 | { 344 | normal = 0.0; depDeriv = 0.0; 345 | 346 | 347 | normal += 2f * tex2D(NorSam0, xy + float2(fp.x, 0.0)) - 1f; depDeriv += tex2D(NorHole, xy + float2(fp.x, 0.0)).x; 348 | normal += 2f * tex2D(NorSam0, xy + float2(-fp.x, 0.0)) - 1f; depDeriv += tex2D(NorHole, xy + float2(-fp.x, 0.0)).x; 349 | normal += 2f * tex2D(NorSam0, xy + float2(0.0, fp.y)) - 1f; depDeriv += tex2D(NorHole, xy + float2(0.0, fp.y)).x; 350 | normal += 2f * tex2D(NorSam0, xy + float2(0.0, -fp.y)) - 1f; depDeriv += tex2D(NorHole, xy + float2(0.0, -fp.y)).x; 351 | normal *= 0.25; depDeriv *= 0.25; 352 | } 353 | normal = 0.5 + 0.5 * normalize(normal); 354 | } 355 | 356 | 357 | #define RAD 6 358 | 359 | float3 NorSmooth(sampler tex, float2 xy, bool x) 360 | { 361 | 362 | float3 cenN = 2f * tex2D(tex, xy).xyz - 1f; 363 | if(!DO_SMOOTH) return cenN; 364 | float cenD = ReShade::GetLinearizedDepth(xy); 365 | float3 surfVP = GetEyePos(xy, cenD); 366 | 367 | float pdDep = tex2D(NorHole, xy).x;//(ddy(cenD) + ddx(cenD));// 368 | 369 | float3 acc = cenN; //Accumulated Blending 370 | float accW = 1.0; //Accumulated Weights 371 | 372 | float2 hp = 1.0 / RES; 373 | 374 | float3 edgeM = 2f * tex2Dlod(tex, float4(xy, 0, 1)).xyz - 1f; 375 | //edgeM += 2f * tex2D(tex, xy + float2(hp.x, -hp.y)).xyz - 1f; 376 | //edgeM += 2f * tex2D(tex, xy + float2(-hp.x, hp.y)).xyz - 1f; 377 | //edgeM += 2f * tex2D(tex, xy + float2(-hp.x, -hp.y)).xyz - 1f; 378 | 379 | edgeM = 1.0 - 2.0 * distance(edgeM, cenN); 380 | 381 | float4 minN; 382 | float4 maxN; 383 | 384 | for(int i = -RAD; i <= RAD; i++) 385 | { 386 | //if(i == 0) continue; 387 | float2 offset = 2.0 * sign(i) * pow(abs(i) + 1, 1.2) * float2(x, !x) / RES; 388 | float3 curN = 2f * tex2Dlod(tex, float4(xy + offset, 0, 1)).xyz - 1f; 389 | float curD = ReShade::GetLinearizedDepth(xy + offset); 390 | 391 | float3 tempVP = GetEyePos(xy + offset, curD); 392 | 393 | float wG = 1.0;// + abs(i - pow(abs(i), 1.2));//1.0;//exp(-pow((2.0 / RAD) * i, 2.0)); 394 | float wN = dot(cenN, curN) >= SMTH_THRSH; 395 | float wD = exp( -(8.0) * abs(dot(cenN, tempVP - surfVP)) );//exp(-2.5 * distance(cenD, curD) / (abs(pdDep * (cenD - curD)) + 0.001) );//exp(-distance(cenD, curD) * 10000.0); 396 | 397 | acc += curN * wN * wD * wG; 398 | accW += wN * wD * wG; 399 | 400 | } 401 | 402 | return normalize(acc / accW); 403 | } 404 | 405 | //=================================================================================== 406 | //Normal Passes 407 | //=================================================================================== 408 | 409 | float4 SmoothNormals0(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 410 | { 411 | float3 Normals = NorSmooth(NorSam1, texcoord, 1).xyz; 412 | return float4(0.5 + 0.5 * Normals, 1f); 413 | } 414 | 415 | float4 SmoothNormals1(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 416 | { 417 | float3 Normals = NorSmooth(NorSam0, texcoord, 0).xyz; 418 | return float4(0.5 + 0.5 * Normals, 1f); 419 | } 420 | 421 | float2 SaveSamN(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 422 | { 423 | float3 offd; 424 | float2 hp = 2.0 / RES; 425 | 426 | float2 offset = float2(hp.x, hp.y); 427 | float d = GetDepth(xy + offset); 428 | if(d > offd.z) offd = float3(xy + offset, d); 429 | 430 | offset = float2(hp.x, -hp.y); 431 | d = GetDepth(xy + offset); 432 | if(d > offd.z) offd = float3(xy + offset, d); 433 | 434 | offset = float2(-hp.x, hp.y); 435 | d = GetDepth(xy + offset); 436 | if(d > offd.z) offd = float3(xy + offset, d); 437 | 438 | offset = float2(-hp.x, -hp.y); 439 | d = GetDepth(xy + offset); 440 | if(d > offd.z) offd = float3(xy + offset, d); 441 | 442 | 443 | return tex2D(Continuity::NormalBuffer, offd.xy).xy; 444 | } 445 | 446 | float SaveSamD(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 447 | { 448 | float2 hp = 1.0 / RES; //half res render target 449 | float d = 0.0; 450 | 451 | /* 452 | d = min(d, ReShade::GetLinearizedDepth(texcoord + float2(hp.x, hp.y) ) ); 453 | d = min(d, ReShade::GetLinearizedDepth(texcoord + float2(hp.x, -hp.y) ) ); 454 | d = min(d, ReShade::GetLinearizedDepth(texcoord + float2(-hp.x, hp.y) ) ); 455 | d = min(d, ReShade::GetLinearizedDepth(texcoord + float2(-hp.x, -hp.y) ) ); 456 | */ 457 | 458 | d = max(d, ReShade::GetLinearizedDepth(texcoord + float2(hp.x, hp.y) ) ); 459 | d = max(d, ReShade::GetLinearizedDepth(texcoord + float2(hp.x, -hp.y) ) ); 460 | d = max(d, ReShade::GetLinearizedDepth(texcoord + float2(-hp.x, hp.y) ) ); 461 | d = max(d, ReShade::GetLinearizedDepth(texcoord + float2(-hp.x, -hp.y) ) ); 462 | 463 | 464 | return d; 465 | } 466 | 467 | float3 CNNormal(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 468 | { 469 | float3 input = 0.5 + 0.5 * GetNormal(texcoord); 470 | return input; 471 | } 472 | 473 | //=================================================================================== 474 | //Thickness Passes 475 | //=================================================================================== 476 | float IGN(float2 xy) 477 | { 478 | float3 conVr = float3(0.06711056, 0.00583715, 52.9829189); 479 | return frac( conVr.z * frac(dot(xy,conVr.xy)) ); 480 | } 481 | 482 | float TraceTHICC(float2 xy, float3 surfN, float surfD, float2 offset, float jitter) 483 | { 484 | float3 surfVP = GetEyePos(xy, surfD); 485 | 486 | float maxA;//horizon vector, vector dot 487 | float maxP; 488 | float dmult = 10.0 + 40.0 / length(surfVP); 489 | 490 | for(int i = 1; i <= 4; i++) 491 | { 492 | float2 npos = xy + dmult * offset * (i * jitter); 493 | if(abs(npos.x - 0.5) > 0.5 || abs(npos.y - 0.5) > 0.5) break; 494 | float tD = SampleDepth(npos, 0.5 * i) - 0.0001; 495 | float3 tVP = GetEyePos(npos, tD); 496 | float tA = dot(surfN, normalize(tVP - surfVP)); 497 | 498 | 499 | 500 | maxP += 40.0 * saturate(tA) / length(surfVP);// / sqrt(1.0 + distance(tVP, surfVP));//RAY_LENGTH * tA / (1.0 + length(tVP - surfVP)); 501 | 502 | } 503 | 504 | 505 | return saturate(maxP / 4.0);// * maxA.x; 506 | } 507 | 508 | float CalcTHICC(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 509 | { 510 | if( (FRAME_COUNT % 2) + (vpos.y + (vpos.x % 2)) % 2 == 0) discard; 511 | float3 surfN = GetNormal(xy); 512 | float surfD = GetDepth(xy); 513 | 514 | 515 | float dir = 6.28 * IGN(vpos.xy + 5.588238 * ((FRAME_COUNT % 128) + 1)); 516 | 517 | //float2 offset = float2(cos(dir), sin(dir)) / RES; 518 | 519 | #define HORIZONS 2 520 | 521 | float AOacc; 522 | for(int i = 1; i <= HORIZONS; i++) 523 | { 524 | 525 | float2 offset = float2(cos(dir), sin(dir)) / RES; 526 | //if(abs(xy.x + offset.x - 0.5) > 0.5 || abs(xy.y + offset.y - 0.5) > 0.5) break; 527 | //offset *= (1.0 - surfD); 528 | float jitter = IGN(vpos.xy + (i + 1) * 100.0); 529 | 530 | AOacc += TraceTHICC(xy, -surfN, surfD, offset, jitter);//countbits(~BITFIELD) / 32.0; 531 | 532 | dir += 6.28 / HORIZONS; 533 | } 534 | 535 | 536 | return (AOacc / HORIZONS); 537 | } 538 | 539 | //=================================================================================== 540 | //Technique 541 | //=================================================================================== 542 | 543 | 544 | technique Continuity < 545 | ui_label = "Quark: Continuity"; 546 | ui_tooltip = 547 | " Continuity - Made by Zenteon \n" 548 | "\n=================================================================================================" 549 | "\n" 550 | "\nContinuity is a prepass shader meant to provide information to other shaders like MSRT" 551 | "\n" 552 | "\n================================================================================================="; 553 | > 554 | { 555 | pass{ VertexShader = PostProcessVS; PixelShader = Down0; RenderTarget = DownTex0; } 556 | pass{ VertexShader = PostProcessVS; PixelShader = Down1; RenderTarget = DownTex1; } 557 | pass{ VertexShader = PostProcessVS; PixelShader = Up0; RenderTarget = DownTex0; } 558 | pass{ VertexShader = PostProcessVS; PixelShader = Up1; RenderTarget = Continuity::ColorTexture; } 559 | 560 | pass { VertexShader = PostProcessVS; PixelShader = LuminBuffer; RenderTarget = LumTex0; } 561 | pass { VertexShader = PostProcessVS; PixelShader = GenNorBuffer; RenderTarget0 = NorTex0; RenderTarget1 = HoleMask; } 562 | pass { VertexShader = PostProcessVS; PixelShader = FillNorBuffer; RenderTarget0 = NorTex1; RenderTarget1 = DepDerivTex; } 563 | pass { VertexShader = PostProcessVS; PixelShader = SmoothNormals0; RenderTarget = NorTex0; } 564 | pass { VertexShader = PostProcessVS; PixelShader = SmoothNormals1; RenderTarget = NorTex1; } 565 | pass { VertexShader = PostProcessVS; PixelShader = HeightNor; RenderTarget0 = NormalTexture; RenderTarget1 = NorTex0; } 566 | 567 | pass { VertexShader = PostProcessVS; PixelShader = SaveSamD; RenderTarget = DepSamTexture; } 568 | 569 | 570 | //pass { VertexShader = PostProcessVS; PixelShader = CalcTHICC; RenderTarget = ThickTexture; } 571 | 572 | pass { VertexShader = PostProcessVS; PixelShader = SaveSamN; RenderTarget = NorSamTexture; } 573 | 574 | /*pass 575 | { 576 | VertexShader = PostProcessVS; 577 | PixelShader = CNNormal; 578 | }*/ 579 | } 580 | 581 | } 582 | #else 583 | int Dx9Warning < 584 | ui_type = "radio"; 585 | ui_text = "Oops, looks like you're using DX9\n" 586 | "if you would like to use Quark Shaders in DX9 games, please use a wrapper like DXVK or dgVoodoo2"; 587 | ui_label = " "; 588 | > = 0; 589 | 590 | technique Continuity < 591 | ui_label = "Quark: Continuity"; 592 | ui_tooltip = 593 | " Continuity - Made by Zenteon \n" 594 | "\n=================================================================================================" 595 | "\n" 596 | "\nContinuity is a prepass shader meant to provide information to other shaders like MSRT" 597 | "\n" 598 | "\n================================================================================================="; 599 | > 600 | { } 601 | #endif 602 | -------------------------------------------------------------------------------- /Shaders/Quark_Fast_GI.fx: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | /* 3 | Copyright © Daniel Oren-Ibarra - 2024 4 | All Rights Reserved. 5 | 6 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND 7 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 8 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 9 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 10 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 11 | TORT OR OTHERWISE,ARISING FROM, OUT OF OR IN CONNECTION WITH THE 12 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13 | 14 | 15 | ====================================================================== 16 | Quark: TurboGI - Authored by Daniel Oren-Ibarra "Zenteon" 17 | 18 | Discord: https://discord.gg/PpbcqJJs6h 19 | Patreon: https://patreon.com/Zenteon 20 | 21 | 22 | */ 23 | //======================================================================== 24 | 25 | #include "ReShade.fxh" 26 | #include "QuarkCommon.fxh" 27 | #define HDR 1.01,0,0 28 | 29 | uniform float INTENSITY < 30 | ui_min = 0.0; 31 | ui_max = 5.0; 32 | ui_type = "drag"; 33 | ui_label = "GI Intensity"; 34 | > = 2.5; 35 | 36 | uniform float AO_INTENSITY < 37 | ui_min = 0.0; 38 | ui_max = 1.0; 39 | ui_type = "drag"; 40 | ui_label = "AO Intensity"; 41 | > = 0.8; 42 | 43 | uniform float RAY_LENGTH < 44 | ui_min = 0.5; 45 | ui_max = 1.0; 46 | ui_type = "drag"; 47 | ui_label = "Ray Length"; 48 | > = 1.0; 49 | 50 | uniform float FADEOUT < 51 | ui_type = "drag"; 52 | ui_label = "Depth Fadeout"; 53 | ui_min = 0.0; 54 | ui_max = 1.0; 55 | > = 0.8; 56 | 57 | uniform int DEBUG < 58 | ui_type = "combo"; 59 | ui_items = "None\0GI\0"; 60 | > = 0; 61 | 62 | uniform bool MV_COMP < 63 | ui_label = "Motion Vector Compatibility"; 64 | ui_tooltip = "Enable if using motion vectors to reduce flickering"; 65 | > = 0; 66 | 67 | uniform int FRAME_COUNT < 68 | source = "framecount";>; 69 | 70 | //============================================================================ 71 | //Bullshit 72 | //============================================================================ 73 | 74 | texture texMotionVectors { DIVRES(1); Format = RG16F; }; 75 | sampler MVSam0 { Texture = texMotionVectors; }; 76 | 77 | namespace TurboGI3 { 78 | 79 | texture NormalTex { DIVRES(2); Format = RGBA8; MipLevels = 5; }; 80 | texture NorDivTex { DIVRES(6); Format = RGBA8; MipLevels = 5; }; 81 | texture DepDivTex { DIVRES(6); Format = R16; MipLevels = 5; }; 82 | texture LumDivTex { DIVRES(6); Format = RGBA16F; MipLevels = 5; }; 83 | 84 | sampler Normal { Texture = NormalTex; WRAPMODE(BORDER); }; 85 | sampler NorDiv { Texture = NorDivTex; WRAPMODE(BORDER); }; 86 | sampler DepDiv { Texture = DepDivTex; WRAPMODE(CLAMP); }; 87 | sampler LumDiv { Texture = LumDivTex; WRAPMODE(BORDER); }; 88 | 89 | texture GITex { DIVRES(3); Format = RGBA8; MipLevels = 2; }; 90 | sampler GISam { Texture = GITex; }; 91 | 92 | texture CurTex{ DIVRES(3); Format = RGBA8; MipLevels = 2; }; 93 | sampler CurSam { Texture = CurTex; }; 94 | 95 | texture PreGITex { DIVRES(3); Format = RGBA8; MipLevels = 2; }; 96 | sampler PreGISam { Texture = PreGITex; }; 97 | 98 | texture PreDepTex { DIVRES(3); Format = R16; }; 99 | sampler PreDep { Texture = PreDepTex; }; 100 | 101 | texture DenTex0 { DIVRES(3); Format = RGBA8; }; 102 | texture DenTex1 { DIVRES(2); Format = RGBA8; }; 103 | 104 | sampler DenSam0 { Texture = DenTex0; }; 105 | sampler DenSam1 { Texture = DenTex1; }; 106 | 107 | //============================================================================ 108 | //Functions 109 | //============================================================================ 110 | 111 | float IGN(float2 xy) 112 | { 113 | float3 conVr = float3(0.06711056, 0.00583715, 52.9829189); 114 | return frac( conVr.z * frac(dot(xy,conVr.xy)) ); 115 | } 116 | 117 | float4 hash42(float2 inp) 118 | { 119 | uint pg = uint(RES.x * inp.y + inp.x); 120 | uint state = pg * 747796405u + 2891336453u; 121 | uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; 122 | uint4 RGBA = 0xFFu & word >> uint4(0,8,16,24); 123 | return float4(RGBA) / float(0xFFu); 124 | } 125 | 126 | float4 psuedoB(float2 xy) 127 | { 128 | float4 noise = hash42(xy); 129 | float4 bl; 130 | for(int i; i < 9; i++) 131 | { 132 | float2 offset = float2(floor(float(i) / 3.0), i % 3) - 1.0; 133 | bl += hash42(xy + offset); 134 | } 135 | 136 | return noise - (bl / 9.0) + 0.5; 137 | } 138 | 139 | 140 | //============================================================================ 141 | //Passes 142 | //============================================================================ 143 | 144 | 145 | float4 GenNormals(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 146 | { 147 | float2 fp = 1.0 / RES; 148 | float3 pos = NorEyePos(xy); 149 | float3 dx = pos - NorEyePos(xy + float2(fp.x, 0.0)); 150 | float3 dy = pos - NorEyePos(xy + float2(0.0, fp.y)); 151 | 152 | 153 | return float4(0.5 + 0.5 * normalize(cross(dy, dx)), 1.0); 154 | } 155 | 156 | void FillSampleTex(in float4 vpos : SV_Position, in float2 xy : TexCoord, out float dep : SV_Target0, out float4 nor : SV_Target1, out float4 lum : SV_Target2) 157 | { 158 | dep = GetDepth(xy); 159 | float2 hp = 2.0 / RES; 160 | nor = tex2Dlod(Normal, float4( xy + float2(hp.x, hp.y), 0, 2) ); 161 | nor += tex2Dlod(Normal, float4( xy + float2(hp.x, -hp.y), 0, 2) ); 162 | nor += tex2Dlod(Normal, float4( xy + float2(-hp.x, hp.y), 0, 2) ); 163 | nor += tex2Dlod(Normal, float4( xy + float2(-hp.x, -hp.y), 0, 2) ); 164 | nor *= 0.25; 165 | nor.a = 0.0; 166 | 167 | float3 input = GetBackBuffer(xy); 168 | float inLum = GetLuminance(input); 169 | //float3 c = max(input / inLum, 0.0); 170 | //input = lerp(input, inLum, 0.5 * inLum*inLum*inLum*inLum); 171 | float3 GI = pow(input, 2.2) * IReinJ(tex2D(GISam, xy).rgb, HDR); 172 | lum = float4(IReinJ(input, HDR) + GI, 1.0); 173 | if(dep == 1.0) lum = float4(0.0.xxx, 1.0); 174 | } 175 | 176 | //============================================================================ 177 | //GI 178 | //============================================================================ 179 | #define FRAME_MOD (3.0 * (FRAME_COUNT % 32 + 1)) 180 | 181 | float remapSin(float x) 182 | { 183 | //approximate sin(acos(x)) very poorly 184 | return saturate(1.0-x*x) / (0.5 * (1.0-x*x) + 0.5); 185 | } 186 | 187 | 188 | float GTAOContrH(float a, float n) 189 | { 190 | float g = 0.25 * (-cos(2.0 * a - n) + cos(n) + 2.0 * a * sin(n) ); 191 | //float2 g = 0.5 * (1.0 - cos(a)); 192 | return any(isnan(g)) ? 1.0 : g.x; 193 | } 194 | 195 | 196 | float CalcDiffuseN(float3 pos0, float3 nor0, float3 pos1, float3 nor1, float backface) 197 | { 198 | float diff0 = saturate(dot(nor0, normalize(pos1 - pos0)) - 0.0); 199 | 200 | //Option for backface lighting, looks bad 201 | float diff1 = saturate(dot(nor1, normalize(pos0 - pos1))); 202 | return diff0 * pow(diff1, 1.0); 203 | } 204 | 205 | float CalcTransferN(float3 pos0, float3 nor0, float3 pos1, float3 nor1, float disDiv, float att, float backface) 206 | { 207 | float lumMult = length(pos1) / (1.0 + disDiv) + 1.0; lumMult *= lumMult; 208 | float dist = att + distance(pos0, pos1) / (1.0 + disDiv) + 1.0; dist = rcp(dist*dist); 209 | float lamb = CalcDiffuseN(pos0, nor0, pos1, nor1, backface); 210 | return max(lamb * lumMult * dist, 0.001); 211 | } 212 | 213 | #define STEPS 10 214 | 215 | float4 CalcGI(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 216 | { 217 | xy = 3.0 * floor(xy * RES * 0.33334) / RES; 218 | float3 surfN = 2f * tex2D(Normal, xy).xyz - 1f; 219 | const float lr = length(RES); 220 | 221 | float3 posV = NorEyePos(xy); 222 | float3 vieV = -normalize(posV); 223 | if(posV.z == FARPLANE) discard; 224 | 225 | #define RAYS 4 226 | float dir = (6.28 / RAYS) * IGN(vpos.yx + FRAME_MOD ); 227 | float3 acc; 228 | float aoAcc; 229 | 230 | float2 minA; 231 | 232 | float attm = 1.0 + 0.05 * posV.z;//1.0;// + sqrt(0.1 * posV.z); 233 | for(int ii; ii < RAYS; ii++) 234 | { 235 | dir += 6.28 / RAYS; 236 | float2 vec = float2(cos(dir), sin(dir)); 237 | 238 | float dirW = 1.0;//clamp(1.0 / (1.0 + dot(normalize(surfN.xy + off), off)), 0.1, 3.0); //Debias weight 239 | float jit = IGN((FRAME_MOD + vpos.xy) % RES) + 0.5; 240 | 241 | float nMul = ii > (RAYS / 2) ? -1 : 1; 242 | 243 | float3 slcN = normalize(cross(float3( nMul * vec, 0.0f), vieV)); 244 | float3 T = cross(vieV, slcN); 245 | 246 | float3 prjN = surfN - slcN * dot(surfN, slcN); 247 | float3 prjNN = normalize(prjN); 248 | float N = -sign(dot(prjN, T)) * acos( dot(normalize(prjN), vieV) ); 249 | //float sinN = sin(N); 250 | //float cosN = cos(N); 251 | 252 | 253 | 254 | //vec /= RES; 255 | float2 maxDot = float2(sin(N) * nMul, -1.0); 256 | float2 maxAtt; 257 | 258 | for(int i; i < STEPS; i++) 259 | { 260 | float lod = floor(5.0 / STEPS * i); 261 | 262 | const float nexp = 1.3; 263 | float ji = jit * i; 264 | float noff = pow(nexp, ji) / pow(nexp, STEPS); 265 | float nint = (pow(nexp, ji) - pow(nexp, ji - 1)) / pow(nexp, STEPS); 266 | 267 | 268 | float2 sampXY = xy + vec * 0.5 * RAY_LENGTH * noff; 269 | if( any( abs(sampXY - 0.5) > 0.5 ) ) break; 270 | 271 | 272 | float sampD = tex2Dlod(DepDiv, float4(sampXY, 0, lod)).x + 0.0002; 273 | float3 sampN = 2f * tex2Dlod(NorDiv, float4(sampXY, 0, lod)).xyz - 1f; 274 | float3 sampL = tex2Dlod(LumDiv, float4(sampXY, 0, lod)).rgb; 275 | 276 | float3 posR = GetEyePos(sampXY, sampD); 277 | float3 sV = normalize(posR - posV); 278 | //I got supremely lazy here 279 | //float cDot = dot(vieV, sV)); 280 | float vDot = dot(vieV, sV); 281 | 282 | float att = rcp(1.0 + 0.1 * dot(posR.z - posV.z, posR.z - posV.z) / attm); 283 | //cDot = 2.0 * (0.5 + 0.5 * cDot) * att - 1.0; 284 | //att *= !any(abs(sampXY - 0.5) > 0.5); 285 | float sh; 286 | [flatten] 287 | if(vDot > maxDot.x) { 288 | maxDot.x = lerp(maxDot.x, vDot, att * 1.0); 289 | } 290 | 291 | [flatten] 292 | if(vDot >= maxDot.y) { 293 | maxDot.y = lerp(maxDot.y, vDot, 0.4 + 0.5 * att); 294 | sh = abs(vDot - maxDot.x); 295 | } 296 | 297 | float trns = distance(xy, sampXY) * max(CalcTransferN(posV, prjNN, posR, sampN, 1.0, 0.001, 0.0), 0.0); 298 | trns *= nint; 299 | trns *= dot(sV, surfN) > 0.03; 300 | acc += dirW * sh * sampL * trns; 301 | } 302 | 303 | maxDot.x = acos(maxDot.x); 304 | maxDot.x *= -nMul.x; 305 | 306 | aoAcc += GTAOContrH(maxDot.x, N) * length(prjN); 307 | 308 | } 309 | return float4(ReinJ(lr * acc / (STEPS * RAYS), HDR), 2.0 * aoAcc / RAYS); 310 | 311 | } 312 | 313 | //============================================================================ 314 | //Denoise 315 | //============================================================================ 316 | 317 | float4 Denoise0(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 318 | { 319 | xy = 2.0 * floor(0.5 * RES * xy) / RES; 320 | float surfD = GetDepth(xy); 321 | if(surfD == 1.0) discard; 322 | float3 surfN = 2f * tex2D(Normal, xy).xyz - 1f; 323 | float adpThrsh = 0.2 + saturate(dot(surfN, float3(0.0, 0.0, -1.0)));//Adaptive depth threshold 324 | xy = 3.0 * floor(xy * RES * 0.33334) / RES; 325 | 326 | float4 acc = tex2D(CurSam, xy); 327 | float pAO = acc.a; 328 | float accW = 1.0; 329 | 330 | for(int i = -2; i <= 2; i++) for(int ii = -2; ii <= 2; ii++) 331 | { 332 | float2 offset = 6.0 * float2(i, ii) / RES; 333 | 334 | float4 sampC = tex2Dlod(CurSam, float4(xy + offset, 0, 0)); 335 | float sampD = tex2D(DepDiv, xy + offset).x; 336 | 337 | 338 | float wN = 1.0;//pow(saturate(dot(surfN, sampN)), 1.0); 339 | float wD = exp(-abs(surfD - sampD) * (100.0 / surfD) * adpThrsh); 340 | acc += wD * wN * sampC; 341 | accW += wD * wN; 342 | } 343 | return acc / accW; 344 | 345 | } 346 | 347 | float4 Denoise1(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 348 | { 349 | xy = 2.0 * floor(0.5 * RES * xy) / RES; 350 | float surfD = GetDepth(xy); 351 | if(surfD == 1.0) discard; 352 | float3 surfN = 2f * tex2D(Normal, xy).xyz - 1f; 353 | float adpThrsh = 0.2 + saturate(dot(surfN, float3(0.0, 0.0, -1.0)));//Adaptive depth threshold 354 | 355 | 356 | float4 acc = tex2D(DenSam0, xy); 357 | float accW = 1.0; 358 | 359 | for(int i = -1; i <= 1; i++) for(int ii = -1; ii <= 1; ii++) 360 | { 361 | float2 offset = 3.0 * float2(i, ii) / RES; 362 | 363 | float4 sampC = tex2Dlod(DenSam0, float4(xy + offset, 0, 0)); 364 | float sampD = tex2D(DepDiv, xy + offset).x; 365 | //float3 sampN = 2f * tex2D(NorDiv, xy + offset).xyz - 1f; 366 | float wN = 1.0;//pow(saturate(dot(surfN, sampN)), 1.0); 367 | float wD = exp(-abs(surfD - sampD) * (300.0 / surfD) * adpThrsh); 368 | acc += wD * wN * sampC; 369 | accW += wD * wN; 370 | } 371 | return acc / accW; 372 | } 373 | 374 | float4 CurFrm(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 375 | { 376 | float2 MV = tex2D(MVSam0, xy).xy; 377 | float4 pre = tex2D(PreGISam, xy + MV); 378 | float4 cur = tex2D(GISam, xy); 379 | float CD = GetDepth(xy); 380 | float PD = tex2D(PreDep, xy + MV).r; 381 | 382 | float DEG = min(saturate(pow(abs(PD / CD), 20.0) + 0.0), saturate(pow(abs(CD / PD), 10.0) + 0.0)); 383 | 384 | return lerp(cur, pre, DEG * (0.8 + 0.1 * MV_COMP) ); 385 | } 386 | 387 | float4 CopyGI(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 388 | { 389 | return tex2D(CurSam, xy); 390 | } 391 | 392 | float CopyDepth(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 393 | { 394 | return tex2D(DepDiv, xy).r; 395 | } 396 | 397 | //============================================================================ 398 | //Blending 399 | //============================================================================ 400 | 401 | float CalcFog(float d, float den) 402 | { 403 | float2 se = float2(0.0, 0.001 + 0.999 * FADEOUT); 404 | se.y = max(se.y, se.x + 0.001); 405 | 406 | d = saturate(1.0 / (se.y) * d - se.x); 407 | 408 | float f = 1.0 - 1.0 / exp(pow(d * den, 2.0)); 409 | 410 | return saturate(f); 411 | } 412 | 413 | float3 Albedont(float2 xy) 414 | { 415 | float3 c = GetBackBuffer(xy + 0.5 / RES); 416 | float cl = dot(c, 0.3);//GetLuminance(c); 417 | float g = abs(ddx_fine(cl)) + abs(ddy_fine(cl)); 418 | c = 0.95 * c / (0.05 + cl); 419 | c*=c; 420 | 421 | 422 | //cl = cl / (cl + 1.0); 423 | //cl = sqrt(cl); 424 | return lerp(c*cl, cl, 0.0); 425 | 426 | //c = SRGBtoOKLAB(c); 427 | //c.x = sqrt(c.x); 428 | //c = OKLABtoSRGB(c); 429 | //return pow(c, 2.2); 430 | } 431 | 432 | float3 SRGBtoOKLAB(float3 c) 433 | { 434 | float l = 0.4122214708f * c.r + 0.5363325363f * c.g + 0.0514459929f * c.b; 435 | float m = 0.2119034982f * c.r + 0.6806995451f * c.g + 0.1073969566f * c.b; 436 | float s = 0.0883024619f * c.r + 0.2817188376f * c.g + 0.6299787005f * c.b; 437 | 438 | float l_ = pow(l, 0.3334); 439 | float m_ = pow(m, 0.3334); 440 | float s_ = pow(s, 0.3334); 441 | 442 | return float3( 443 | 0.2104542553f*l_ + 0.7936177850f*m_ - 0.0040720468f*s_, 444 | 1.9779984951f*l_ - 2.4285922050f*m_ + 0.4505937099f*s_, 445 | 0.0259040371f*l_ + 0.7827717662f*m_ - 0.8086757660f*s_); 446 | } 447 | 448 | float3 OKLABtoSRGB(float3 c) 449 | { 450 | float l_ = c.x + 0.3963377774f * c.y + 0.2158037573f * c.z; 451 | float m_ = c.x - 0.1055613458f * c.y - 0.0638541728f * c.z; 452 | float s_ = c.x - 0.0894841775f * c.y - 1.2914855480f * c.z; 453 | 454 | float l = l_*l_*l_; 455 | float m = m_*m_*m_; 456 | float s = s_*s_*s_; 457 | 458 | return float3( 459 | 4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s, 460 | -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s, 461 | -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s); 462 | } 463 | 464 | /* 465 | float3 Albedont(float2 xy) 466 | { 467 | float3 c = GetBackBuffer(xy); 468 | c *= c; 469 | c = SRGBtoOKLAB(c); 470 | //c.x = sqrt(c.x); 471 | //c.x *= 2.0; 472 | c.x /= lerp(c.x, 1.0, 0.9); 473 | c = OKLABtoSRGB(c); 474 | return c; 475 | } 476 | */ 477 | float3 Blend(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 478 | { 479 | 480 | float3 input = tex2D(ReShade::BackBuffer, xy).rgb; 481 | float3 prein = input; 482 | 483 | //depth thing 484 | float depth = GetDepth(xy); 485 | if(depth == 1.0) return lerp(input, 0.5, DEBUG); 486 | float lerpVal = CalcFog(depth, 2.0); 487 | 488 | //AO 489 | float4 GI, tGI; // = tex2D(DenSam1, xy);// * pow(input, 2.2); 490 | float w, tW; 491 | float2 tpos; 492 | 493 | tpos = floor(0.5 * vpos.xy) + int2(0, 0); 494 | tGI = tex2Dfetch(DenSam1, tpos); 495 | tW = rcp(0.0001 + abs(GetDepth(2.0 * tpos / RES) - depth)); 496 | GI += tGI * tW; 497 | w += tW; 498 | 499 | tpos = floor(0.5 * vpos.xy) + int2(0, 1); 500 | tGI = tex2Dfetch(DenSam1, tpos); 501 | tW = rcp(0.0001 + abs(GetDepth(2.0 * tpos / RES) - depth)); 502 | GI += tGI * tW; 503 | w += tW; 504 | 505 | tpos = floor(0.5 * vpos.xy) + int2(1, 0); 506 | tGI = tex2Dfetch(DenSam1, tpos); 507 | tW = rcp(0.0001 + abs(GetDepth(2.0 * tpos / RES) - depth)); 508 | GI += tGI * tW; 509 | w += tW; 510 | 511 | tpos = floor(0.5 * vpos.xy) + int2(1, 1); 512 | tGI = tex2Dfetch(DenSam1, tpos); 513 | tW = rcp(0.0001 + abs(GetDepth(2.0 * tpos / RES) - depth)); 514 | GI += tGI * tW; 515 | w += tW; 516 | 517 | GI /= w; 518 | 519 | //GI = tex2D(DenSam1, xy); 520 | 521 | float AO = GI.a; 522 | AO = lerp(1.0, AO, 0.95 * AO_INTENSITY); 523 | GI.rgb = IReinJ(GI.rgb, HDR) * INTENSITY; 524 | 525 | //GI.rgb *= AO; 526 | 527 | //Debug out 528 | //GI = tex2Dfetch(GISam, vpos.xy); 529 | //AO = GI.a; 530 | if(DEBUG) return lerp(ReinJ(AO* 0.05 + AO * GI.rgb, HDR), 0.5, lerpVal); 531 | 532 | //Fake albedo 533 | //float inGray = prein.r + prein.g + prein.b; 534 | float3 albedo = Albedont(xy);//pow(2.0 * prein / (1.0 + inGray), 2.2); 535 | 536 | //GI blending 537 | 538 | GI.rgb *= albedo; 539 | input = IReinJ(input, HDR); 540 | 541 | 542 | //return pow(tex2D(GISam, xy).a, 1.0 / 2.2); 543 | return lerp(ReinJ(AO * input + GI.rgb, HDR), prein, lerpVal); 544 | 545 | } 546 | 547 | technique TurboGI3 < 548 | ui_label = "Quark: Turbo GI v0.3"; 549 | ui_tooltip = 550 | " Quark TurboGI - Made by Zenteon \n" 551 | "\n=================================================================================================" 552 | "\n" 553 | "\nTurbo GI is a free lightweight global illumination and AO shader with a rendering budget of" 554 | "\n1ms on a 3050 mobile" 555 | "\n" 556 | "\n================================================================================================="; 557 | > 558 | { 559 | pass { VertexShader = PostProcessVS; PixelShader = GenNormals; RenderTarget = NormalTex; } 560 | pass { VertexShader = PostProcessVS; PixelShader = FillSampleTex; RenderTarget0 = DepDivTex; RenderTarget1 = NorDivTex; RenderTarget2 = LumDivTex; } 561 | pass { VertexShader = PostProcessVS; PixelShader = CalcGI; RenderTarget = GITex; } 562 | 563 | pass { VertexShader = PostProcessVS; PixelShader = CurFrm; RenderTarget = CurTex; } 564 | 565 | pass { VertexShader = PostProcessVS; PixelShader = Denoise0; RenderTarget = DenTex0; } 566 | pass { VertexShader = PostProcessVS; PixelShader = Denoise1; RenderTarget = DenTex1; } 567 | 568 | 569 | pass { VertexShader = PostProcessVS; PixelShader = CopyGI; RenderTarget = PreGITex; } 570 | pass { VertexShader = PostProcessVS; PixelShader = CopyDepth; RenderTarget = PreDepTex; } 571 | 572 | pass { VertexShader = PostProcessVS; PixelShader = Blend; } 573 | } 574 | } 575 | -------------------------------------------------------------------------------- /Shaders/Quark_Film_Grain.fx: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | /* 3 | Copyright © Daniel Oren-Ibarra - 2024 4 | All Rights Reserved. 5 | 6 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND 7 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 8 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 9 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 10 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 11 | TORT OR OTHERWISE,ARISING FROM, OUT OF OR IN CONNECTION WITH THE 12 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13 | 14 | 15 | ====================================================================== 16 | Quark: Fractal Grain v0.1 - Authored by Daniel Oren-Ibarra "Zenteon" 17 | 18 | Discord: https://discord.gg/PpbcqJJs6h 19 | Patreon: https://patreon.com/Zenteon 20 | 21 | 22 | */ 23 | //======================================================================== 24 | 25 | #if(__RENDERER__ != 0x9000) 26 | 27 | #include "ReShade.fxh" 28 | #define CLAMPSAM AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP 29 | #define RES float2(BUFFER_WIDTH, BUFFER_HEIGHT) 30 | #define LP (1.0 + (pow(1.0 - INTENSITY, 4.0) * 256.0)) 31 | 32 | uniform int FRAME_COUNT < 33 | source = "framecount";>; 34 | 35 | #define FRAME_MOD ((!STATIC_GRN * FRAME_COUNT % 512) + (!STATIC_GRN * FRAME_COUNT % 512) + 1) 36 | 37 | 38 | uniform float INTENSITY < 39 | ui_type = "slider"; 40 | ui_min = 0.0; 41 | ui_max = 1.0; 42 | ui_label = "Intensity"; 43 | > = 0.6; 44 | 45 | uniform float GRAIN_SIZE < 46 | ui_type = "slider"; 47 | ui_min = 0.0; 48 | ui_max = 1.0; 49 | ui_label = "Grain Size\n\n"; 50 | > = 0.5; 51 | 52 | uniform float IMG_SAT < 53 | ui_type = "slider"; 54 | ui_min = 0.0; 55 | ui_max = 1.0; 56 | ui_label = "Saturation"; 57 | > = 1.0; 58 | 59 | uniform float GRAIN_SAT < 60 | ui_type = "slider"; 61 | ui_min = 0.0; 62 | ui_max = 1.0; 63 | ui_label = "Grain Saturation"; 64 | > = 0.3; 65 | 66 | uniform bool STATIC_GRN < 67 | ui_label = "Static Grain"; 68 | > = 1; 69 | 70 | namespace FFG { 71 | texture GrainTex { Width = RES.x; Height = RES.y; Format = RGBA8; }; 72 | sampler GrainSam { Texture = GrainTex; CLAMPSAM; }; 73 | 74 | 75 | 76 | //============================================================================= 77 | //Functions 78 | //============================================================================= 79 | 80 | float4 UpSample(sampler input, float2 xy, float div, float offset) 81 | { 82 | float2 hp = 0.65 / RES; 83 | float4 acc = 0.5 * tex2D(input, xy); 84 | 85 | acc += 0.1875 * tex2Dlod(input, float4(xy - hp * offset, 0, 0)); 86 | acc += 0.1875 * tex2Dlod(input, float4(xy + hp * offset, 0, 0)); 87 | acc += 0.1875 * tex2Dlod(input, float4(xy + float2(hp.x, -hp.y) * offset, 0, 0)); 88 | acc += 0.1875 * tex2Dlod(input, float4(xy - float2(hp.x, -hp.y) * offset, 0, 0)); 89 | 90 | acc += 0.0625 * tex2Dlod(input, float4(xy + hp * float2(2f, 0) * offset, 0, 0)); 91 | acc += 0.0625 * tex2Dlod(input, float4(xy + hp * float2(-2f, 0) * offset, 0, 0)); 92 | acc += 0.0625 * tex2Dlod(input, float4(xy + hp * float2(0, 2f) * offset, 0, 0)); 93 | acc += 0.0625 * tex2Dlod(input, float4(xy + hp * float2(0, -2f) * offset, 0, 0)); 94 | 95 | return acc / 1.5; 96 | } 97 | 98 | 99 | float4 hash42(float2 inp) 100 | { 101 | uint pg = asuint(RES.x * RES.x * inp.y + inp.x * RES.x); 102 | uint state = pg * 747796405u + 2891336453u; 103 | uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; 104 | uint4 RGBA = 0xFFu & word >> uint4(0,8,16,24); 105 | return float4(RGBA) / 0xFFu; 106 | } 107 | 108 | float4 lhash42(uint pg) 109 | { 110 | uint state = pg * 747796405u + 2891336453u; 111 | uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; 112 | uint4 RGBA = 0xFFu & word >> uint4(0,8,16,24); 113 | return float4(RGBA) / 0xFFu; 114 | } 115 | 116 | //============================================================================= 117 | //Passes 118 | //============================================================================= 119 | 120 | float4 GenGrain(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 121 | { 122 | float3 input = tex2D(ReShade::BackBuffer, texcoord).rgb; 123 | input = lerp(input.r * 0.2126 + input.g * 0.7152 + input.b * 0.0722, input, IMG_SAT); 124 | 125 | uint pg = uint(RES.x * RES.x * texcoord.y + texcoord.x * RES.x); 126 | float4 noise = lhash42((FRAME_MOD) * pg); 127 | noise.rgb = lerp(noise.a, noise.rgb, min(GRAIN_SAT, IMG_SAT)); 128 | 129 | #define QuantBias ((pow(input, 1.3)) - 1f) 130 | input = floor(LP * (input + ((2.0 * noise.rgb + QuantBias) / LP))) / LP - ((noise.rgb - 0.5) / LP); 131 | input -= 0.15 * pow(INTENSITY, 4.0) * QuantBias; 132 | return float4(saturate(input), noise.a); 133 | } 134 | 135 | float3 QUARK_FILMGRAIN(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 136 | { 137 | float2 offset = GRAIN_SIZE * hash42(FRAME_MOD * texcoord + 0.5).zw / RES; 138 | float3 grain = UpSample(GrainSam, offset + texcoord, 1.0, 0.5 * GRAIN_SIZE).rgb; 139 | return grain; 140 | } 141 | 142 | technique Crystallis < 143 | ui_label = "Quark: Crystallis"; 144 | ui_tooltip = 145 | " Crystallis - Made by Zenteon \n" 146 | "\n=================================================================================================" 147 | "\n" 148 | "\nCrystallis is a unique approach to filmgrain" 149 | "\nbuilt around using quantization to simulate subpixel binaries" 150 | "\n" 151 | "\n================================================================================================="; 152 | > 153 | { 154 | pass 155 | { 156 | VertexShader = PostProcessVS; 157 | PixelShader = GenGrain; 158 | RenderTarget = GrainTex; 159 | } 160 | pass 161 | { 162 | VertexShader = PostProcessVS; 163 | PixelShader = QUARK_FILMGRAIN; 164 | } 165 | } 166 | } 167 | 168 | #else 169 | int Dx9Warning < 170 | ui_type = "radio"; 171 | ui_text = "Oops, looks like you're using DX9\n" 172 | "if you would like to use Quark Shaders in DX9 games, please use a wrapper like DXVK or dgVoodoo2"; 173 | ui_label = " "; 174 | > = 0; 175 | 176 | technique Crystallis < 177 | ui_label = "Quark: Crystallis"; 178 | ui_tooltip = 179 | " Crystallis - Made by Zenteon \n" 180 | "\n=================================================================================================" 181 | "\n" 182 | "\nCrystallis is a unique approach to filmgrain" 183 | "\nbuilt around using quantization to simulate subpixel binaries" 184 | "\n" 185 | "\n================================================================================================="; 186 | > 187 | {} 188 | #endif 189 | 190 | -------------------------------------------------------------------------------- /Shaders/Quark_Local_Contrast.fx: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | /* 3 | Copyright © Daniel Oren-Ibarra - 2024 4 | All Rights Reserved. 5 | 6 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND 7 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 8 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 9 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 10 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 11 | TORT OR OTHERWISE,ARISING FROM, OUT OF OR IN CONNECTION WITH THE 12 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13 | 14 | 15 | ====================================================================== 16 | Quark: Local Contrast v0.2 - Authored by Daniel Oren-Ibarra "Zenteon" 17 | 18 | Discord: https://discord.gg/PpbcqJJs6h 19 | Patreon: https://patreon.com/Zenteon 20 | 21 | 22 | */ 23 | //======================================================================== 24 | 25 | #include "ReShade.fxh" 26 | 27 | #define RES float2(BUFFER_WIDTH, BUFFER_HEIGHT) 28 | #define FARPLANE RESHADE_DEPTH_LINEARIZATION_FAR_PLANE 29 | #define ASPECT_RATIO (RES.x/RES.y) 30 | 31 | #define DIVRES(DIVRES_RIV) Width = BUFFER_WIDTH / DIVRES_RIV; Height = BUFFER_HEIGHT / DIVRES_RIV 32 | 33 | 34 | 35 | #if(__RENDERER__ != 0x9000) 36 | 37 | 38 | uniform int MODE < 39 | ui_type = "combo"; 40 | ui_items = "Laplacian\0Unsharp\0Obscurance\0ZN LC\0Quark LC\0"; 41 | ui_label = "Enhancement Mode"; 42 | ui_tooltip = "Contrast enhancement method used."; 43 | > = 4; 44 | 45 | uniform float KERNEL_SHAPE < 46 | ui_type = "drag"; 47 | ui_min = 0.0; 48 | ui_max = 1.0; 49 | ui_label = "Detail Precision"; 50 | ui_tooltip = "Lower values effect larger sections of the image, higher values affect more details and have less clipping"; 51 | > = 0.7; 52 | 53 | uniform float INTENSITY < 54 | ui_type = "drag"; 55 | ui_min = -1.0; 56 | ui_max = 1.0; 57 | ui_label = "Intensity"; 58 | > = 0.5; 59 | 60 | uniform float GLOBALBRIGHT < 61 | ui_type = "drag"; 62 | ui_min = 0.0; 63 | ui_max = 1.0; 64 | ui_label = "Highlight Detail"; 65 | ui_tooltip = "Enhances detail in brighter regions"; 66 | > = 0.0; 67 | 68 | uniform int DEBUG < 69 | ui_type = "combo"; 70 | ui_items = "None\0Image Difference\0Mask Difference\0"; 71 | ui_label = "Debug"; 72 | > = 0; 73 | #define DMULT 0.5 74 | namespace QLC0 { 75 | texture BlurTex0 { DIVRES(1 * DMULT); Format = R16; }; 76 | texture BlurTex1 { DIVRES(1 * DMULT); Format = R16; }; 77 | 78 | texture DownTex0 { DIVRES(2 * DMULT); Format = R16; }; 79 | texture DownTex1 { DIVRES(4 * DMULT); Format = R16; }; 80 | texture DownTex2 { DIVRES(8 * DMULT); Format = R16; }; 81 | texture DownTex3 { DIVRES(16 * DMULT); Format = R16; }; 82 | texture DownTex4 { DIVRES(32 * DMULT); Format = R16; }; 83 | texture DownTex5 { DIVRES(64 * DMULT); Format = R16; }; 84 | texture DownTex6 { DIVRES(128 * DMULT); Format = R16; }; 85 | 86 | texture UpTex5 { DIVRES(64 * DMULT); Format = R16; }; 87 | texture UpTex4 { DIVRES(32 * DMULT); Format = R16; }; 88 | texture UpTex3 { DIVRES(16 * DMULT); Format = R16; }; 89 | texture UpTex2 { DIVRES(8 * DMULT); Format = R16; }; 90 | texture UpTex1 { DIVRES(4 * DMULT); Format = R16; }; 91 | texture UpTex0 { DIVRES(2 * DMULT); Format = R16; }; 92 | 93 | sampler BlurSam0 { Texture = BlurTex0; }; 94 | sampler BlurSam1 { Texture = BlurTex1; }; 95 | 96 | sampler DownSam0 { Texture = DownTex0; }; 97 | sampler DownSam1 { Texture = DownTex1; }; 98 | sampler DownSam2 { Texture = DownTex2; }; 99 | sampler DownSam3 { Texture = DownTex3; }; 100 | sampler DownSam4 { Texture = DownTex4; }; 101 | sampler DownSam5 { Texture = DownTex5; }; 102 | sampler DownSam6 { Texture = DownTex6; }; 103 | 104 | sampler UpSam5 { Texture = UpTex5; }; 105 | sampler UpSam4 { Texture = UpTex4; }; 106 | sampler UpSam3 { Texture = UpTex3; }; 107 | sampler UpSam2 { Texture = UpTex2; }; 108 | sampler UpSam1 { Texture = UpTex1; }; 109 | sampler UpSam0 { Texture = UpTex0; }; 110 | 111 | //============================================================================= 112 | //Tonemappers 113 | //============================================================================= 114 | #define HDR_RED 1.05 115 | float3 Reinhardt(float3 x) 116 | { 117 | return HDR_RED * x / (x + 1.0); 118 | } 119 | 120 | float3 IReinhardt(float3 x) 121 | { 122 | return -x / (x - HDR_RED); 123 | } 124 | 125 | //============================================================================= 126 | //Functions 127 | //============================================================================= 128 | #define OFF 1.0 129 | float DownSample(sampler input, float2 xy, float div)//0.375 + 0.25 130 | { 131 | float2 hp = div * 0.5 / RES; 132 | float offset = OFF; 133 | 134 | float acc = 0.125 * tex2D(input, xy).r; 135 | acc += 0.125 * tex2D(input, xy - hp * offset).r; 136 | acc += 0.125 * tex2D(input, xy + hp * offset).r; 137 | acc += 0.125 * tex2D(input, xy + float2(-hp.x, hp.y) * offset).r; 138 | acc += 0.125 * tex2D(input, xy + float2(hp.x, -hp.y) * offset).r; 139 | 140 | acc += 0.0625 * tex2D(input, xy - float2(2f * hp.x, 0) * offset).r; 141 | acc += 0.0625 * tex2D(input, xy + float2(0, 2f * hp.y) * offset).r; 142 | acc += 0.0625 * tex2D(input, xy + float2(2f * -hp.x,0) * offset).r; 143 | acc += 0.0625 * tex2D(input, xy - float2(0, 2f*-hp.y) * offset).r; 144 | 145 | acc += 0.03125 * tex2D(input, xy - hp * 2f * offset).r; 146 | acc += 0.03125 * tex2D(input, xy + hp * 2f * offset).r; 147 | acc += 0.03125 * tex2D(input, xy + float2(hp.x, -hp.y) * 2f * offset).r; 148 | acc += 0.03125 * tex2D(input, xy - float2(hp.x, -hp.y) * 2f * offset).r; 149 | 150 | return acc; 151 | 152 | } 153 | 154 | float UpSample(sampler input, float2 xy, float div) 155 | { 156 | float offset = OFF; 157 | float2 hp = div * 0.5 / RES; 158 | float acc = 0.5 * tex2D(input, xy).r; 159 | 160 | acc += 0.1875 * tex2D(input, xy - hp * offset).r; 161 | acc += 0.1875 * tex2D(input, xy + hp * offset).r; 162 | acc += 0.1875 * tex2D(input, xy + float2(hp.x, -hp.y) * offset).r; 163 | acc += 0.1875 * tex2D(input, xy - float2(hp.x, -hp.y) * offset).r; 164 | 165 | 166 | return acc / 1.25; 167 | } 168 | 169 | float GetLum(float3 x) 170 | { 171 | if(MODE == 0) return dot(x, float3(0.2126, 0.7152, 0.0722)); 172 | if(MODE == 2) return (x.r + x.g + x.b) / 3.0; 173 | if(MODE == 1) return dot(x, float3(0.2126, 0.7152, 0.0722)); 174 | if(MODE == 3) return dot(x, float3(0.2126, 0.7152, 0.0722)); 175 | if(MODE == 4) return dot(x, float3(0.2126, 0.7152, 0.0722)); 176 | return 0.0; 177 | } 178 | 179 | //============================================================================= 180 | //Down Passes 181 | //============================================================================= 182 | float Lum(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 183 | { 184 | float3 col = tex2D(ReShade::BackBuffer, xy).rgb; 185 | col = GetLum(col); 186 | return col.r; 187 | } 188 | 189 | 190 | float Down0(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 191 | { 192 | return DownSample(BlurSam0, xy, 2.0); 193 | } 194 | 195 | float Down1(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 196 | { 197 | return DownSample(DownSam0, xy, 4.0); 198 | } 199 | 200 | float Down2(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 201 | { 202 | return DownSample(DownSam1, xy, 8.0); 203 | } 204 | 205 | float Down3(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 206 | { 207 | return DownSample(DownSam2, xy, 16.0); 208 | } 209 | 210 | float Down4(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 211 | { 212 | return DownSample(DownSam3, xy, 32.0); 213 | } 214 | 215 | float Down5(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 216 | { 217 | return DownSample(DownSam4, xy, 64.0); 218 | } 219 | 220 | float Down6(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 221 | { 222 | return DownSample(DownSam5, xy, 128.0); 223 | } 224 | 225 | //============================================================================= 226 | //Up Passes 227 | //============================================================================= 228 | 229 | #define KS sqrt(1.0 - KERNEL_SHAPE) 230 | 231 | float Up5(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 232 | { 233 | return lerp(tex2D(DownSam5, xy).r, UpSample(DownSam6, xy, 64.0), 0.3 + 0.7 * KS); 234 | } 235 | 236 | float Up4(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 237 | { 238 | return lerp(tex2D(DownSam4, xy).r, UpSample(UpSam5, xy, 32.0), 0.4 + 0.6 * KS); 239 | } 240 | 241 | float Up3(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 242 | { 243 | return lerp(tex2D(DownSam3, xy).r, UpSample(UpSam4, xy, 16.0), 0.5 + 0.5 * KS); 244 | } 245 | 246 | float Up2(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 247 | { 248 | return lerp(tex2D(DownSam2, xy).r, UpSample(UpSam3, xy, 8.0), 0.6 + 0.4 * KS); 249 | } 250 | 251 | float Up1(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 252 | { 253 | return lerp(tex2D(DownSam1, xy).r, UpSample(UpSam2, xy, 4.0), 0.7 + 0.3 * KS); 254 | } 255 | 256 | float Up0(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 257 | { 258 | return lerp(tex2D(DownSam0, xy).r, UpSample(UpSam1, xy, 2.0), 0.8 + 0.2 * KS); 259 | } 260 | 261 | float Up00(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 262 | { 263 | return lerp(tex2D(BlurSam0, xy).r, UpSample(UpSam0, xy, 2.0), 0.9 + 0.1 * KS); 264 | } 265 | 266 | //============================================================================= 267 | //Blend Passes 268 | //============================================================================= 269 | 270 | 271 | float3 QuarkLC(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 272 | { 273 | float3 input = tex2D(ReShade::BackBuffer, xy).rgb; 274 | float lum = GetLum(input); 275 | float blum = UpSample(BlurSam0, xy, 2.0); 276 | 277 | input = IReinhardt(input); 278 | float blur = tex2D(BlurSam1, xy).r; 279 | float3 tempI = Reinhardt(input); 280 | 281 | float tempINT = INTENSITY; 282 | if(DEBUG) tempINT = 1.0; 283 | 284 | if(MODE == 0) input -= 3.0 * tempINT * input * (sqrt(blur) - sqrt(0.5 * lum + 0.5 * blum)); 285 | if(MODE == 2) input *= lerp(1.0, (1.5 + pow(1.0 - KERNEL_SHAPE, 2.0)) * blur, 0.9 * tempINT); 286 | if(MODE == 3) input += pow(1.0 - blur, 0.5) * tempINT * (input - blur); 287 | 288 | 289 | 290 | //My fancy method 291 | if(MODE == 4) 292 | { 293 | float3 detail = blur * (0.5 - pow(abs(blur - lum), 0.5) * sign(blur - lum)); 294 | input = Reinhardt(input); 295 | float3 detail2 = input * (detail / blur); 296 | 297 | 298 | float3 screen = 1.0 - (1.0 - input) * (blur); 299 | detail = lerp(detail2, screen, input); 300 | input = lerp(input, detail, clamp(0.8 * tempINT, -0.8, 0.8)); 301 | } 302 | else 303 | { 304 | input = Reinhardt(input); 305 | } 306 | 307 | 308 | 309 | if(MODE == 1) input = lerp(input * (1.0 - tempINT * blur), 1.0 - lerp(1.0, blur, tempINT) * (1.0 - input), pow(tempI, 2.2)); 310 | 311 | 312 | 313 | input = pow(input, 1.0 + GLOBALBRIGHT * 0.5 * pow(lum, 2.0)); 314 | if(DEBUG == 1) input = sqrt(2.0 * abs(input - INTENSITY * tempI)); 315 | if(DEBUG == 2) input = sqrt(distance(INTENSITY * blur, input)); 316 | 317 | return saturate(input - 0.001); 318 | } 319 | 320 | technique Quark_LC < 321 | ui_label = "Quark: Local Contrast"; 322 | ui_tooltip = 323 | " Quark LC - Made by Zenteon \n" 324 | "\n=================================================================================================" 325 | "\n" 326 | "\nQuark LC is an all in one local contrast enhancement shader" 327 | "\nIt features methods to enhance small scale details, highlights, and image graduation" 328 | "\n" 329 | "\n================================================================================================="; 330 | > 331 | { 332 | pass { VertexShader = PostProcessVS; PixelShader = Lum; RenderTarget0 = BlurTex0;} 333 | pass { VertexShader = PostProcessVS; PixelShader = Down0; RenderTarget = DownTex0; } 334 | pass { VertexShader = PostProcessVS; PixelShader = Down1; RenderTarget = DownTex1; } 335 | pass { VertexShader = PostProcessVS; PixelShader = Down2; RenderTarget = DownTex2; } 336 | pass { VertexShader = PostProcessVS; PixelShader = Down3; RenderTarget = DownTex3; } 337 | pass { VertexShader = PostProcessVS; PixelShader = Down4; RenderTarget = DownTex4; } 338 | pass { VertexShader = PostProcessVS; PixelShader = Down5; RenderTarget = DownTex5; } 339 | pass { VertexShader = PostProcessVS; PixelShader = Down6; RenderTarget = DownTex6; } 340 | 341 | pass { VertexShader = PostProcessVS; PixelShader = Up5; RenderTarget = UpTex5;} 342 | pass { VertexShader = PostProcessVS; PixelShader = Up4; RenderTarget = UpTex4;} 343 | pass { VertexShader = PostProcessVS; PixelShader = Up3; RenderTarget = UpTex3;} 344 | pass { VertexShader = PostProcessVS; PixelShader = Up2; RenderTarget = UpTex2;} 345 | pass { VertexShader = PostProcessVS; PixelShader = Up1; RenderTarget = UpTex1;} 346 | pass { VertexShader = PostProcessVS; PixelShader = Up0; RenderTarget = UpTex0; } 347 | pass { VertexShader = PostProcessVS; PixelShader = Up00; RenderTarget = BlurTex1; } 348 | 349 | pass 350 | { 351 | VertexShader = PostProcessVS; 352 | PixelShader = QuarkLC; 353 | } 354 | } 355 | } 356 | #else 357 | int Dx9Warning < 358 | ui_type = "radio"; 359 | ui_text = "Oops, looks like you're using DX9\n" 360 | "if you would like to use Quark Shaders in DX9 games, please use a wrapper like DXVK or dgVoodoo2"; 361 | ui_label = " "; 362 | > = 0; 363 | 364 | technique Quark_LC < 365 | ui_label = "Quark: Local Contrast"; 366 | ui_tooltip = 367 | " Quark LC - Made by Zenteon \n" 368 | "\n=================================================================================================" 369 | "\n" 370 | "\nQuark LC is an all in one local contrast enhancement shader" 371 | "\nIt features methods to enhance small scale details, highlights, and image graduation" 372 | "\n" 373 | "\n================================================================================================="; 374 | > 375 | { } 376 | #endif 377 | -------------------------------------------------------------------------------- /Shaders/Quark_Motion.fx: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | /* 3 | Copyright © Daniel Oren-Ibarra - 2025 4 | All Rights Reserved. 5 | 6 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND 7 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 8 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 9 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 10 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 11 | TORT OR OTHERWISE,ARISING FROM, OUT OF OR IN CONNECTION WITH THE 12 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13 | 14 | 15 | ====================================================================== 16 | Quark: Motion - Authored by Daniel Oren-Ibarra "Zenteon" 17 | 18 | Discord: https://discord.gg/PpbcqJJs6h 19 | Patreon: https://patreon.com/Zenteon 20 | 21 | 22 | */ 23 | //======================================================================== 24 | 25 | //Not sure what else to call this, half res vectors, half pixel precision 26 | #ifndef SUBPIXEL_FLOW 27 | //============================================================================================ 28 | #define SUBPIXEL_FLOW 0 29 | //============================================================================================ 30 | #endif 31 | 32 | #include "ReShade.fxh" 33 | #include "QuarkCommon.fxh" 34 | 35 | uniform bool DEBUG < 36 | ui_label = "Debug Flow"; 37 | > = 0; 38 | 39 | 40 | /* 41 | 16 taps 42 | 6 43 | 5 44 | 4 45 | 3 o o o o 46 | 2 o o o o 47 | 1 o o o o 48 | 0 o o o o 49 | -1 50 | -2 51 | 52 | -2-1 0 1 2 3 4 5 6 53 | 54 | Big thanks to Marty for the idea 55 | Lower noise, low cost increase, plays better with temporal stablization 56 | 20 taps 57 | 6 58 | 5 o o 59 | 4 o o 60 | 3 o o 61 | 2 o o o o 62 | 1 o o o o 63 | 0 o o 64 | -1 o o 65 | -2 o o 66 | 67 | -2-1 0 1 2 3 4 5 6 68 | 69 | */ 70 | 71 | static const int2 off16[16] = { 72 | int2(0,0), int2(1,0), int2(2,0), int2(3,0), 73 | int2(0,1), int2(1,1), int2(2,1), int2(3,1), 74 | int2(0,2), int2(1,2), int2(2,2), int2(3,2), 75 | int2(0,3), int2(1,3), int2(2,3), int2(3,3) 76 | }; 77 | 78 | static const int2 off20[20] = { 79 | int2(1,5), int2(2,5), 80 | int2(-1,4), int2(4,4), 81 | int2(0,3), int2(3,3), 82 | int2(-2,2), int2(1,2), int2(2,2), int2(5,2), 83 | int2(-2,1), int2(1,1), int2(2,1), int2(5,1), 84 | int2(0,0), int2(3,0), 85 | int2(-1,-1), int2(4,-1), 86 | int2(1,-2), int2(2,-2), 87 | 88 | }; 89 | #define BLOCK_POS_CT 20 90 | #define UBLOCK off20 91 | #define TEMPORAL 1 92 | 93 | #define PS_INPUTS float4 vpos : SV_Position, float2 xy : TEXCOORD0 94 | 95 | //Pass helpers 96 | 97 | #define PASS0(iPS) VertexShader = PostProcessVS; PixelShader = iPS 98 | #define PASS1(iPS, oRT) VertexShader = PostProcessVS; PixelShader = iPS; RenderTarget = oRT 99 | #define PASS2(iPS, oRT0, oRT1) VertexShader = PostProcessVS; PixelShader = iPS; RenderTarget0 = oRT0; RenderTarget1 = oRT1 100 | #define PASS3(iPS, oRT0, oRT1, oRT2) VertexShader = PostProcessVS; PixelShader = iPS; RenderTarget0 = oRT0; RenderTarget1 = oRT1; RenderTarget2 = oRT2 101 | 102 | texture texMotionVectors { DIVRES(1); Format = RG16F; }; 103 | sampler sMV { Texture = texMotionVectors; }; 104 | namespace QuarkMotion { 105 | 106 | #define FWRAP CLAMP 107 | #define LFORM RG16F 108 | #define LFILT POINT 109 | #define DIV_LEV (2 - SUBPIXEL_FLOW) 110 | //#define BLOCK_SIZE 4 111 | 112 | #define BLOCKS_SIZE 2 113 | 114 | //optical flow 115 | texture2D tLevel0 { DIVRES((2 * DIV_LEV)); Format = RGBA16F; MipLevels = 6; }; 116 | sampler2D sLevel0 { Texture = tLevel0; MagFilter = POINT; MinFilter = LINEAR; MipFilter = LINEAR; }; 117 | /* 118 | texture2D tTemp0 { DIVRES((1 * DIV_LEV)); Format = RGBA16F; }; 119 | sampler2D sTemp0 { Texture = tTemp0; FILTER(POINT); }; 120 | texture2D tTemp1 { DIVRES((1 * DIV_LEV)); Format = RGBA16F; }; 121 | sampler2D sTemp1 { Texture = tTemp1; FILTER(POINT); }; 122 | */ 123 | texture2D tLevel1 { DIVRES((4 * DIV_LEV)); Format = LFORM; }; 124 | sampler2D sLevel1 { Texture = tLevel1; FILTER(LFILT); WRAPMODE(FWRAP); }; 125 | texture2D tLevel2 { DIVRES((8 * DIV_LEV)); Format = LFORM; }; 126 | sampler2D sLevel2 { Texture = tLevel2; FILTER(LFILT); WRAPMODE(FWRAP); }; 127 | texture2D tLevel3 { DIVRES((16 * DIV_LEV)); Format = LFORM; }; 128 | sampler2D sLevel3 { Texture = tLevel3; FILTER(LFILT); WRAPMODE(FWRAP); }; 129 | texture2D tLevel4 { DIVRES((32 * DIV_LEV)); Format = LFORM; }; 130 | sampler2D sLevel4 { Texture = tLevel4; FILTER(LFILT); WRAPMODE(FWRAP); }; 131 | texture2D tLevel5 { DIVRES((64 * DIV_LEV)); Format = LFORM; }; 132 | sampler2D sLevel5 { Texture = tLevel5; FILTER(LFILT); WRAPMODE(FWRAP); }; 133 | 134 | //current 135 | texture2D tCG0 { DIVRES((0.5 * DIV_LEV)); Format = R16; }; 136 | sampler2D sCG0 { Texture = tCG0; WRAPMODE(FWRAP); }; 137 | texture2D tCG1 { DIVRES((1 * DIV_LEV)); Format = R16; }; 138 | sampler2D sCG1 { Texture = tCG1; WRAPMODE(FWRAP); }; 139 | texture2D tCG2 { DIVRES((2 * DIV_LEV)); Format = R16; }; 140 | sampler2D sCG2 { Texture = tCG2; WRAPMODE(FWRAP); }; 141 | texture2D tCG3 { DIVRES((4 * DIV_LEV)); Format = R16; }; 142 | sampler2D sCG3 { Texture = tCG3; WRAPMODE(FWRAP); }; 143 | texture2D tCG4 { DIVRES((8 * DIV_LEV)); Format = R16; }; 144 | sampler2D sCG4 { Texture = tCG4; WRAPMODE(FWRAP); }; 145 | texture2D tCG5 { DIVRES((16 * DIV_LEV)); Format = R16; }; 146 | sampler2D sCG5 { Texture = tCG5; WRAPMODE(FWRAP); }; 147 | //previous 148 | texture2D tPG0 { DIVRES((0.5 * DIV_LEV)); Format = R16; }; 149 | sampler2D sPG0 { Texture = tPG0; WRAPMODE(FWRAP); }; 150 | texture2D tPG1 { DIVRES((1 * DIV_LEV)); Format = R16; }; 151 | sampler2D sPG1 { Texture = tPG1; WRAPMODE(FWRAP); }; 152 | texture2D tPG2 { DIVRES((2 * DIV_LEV)); Format = R16; }; 153 | sampler2D sPG2 { Texture = tPG2; WRAPMODE(FWRAP); }; 154 | texture2D tPG3 { DIVRES((4 * DIV_LEV)); Format = R16; }; 155 | sampler2D sPG3 { Texture = tPG3; WRAPMODE(FWRAP); }; 156 | texture2D tPG4 { DIVRES((8 * DIV_LEV)); Format = R16; }; 157 | sampler2D sPG4 { Texture = tPG4; WRAPMODE(FWRAP); }; 158 | texture2D tPG5 { DIVRES((16 * DIV_LEV)); Format = R16; }; 159 | sampler2D sPG5 { Texture = tPG5; WRAPMODE(FWRAP); }; 160 | 161 | //======================================================================================= 162 | //Functions 163 | //======================================================================================= 164 | 165 | float IGN(float2 xy) 166 | { 167 | float3 conVr = float3(0.06711056, 0.00583715, 52.9829189); 168 | return frac( conVr.z * frac(dot(xy % RES,conVr.xy)) ); 169 | } 170 | 171 | 172 | //======================================================================================= 173 | //Optical Flow Functions 174 | //======================================================================================= 175 | 176 | float4 tex2DfetchLin(sampler2D tex, float2 vpos) 177 | { 178 | //return tex2Dfetch(tex, vpos); 179 | float2 s = tex2Dsize(tex); 180 | return tex2Dlod(tex, float4(vpos / s, 0, 0)); 181 | } 182 | 183 | float3 tex2DfetchLinD(sampler2D tex, float2 vpos) 184 | { 185 | float2 s = tex2Dsize(tex); 186 | float2 t = tex2Dlod(tex, float4(vpos / s, 0, 0)).xy; 187 | float d = GetDepth(vpos / s); 188 | return float3(t,d); 189 | } 190 | 191 | float GetBlock(sampler2D tex, float2 vpos, float2 offset, float div, inout float Block[BLOCK_POS_CT] ) 192 | { 193 | vpos = (vpos) * div; 194 | float acc; 195 | for(int i; i < BLOCK_POS_CT; i++) 196 | { 197 | int2 np = UBLOCK[i]; 198 | float tCol = tex2DfetchLin(tex, vpos + np + offset).r; 199 | Block[i] = tCol; 200 | acc += tCol; 201 | } 202 | return acc / (BLOCK_POS_CT); 203 | } 204 | 205 | void GetBlockS(sampler2D tex, float2 vpos, float2 offset, float div, inout float Block[9] ) 206 | { 207 | vpos = vpos; 208 | for(int i; i < 9; i++) 209 | { 210 | int2 np = int2(floor(float(i) / 3), i % 3) - 1; 211 | np = abs(np * np) + 1; 212 | float tCol = tex2DfetchLin(tex, vpos + np + offset).r; 213 | Block[i] = tCol; 214 | } 215 | } 216 | 217 | 218 | float BlockErr(float Block0[BLOCK_POS_CT], float Block1[BLOCK_POS_CT]) 219 | { 220 | float3 ssd; 221 | for(int i; i < BLOCK_POS_CT; i++) 222 | { 223 | float2 t = 2.0 * (Block0[i] - Block1[i]) / (Block0[i] + Block1[i] + 0.001); 224 | ssd += abs(t); 225 | } 226 | 227 | return dot(ssd, 0.5) * rcp(BLOCK_POS_CT); 228 | } 229 | 230 | float BlockErrS(float Block0[9], float Block1[9]) 231 | { 232 | float ssd; 233 | for(int i; i < 9; i++) 234 | { 235 | float t = (Block0[i] - Block1[i]) / (Block0[i] + Block1[i] + 0.001); 236 | ssd += abs(t); 237 | } 238 | 239 | return ssd * rcp(BLOCKS_SIZE*BLOCKS_SIZE); 240 | } 241 | 242 | float3 HueToRGB(float hue) 243 | { 244 | float3 fr = frac(hue.xxx + float3(0.0, -1.0/3.0, 1.0/3.0)); 245 | float3 s = 3.0 * abs(1.0 - 2.0*fr) - 1.0; 246 | return s; 247 | //return 0.5 + 0.5 * sin(12.56 * hue + float3(0.0,1.5707,3.14159)); 248 | } 249 | 250 | float3 MVtoRGB( float2 MV ) 251 | { 252 | float3 col = HueToRGB(atan2(MV.y, MV.x) / 6.28); 253 | if(isnan(col).x) return 0.5; 254 | return lerp(0.5, col, saturate(length(MV))); 255 | 256 | } 257 | 258 | float4 CalcMV(sampler2D cur, sampler2D pre, int2 pos, float4 off, int RAD, bool reject) 259 | { 260 | 261 | float cBlock[BLOCK_POS_CT]; 262 | GetBlock(cur, pos, 0.0, 4.0, cBlock); 263 | 264 | float sBlock[BLOCK_POS_CT]; 265 | GetBlock(pre, pos, 0.0, 4.0, sBlock); 266 | 267 | float2 MV; 268 | float2 noff = off.xy; 269 | 270 | float Err = BlockErr(cBlock, sBlock); 271 | 272 | float cenC = tex2DfetchLin(cur, floor(pos) * 4.0).x; 273 | 274 | for(int i = -RAD; i <= RAD; i++) for(int ii = -RAD; ii <= RAD; ii++) 275 | { 276 | GetBlock(pre, pos, int2(i, ii) + off.xy, 4.0, sBlock); 277 | float tErr = BlockErr(cBlock, sBlock); 278 | 279 | [flatten] 280 | if(tErr < Err) 281 | { 282 | Err = tErr; 283 | MV = float2(i, ii); 284 | } 285 | if(Err < 0.001) break; 286 | } 287 | 288 | //off += MV; 289 | //MV = 0; 290 | 291 | //if(Err > 0.33 && reject) return float4(0.0.xx, 1000.0, 1.0); 292 | 293 | //Err *= Err; 294 | return float4(MV + off.xy, off.z + Err, 1.0); 295 | } 296 | 297 | float4 PrevLayer(sampler2D tex, sampler2D depTexC, sampler2D depTexL, int2 vpos, float level, int ITER, float mult) 298 | { 299 | float3 acc = 0.0;//tex2DfetchLin(tex, 0.5 * vpos).xyz; 300 | float accw = 0.0; 301 | float noise = 1.0 + IGN(vpos); 302 | float2 uvm = 0.5 * rcp(tex2Dsize(tex)); 303 | float2 xy = vpos.xy * uvm; 304 | float cenD = tex2Dlod(depTexC, float4(xy, 0, 0) ).y; 305 | 306 | float2 avgSign; 307 | for(int i = -ITER; i <= ITER; i++) for(int ii = -ITER; ii <= ITER; ii++) 308 | { 309 | float2 off = 2 * abs(float2(i,ii)) * float2(i,ii); 310 | float2 sxy = uvm * (vpos + off); 311 | float3 sam = tex2DfetchLin(tex, 0.5 * vpos + noise*off).xyz; 312 | float samD = tex2Dlod(depTexL, float4(sxy,0,0) ).y; 313 | 314 | 315 | float w = exp(-(abs(i) + abs(ii)) * 1.0 * sam.z) + 0.001;// 316 | w *= exp(-exp2(level) * 10.0 * abs(cenD - samD) / (cenD + 0.001)) + exp2(-32); 317 | float2 r = saturate(sxy * sxy - sxy);//thx ceejay 318 | w *= r.x == -r.y; 319 | 320 | float step = 0.5 * (1.0 - ( (ITER*(i + ITER) + (ii + ITER) + 1) / (4*ITER*ITER) )); 321 | 322 | //acc = lerp(acc, sam, 0.1 ); 323 | acc += w * float3((sam.xy), sam.z); 324 | accw += w; 325 | avgSign += w * sign(sam.xy); 326 | } 327 | 328 | acc = acc / accw;// * float3(sign(avgSign), 1.0); 329 | 330 | 331 | //return float4(2.0 * tex2DfetchLin(tex, 0.5 * vpos).xyz, 1.0); 332 | return float4(2.0 * acc.xy, 1.0 * acc.z, 1.0); 333 | } 334 | 335 | static const int2 ioff[5] = { int2(0,0), int2(1,0), int2(0,1), int2(-1,0), int2(0,-1) }; 336 | float4 PrevLayerL(sampler2D tex, sampler2D cur, sampler2D pre, float2 vpos, float level, int ITER, float mult) 337 | { 338 | float cBlock[BLOCK_POS_CT]; 339 | GetBlock(cur, vpos, 0.0, mult, cBlock); 340 | 341 | float sBlock[BLOCK_POS_CT]; 342 | GetBlock(pre, vpos, 0.0, mult, sBlock); 343 | 344 | float Err = BlockErr(cBlock, sBlock); 345 | float4 MV = tex2Dfetch(tex, 0.5 * vpos); 346 | 347 | for(int i = 1; i <= 1; i++) for(int ii; ii < 5; ii++) 348 | { 349 | float4 samMV = 2.0 * tex2Dfetch(tex, 2 * i * ioff[ii] + 0.5 * vpos); 350 | GetBlock(pre, vpos, samMV.xy, 4.0, sBlock); 351 | 352 | float tErr = BlockErr(cBlock, sBlock); 353 | 354 | [flatten] 355 | if(tErr < Err) 356 | { 357 | MV = samMV; 358 | Err = tErr; 359 | } 360 | 361 | } 362 | 363 | return MV;// 364 | //return float4(2.0 * tex2DfetchLin(tex, 0.5 * vpos).xyz, 1.0); 365 | } 366 | 367 | float2 CurrLayer(sampler2D tex, int2 vpos, float level, int ITER) 368 | { 369 | float2 cen = tex2DfetchLin(tex, vpos).xy; 370 | float2 minm; float2 maxm; float2 t; 371 | 372 | float dir = 1.5707 * IGN(vpos + IGNSCROLL * level); 373 | float2 o; 374 | 375 | float2 tcord; float2 txy; 376 | float w; 377 | 378 | for(int i; i < ITER; i++) 379 | { 380 | minm = 9999.9; maxm = -9999.9; 381 | dir += 0.25 * 1.5707; 382 | o = (1.0 + i) * float2(sin(dir), cos(dir)); 383 | 384 | txy = vpos + int2(o.y,o.x); 385 | t = tex2DfetchLin(tex, txy ).xy; 386 | cen += 0.25 * t / i; 387 | 388 | minm = min(minm, t); maxm = max(maxm, t); 389 | txy = vpos + int2(o.x,o.y); 390 | t = tex2DfetchLin(tex, txy ).xy; 391 | cen += 0.25 * t / i; 392 | 393 | minm = min(minm, t); maxm = max(maxm, t); 394 | cen /= 1.0 + 1.0 * rcp(i); 395 | cen = clamp(cen, minm, maxm); 396 | 397 | } 398 | 399 | return cen; 400 | } 401 | 402 | //======================================================================================= 403 | //Gaussian Pyramid 404 | //======================================================================================= 405 | 406 | float2 DUSample(sampler input, float2 xy, float div)//0.375 + 0.25 407 | { 408 | float2 hp = div * rcp(RES); 409 | float4 acc; float4 t; 410 | float minD = 1.0; 411 | 412 | t = tex2D(input, xy + float2(-hp.x, hp.y)); 413 | acc += 0.03125 * t; minD = min(minD, t.y); 414 | 415 | t = tex2D(input, xy + float2(0, hp.y)); 416 | acc += 0.0625 * t; minD = min(minD, t.y); 417 | 418 | t = tex2D(input, xy + float2(hp.x, hp.y)); 419 | acc += 0.03125 * t; minD = min(minD, t.y); 420 | 421 | t = tex2D(input, xy + float2(-hp.x, 0)); 422 | acc += 0.0625 * t; minD = min(minD, t.y); 423 | 424 | t = tex2D(input, xy + float2(0, 0)); 425 | acc += 0.125 * t; minD = min(minD, t.y); 426 | 427 | t = tex2D(input, xy + float2(hp.x, 0)); 428 | acc += 0.0625 * t; minD = min(minD, t.y); 429 | 430 | t = tex2D(input, xy + float2(-hp.x, -hp.y)); 431 | acc += 0.03125 * t; minD = min(minD, t.y); 432 | 433 | t = tex2D(input, xy + float2(0, -hp.y)); 434 | acc += 0.0625 * t; minD = min(minD, t.y); 435 | 436 | t = tex2D(input, xy + float2(hp.x, -hp.y)); 437 | acc += 0.03125 * t; minD = min(minD, t.y); 438 | 439 | t = tex2D(input, xy + 0.5 * float2(hp.x, hp.y)); 440 | acc += 0.125 * t; minD = min(minD, t.y); 441 | 442 | t = tex2D(input, xy + 0.5 * float2(hp.x, -hp.y)); 443 | acc += 0.125 * t; minD = min(minD, t.y); 444 | 445 | t = tex2D(input, xy + 0.5 * float2(-hp.x, hp.y)); 446 | acc += 0.125 * t; minD = min(minD, t.y); 447 | 448 | t = tex2D(input, xy + 0.5 * float2(-hp.x, -hp.y)); 449 | acc += 0.125 * t; minD = min(minD, t.y); 450 | 451 | 452 | 453 | return acc.xy;//float2(acc.x, minD); 454 | } 455 | 456 | 457 | float2 Gauss0PS(PS_INPUTS) : SV_Target { 458 | float lum = pow(GetLuminance(pow(GetBackBuffer(xy), 2.2)), rcp(2.2)); 459 | float dep = GetDepth(xy); 460 | return float2(pow(lum, 2.2), dep).xy; 461 | } 462 | float2 Gauss1PS(PS_INPUTS) : SV_Target { return DUSample(sCG0, xy, 2.0).xy; } 463 | float2 Gauss2PS(PS_INPUTS) : SV_Target { return DUSample(sCG1, xy, 4.0).xy; } 464 | float2 Gauss3PS(PS_INPUTS) : SV_Target { return DUSample(sCG2, xy, 8.0).xy; } 465 | float2 Gauss4PS(PS_INPUTS) : SV_Target { return DUSample(sCG3, xy, 16.0).xy; } 466 | float2 Gauss5PS(PS_INPUTS) : SV_Target { return DUSample(sCG4, xy, 32.0).xy; } 467 | 468 | float Copy0PS(PS_INPUTS) : SV_Target { return tex2D(sCG0, xy).x; } 469 | float Copy1PS(PS_INPUTS) : SV_Target { return tex2D(sCG1, xy).x; } 470 | float Copy2PS(PS_INPUTS) : SV_Target { return tex2D(sCG2, xy).x; } 471 | float Copy3PS(PS_INPUTS) : SV_Target { return tex2D(sCG3, xy).x; } 472 | float Copy4PS(PS_INPUTS) : SV_Target { return tex2D(sCG4, xy).x; } 473 | float Copy5PS(PS_INPUTS) : SV_Target { return tex2D(sCG5, xy).x; } 474 | 475 | 476 | //======================================================================================= 477 | //Motion Passes 478 | //======================================================================================= 479 | 480 | float4 Level5PS(PS_INPUTS) : SV_Target 481 | { 482 | return CalcMV(sCG5, sPG5, vpos.xy, TEMPORAL * tex2Dlod(sLevel0, float4(xy, 0, 6) ) / 32, 4, 1); 483 | } 484 | 485 | float4 Level4PS(PS_INPUTS) : SV_Target 486 | { 487 | return CalcMV(sCG4, sPG4, vpos.xy, PrevLayerL(sLevel5, sCG4, sPG4, vpos.xy, 2, 1, 4.0), 2, 1); 488 | } 489 | 490 | float4 Level3PS(PS_INPUTS) : SV_Target 491 | { 492 | return CalcMV(sCG3, sPG3, vpos.xy, PrevLayerL(sLevel4, sCG3, sPG3, vpos.xy, 2, 1, 4.0), 1, 1); 493 | } 494 | 495 | float4 Level2PS(PS_INPUTS) : SV_Target 496 | { 497 | return CalcMV(sCG2, sPG2, vpos.xy, PrevLayerL(sLevel3, sCG2, sPG2, vpos.xy, 2, 1, 4.0), 1, 1); 498 | } 499 | 500 | float4 Level1PS(PS_INPUTS) : SV_Target 501 | { 502 | return CalcMV(sCG1, sPG1, vpos.xy, PrevLayerL(sLevel2, sCG1, sPG1, vpos.xy, 1, 1, 4.0), 1, 1); 503 | } 504 | 505 | float4 Level0PS(PS_INPUTS) : SV_Target 506 | { 507 | //if(FLOW_QUALITY == 0) discard; 508 | return CalcMV(sCG0, sPG0, vpos.xy, PrevLayerL(sLevel1, sCG0, sPG0, vpos.xy, 0, 1, 4.0), 1, 1); 509 | } 510 | 511 | //======================================================================================= 512 | //Final Filtering 513 | //======================================================================================= 514 | /* 515 | float3 JumpFlood(sampler2D tex, float2 xy, float level) 516 | { 517 | float3 fpos = tex2Dlod(tex, float4(xy, 0, 0)).xyz; 518 | 519 | [branch] 520 | if(any(fpos <= FARPLANE)) return fpos; 521 | float3 cpos = NorEyePos(xy); 522 | 523 | float2 mult = exp2(level) / tex2Dsize(tex); 524 | for(int i = -2; i <= 2; i++) for(int ii = -2; ii <= 2; ii++) 525 | { 526 | float2 nxy = xy + mult * float2(i, ii); 527 | float3 tpos = tex2Dlod(tex, float4(nxy,0,0)).xyz; 528 | [flatten] 529 | if(dot(cpos-tpos, cpos-tpos) < dot(cpos-fpos, cpos-fpos)) 530 | { 531 | fpos = tpos; 532 | } 533 | } 534 | return fpos; 535 | } 536 | 537 | float4 PrepFloodPS(PS_INPUTS) : SV_Target 538 | { 539 | float doc = tex2D(sLevel0, xy ).z; 540 | float l = dot(GetBackBuffer(xy), 1.0); 541 | return float4( (doc > 100.0 || l <= exp2(-8) ) ? 10.0 * FARPLANE : NorEyePos(xy), 1.0); 542 | } 543 | 544 | float4 Flood5PS(PS_INPUTS) : SV_Target { return float4(JumpFlood(sTemp0, xy, 5.0), 1.0); } 545 | float4 Flood4PS(PS_INPUTS) : SV_Target { return float4(JumpFlood(sTemp1, xy, 4.0), 1.0); } 546 | float4 Flood3PS(PS_INPUTS) : SV_Target { return float4(JumpFlood(sTemp0, xy, 3.0), 1.0); } 547 | float4 Flood2PS(PS_INPUTS) : SV_Target { return float4(JumpFlood(sTemp1, xy, 2.0), 1.0); } 548 | float4 Flood1PS(PS_INPUTS) : SV_Target { return float4(JumpFlood(sTemp0, xy, 1.0), 1.0); } 549 | float4 Flood0PS(PS_INPUTS) : SV_Target { return float4(JumpFlood(sTemp1, xy, 0.0), 1.0); } 550 | */ 551 | //======================================================================================= 552 | //Blending 553 | //======================================================================================= 554 | 555 | float2 SavePS(PS_INPUTS) : SV_Target 556 | { 557 | //float2 fuv = GetScreenPos(tex2D(sTemp0, xy).xyz).xy; 558 | float2 MV = tex2D(sLevel0, xy ).xy / (1.0 + SUBPIXEL_FLOW); 559 | 560 | return any(abs(MV.xy) > 0.125) ? MV.xy / RES : 0.0; 561 | } 562 | 563 | float3 BlendPS(PS_INPUTS) : SV_Target 564 | { 565 | float2 MV = tex2D(sMV, xy).xy; 566 | 567 | MV *= 0.05 * RES; 568 | MV = lerp(MV, MV / (abs(MV) + 1.0), saturate(MV)); 569 | return DEBUG ? MVtoRGB(MV) : GetBackBuffer(xy); 570 | } 571 | 572 | technique QuarkMotion < 573 | ui_label = "Quark: Motion"; 574 | ui_tooltip = 575 | " Quark Motion - Created by Zenteon \n" 576 | "\n=================================================================================================" 577 | "\n" 578 | "\nGenerates motion vectors for other shaders" 579 | "\n" 580 | "\n================================================================================================="; 581 | > 582 | { 583 | pass { PASS1(Gauss0PS, tCG0); } 584 | pass { PASS1(Gauss1PS, tCG1); } 585 | pass { PASS1(Gauss2PS, tCG2); } 586 | pass { PASS1(Gauss3PS, tCG3); } 587 | pass { PASS1(Gauss4PS, tCG4); } 588 | pass { PASS1(Gauss5PS, tCG5); } 589 | 590 | //optical flow 591 | pass { PASS1(Level5PS, tLevel5); } 592 | pass { PASS1(Level4PS, tLevel4); } 593 | pass { PASS1(Level3PS, tLevel3); } 594 | pass { PASS1(Level2PS, tLevel2); } 595 | pass { PASS1(Level1PS, tLevel1); } 596 | pass { PASS1(Level0PS, tLevel0); } 597 | 598 | /* 599 | pass { PASS1(PrepFloodPS, tTemp0); } 600 | pass { PASS1(Flood5PS, tTemp1); } 601 | pass { PASS1(Flood4PS, tTemp0); } 602 | pass { PASS1(Flood3PS, tTemp1); } 603 | pass { PASS1(Flood2PS, tTemp0); } 604 | pass { PASS1(Flood1PS, tTemp1); } 605 | pass { PASS1(Flood0PS, tTemp0); } 606 | */ 607 | 608 | pass { PASS1(Copy0PS, tPG0); } 609 | pass { PASS1(Copy1PS, tPG1); } 610 | pass { PASS1(Copy2PS, tPG2); } 611 | pass { PASS1(Copy3PS, tPG3); } 612 | pass { PASS1(Copy4PS, tPG4); } 613 | pass { PASS1(Copy5PS, tPG5); } 614 | 615 | pass { PASS1(SavePS, texMotionVectors); } 616 | pass { PASS0(BlendPS); } 617 | } 618 | } 619 | -------------------------------------------------------------------------------- /Shaders/Quark_Xenon_Bloom.fx: -------------------------------------------------------------------------------- 1 | //======================================================================== 2 | /* 3 | Copyright © Daniel Oren-Ibarra - 2024 4 | All Rights Reserved. 5 | 6 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND 7 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 8 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 9 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 10 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 11 | TORT OR OTHERWISE,ARISING FROM, OUT OF OR IN CONNECTION WITH THE 12 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 13 | 14 | 15 | ====================================================================== 16 | Quark: Xenon v0.2 - Authored by Daniel Oren-Ibarra "Zenteon" 17 | 18 | Discord: https://discord.gg/PpbcqJJs6h 19 | Patreon: https://patreon.com/Zenteon 20 | 21 | 22 | */ 23 | //======================================================================== 24 | 25 | 26 | 27 | 28 | 29 | #if(__RENDERER__ != 0x9000) 30 | 31 | #include "ReShade.fxh" 32 | 33 | #ifndef FULL_CONTROL 34 | //============================================================================================ 35 | #define FULL_CONTROL 0 36 | //============================================================================================ 37 | #endif 38 | 39 | #ifndef EMX 40 | //============================================================================================ 41 | #define EMX 0 42 | //============================================================================================ 43 | #endif 44 | 45 | //#if(Sample_Wrap == 0) 46 | #define CLAMPSAM AddressU = CLAMP; AddressV = CLAMP; AddressW = CLAMP; 47 | #define WRAPSAM AddressU = WRAP; AddressV = WRAP; AddressW = WRAP; 48 | //#else 49 | // #define WRAPSAM AddressU = WRAP; AddressV = WRAP; AddressW = WRAP; 50 | //#endif 51 | #define RES float2(BUFFER_WIDTH, BUFFER_HEIGHT) 52 | #define ASPECT_R (float2(1.0, 0.5625) / float2(1.0, RES.y / RES.x)) 53 | 54 | namespace Xenon { 55 | texture DirtTex < source = "QuarkDirt.png"; > 56 | { 57 | Width = 1920; 58 | Height = 1080; 59 | Format = RGBA8; 60 | }; 61 | } 62 | 63 | sampler XenDirt { Texture = Xenon::DirtTex; WRAPSAM}; 64 | 65 | uniform int XENON < 66 | ui_type = "radio"; 67 | ui_label = " "; 68 | ui_text = "XENON is a high quality bloom shader tuned to provide dramatic bloom without overpowering the image"; 69 | ui_category = "XENON"; 70 | ui_category_closed = true; 71 | > = 0; 72 | 73 | uniform float BLUR_OFFSET < 74 | ui_type = "slider"; 75 | ui_min = 0.5; 76 | ui_max = 1.0; 77 | hidden = !FULL_CONTROL; 78 | ui_label = "Bloom Radius"; 79 | > = 1.0; 80 | 81 | uniform float BLOOM_INTENSITY < 82 | ui_type = "slider"; 83 | ui_min = 0.0; 84 | ui_max = 1.0 + FULL_CONTROL; 85 | ui_label = "Bloom Intensity"; 86 | ui_tooltip = "How much bloom is added into the original image"; 87 | > = 0.25; 88 | 89 | uniform float BLOOM_BRIGHT < 90 | ui_type = "slider"; 91 | ui_min = 0.0; 92 | ui_max = 3.0; 93 | ui_label = "Bloom Brightness"; 94 | ui_tooltip = "Intensity of added bloom"; 95 | > = 1.5; 96 | 97 | uniform float DEPTH_MASK < 98 | ui_type = "slider"; 99 | ui_min = 0.0; 100 | ui_max = 8.0; 101 | ui_label = "Depth Mask"; 102 | > = 2.0; 103 | 104 | uniform float DIRT_STRENGTH < 105 | ui_type = "slider"; 106 | ui_min = 0.0; 107 | ui_max = 2.0; 108 | ui_label = "Dirt Intensity"; 109 | > = 0.8; 110 | 111 | uniform bool DEBUG < 112 | ui_label = "Display Raw Bloom\n\n"; 113 | hidden = !FULL_CONTROL; 114 | > = 0; 115 | 116 | uniform float HDR_RED < 117 | ui_type = "slider"; 118 | ui_min = 1.001; 119 | ui_max = 1.2; 120 | ui_label = "Range Expansion"; 121 | hidden = !FULL_CONTROL; 122 | ui_tooltip = "Desaturates highlights and reduces point intensity"; 123 | > = 1.03; 124 | 125 | uniform float POSXPOS < 126 | ui_type = "slider"; 127 | ui_min = 0.5; 128 | ui_max = 2.0; 129 | ui_label = "Post Contrast"; 130 | hidden = !FULL_CONTROL; 131 | ui_tooltip = "Desaturates highlights and reduces point intensity"; 132 | > = 1.5; 133 | 134 | uniform float PREXPOS < 135 | ui_type = "slider"; 136 | ui_min = 0.9; 137 | ui_max = 3.0; 138 | ui_label = "Pre Exposure"; 139 | hidden = !FULL_CONTROL; 140 | ui_tooltip = "Desaturates highlights and reduces point intensity"; 141 | > = 2.5; 142 | 143 | uniform float KERNEL_SHAPE < 144 | ui_type = "slider"; 145 | ui_min = 0.1; 146 | ui_max = 1.0; 147 | ui_label = "Kernel Shape"; 148 | hidden = !FULL_CONTROL; 149 | ui_tooltip = "Modify the shape of the bloom kernel"; 150 | > = 0.7; 151 | 152 | uniform float BLOOM_SAT < 153 | ui_type = "slider"; 154 | ui_min = 0.0; 155 | ui_max = 1.5; 156 | ui_label = "Bloom Saturation"; 157 | hidden = !FULL_CONTROL; 158 | > = 1.1; 159 | 160 | uniform float3 BLOOM_COL < 161 | ui_type = "color"; 162 | ui_label = "Bloom Color"; 163 | hidden = !FULL_CONTROL; 164 | > = 1.0; 165 | 166 | 167 | 168 | namespace XEN { 169 | texture LightMap{Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F;}; 170 | texture DownTex0{Width = BUFFER_WIDTH / 2; Height = BUFFER_HEIGHT / 2; Format = RGBA16F;}; 171 | texture DownTex1{Width = BUFFER_WIDTH / 4; Height = BUFFER_HEIGHT / 4; Format = RGBA16F;}; 172 | texture DownTex2{Width = BUFFER_WIDTH / 8; Height = BUFFER_HEIGHT / 8; Format = RGBA16F;}; 173 | texture DownTex3{Width = BUFFER_WIDTH / 16; Height = BUFFER_HEIGHT / 16; Format = RGBA16F;}; 174 | texture DownTex4{Width = BUFFER_WIDTH / 32; Height = BUFFER_HEIGHT / 32; Format = RGBA16F;}; 175 | texture DownTex5{Width = BUFFER_WIDTH / 64; Height = BUFFER_HEIGHT / 64; Format = RGBA16F;}; 176 | texture DownTex6{Width = BUFFER_WIDTH / 128; Height = BUFFER_HEIGHT / 128; Format = RGBA16F;}; 177 | texture DownTex7{Width = BUFFER_WIDTH / 256; Height = BUFFER_HEIGHT / 256; Format = RGBA16F;}; 178 | 179 | texture UpTex000{Width = BUFFER_WIDTH / 128; Height = BUFFER_HEIGHT / 128; Format = RGBA16F;}; 180 | texture UpTex00{Width = BUFFER_WIDTH / 64; Height = BUFFER_HEIGHT / 64; Format = RGBA16F;}; 181 | texture UpTex0{Width = BUFFER_WIDTH / 32; Height = BUFFER_HEIGHT / 32; Format = RGBA16F;}; 182 | texture UpTex1{Width = BUFFER_WIDTH / 16; Height = BUFFER_HEIGHT / 16; Format = RGBA16F;}; 183 | texture UpTex2{Width = BUFFER_WIDTH / 8; Height = BUFFER_HEIGHT / 8; Format = RGBA16F;}; 184 | texture UpTex3{Width = BUFFER_WIDTH / 4; Height = BUFFER_HEIGHT / 4; Format = RGBA16F;}; 185 | texture UpTex4{Width = BUFFER_WIDTH / 2; Height = BUFFER_HEIGHT / 2; Format = RGBA16F;}; 186 | 187 | texture BloomTex{Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F;}; 188 | } 189 | sampler LightSam{Texture = XEN::LightMap; CLAMPSAM}; 190 | sampler DownSam0{Texture = XEN::DownTex0; CLAMPSAM}; 191 | sampler DownSam1{Texture = XEN::DownTex1; CLAMPSAM}; 192 | sampler DownSam2{Texture = XEN::DownTex2; CLAMPSAM}; 193 | sampler DownSam3{Texture = XEN::DownTex3; CLAMPSAM}; 194 | sampler DownSam4{Texture = XEN::DownTex4; CLAMPSAM}; 195 | sampler DownSam5{Texture = XEN::DownTex5; CLAMPSAM}; 196 | sampler DownSam6{Texture = XEN::DownTex6; CLAMPSAM}; 197 | sampler DownSam7{Texture = XEN::DownTex7; CLAMPSAM}; 198 | 199 | sampler UpSam000{Texture = XEN::UpTex000; CLAMPSAM}; 200 | sampler UpSam00{Texture = XEN::UpTex00; CLAMPSAM}; 201 | sampler UpSam0{Texture = XEN::UpTex0; CLAMPSAM}; 202 | sampler UpSam1{Texture = XEN::UpTex1; CLAMPSAM}; 203 | sampler UpSam2{Texture = XEN::UpTex2; CLAMPSAM}; 204 | sampler UpSam3{Texture = XEN::UpTex3; CLAMPSAM}; 205 | sampler UpSam4{Texture = XEN::UpTex4; CLAMPSAM}; 206 | 207 | 208 | sampler BloomSam{Texture = XEN::BloomTex; CLAMPSAM}; 209 | 210 | //============================================================================= 211 | //Functions 212 | //============================================================================= 213 | 214 | float4 DownSample(float2 xy, sampler input, float div)//0.375 + 0.25 215 | { 216 | //float2 xy = texcoord; 217 | float2 res = float2(BUFFER_WIDTH, BUFFER_HEIGHT) / div; 218 | float2 hp = 0.5 / res; 219 | float offset = BLUR_OFFSET; 220 | 221 | float4 acc = 0.125 * tex2D(input, xy); 222 | acc += 0.125 * tex2D(input, xy + float2(hp.x, hp.y) * offset); 223 | acc += 0.125 * tex2D(input, xy + float2(hp.x, -hp.y) * offset); 224 | acc += 0.125 * tex2D(input, xy + float2(-hp.x, hp.y) * offset); 225 | acc += 0.125 * tex2D(input, xy + float2(-hp.x, -hp.y) * offset); 226 | 227 | acc += 0.0625 * tex2D(input, xy + float2(2f * hp.x, 0) * offset); 228 | acc += 0.0625 * tex2D(input, xy + float2(0, 2f * hp.y) * offset); 229 | acc += 0.0625 * tex2D(input, xy + float2(2f * -hp.x,0) * offset); 230 | acc += 0.0625 * tex2D(input, xy + float2(0, 2f*-hp.y) * offset); 231 | 232 | acc += 0.03125 * tex2D(input, xy + float2(hp.x, hp.y) * 2f * offset); 233 | acc += 0.03125 * tex2D(input, xy + float2(hp.x, -hp.y) * 2f * offset); 234 | acc += 0.03125 * tex2D(input, xy + float2(-hp.x, hp.y) * 2f * offset); 235 | acc += 0.03125 * tex2D(input, xy + float2(-hp.x, -hp.y) * 2f * offset); 236 | 237 | 238 | return acc; 239 | 240 | } 241 | 242 | float4 UpSample(float2 xy, sampler input, float div) 243 | { 244 | //float2 xy = texcoord; 245 | float2 res = float2(BUFFER_WIDTH, BUFFER_HEIGHT) / div; 246 | 247 | float offset = BLUR_OFFSET; 248 | float2 hp = 0.5 / res; 249 | float4 acc = 0.5 * tex2D(input, xy); 250 | 251 | acc += 0.1875 * tex2D(input, xy + float2(hp.x, hp.y) * offset); 252 | acc += 0.1875 * tex2D(input, xy + float2(hp.x, -hp.y) * offset); 253 | acc += 0.1875 * tex2D(input, xy + float2(-hp.x, hp.y) * offset); 254 | acc += 0.1875 * tex2D(input, xy + float2(-hp.x, -hp.y) * offset); 255 | 256 | acc += 0.0625 * tex2D(input, xy + hp * float2(2, 0) * offset); 257 | acc += 0.0625 * tex2D(input, xy + hp * float2(-2, 0) * offset); 258 | acc += 0.0625 * tex2D(input, xy + hp * float2(0, 2) * offset); 259 | acc += 0.0625 * tex2D(input, xy + hp * float2(0, -2) * offset); 260 | 261 | return acc / 1.5; 262 | } 263 | 264 | //============================================================================= 265 | //Tonemappers 266 | //============================================================================= 267 | 268 | float3 ReinhardtJ(float3 x) //Modified Reinhardt Jodie 269 | { 270 | float lum = dot(x, float3(0.2126, 0.7152, 0.0722)); 271 | float3 tx = x / (x + 1.0); 272 | return saturate(HDR_RED * lerp(x / (lum + 1.0), tx, pow(tx, 1.0))); 273 | //return saturate(HDR_RED * x / (x + 1.0)); 274 | } 275 | 276 | float3 InvReinhardtJ(float3 x) 277 | { 278 | 279 | float lum = dot(x, float3(0.2126, 0.7152, 0.0722)); 280 | float3 tx = -x / (x - HDR_RED); 281 | return max(lerp(tx, -lum / ((0.6 * x + 0.4 * lum) - HDR_RED), pow(x, 1.0)), 0.0001); 282 | //return max(-x / (x - HDR_RED), 0.0001); 283 | } 284 | 285 | //============================================================================= 286 | //Passes 287 | //============================================================================= 288 | float4 BloomMap(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target 289 | { 290 | float3 input = tex2D(ReShade::BackBuffer, xy).rgb; 291 | float depth = 1f - ReShade::GetLinearizedDepth(xy); 292 | input = InvReinhardtJ(input); 293 | input = lerp(0.2126 * input.r + 0.7152 * input.g + 0.0722 * input.b, input, BLOOM_SAT); 294 | input = max(input, 0.0); 295 | input = (normalize(input) / 0.5774) * pow((input.r + input.g + input.b) / 3.0, PREXPOS); 296 | return float4(BLOOM_COL * BLOOM_BRIGHT * input, depth); 297 | } 298 | //============================================================================= 299 | //Bloom Passes 300 | //============================================================================= 301 | 302 | float4 DownSample0(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 303 | return DownSample(xy, LightSam, 2.0); } 304 | 305 | float4 DownSample1(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 306 | return DownSample(xy, DownSam0, 4.0); } 307 | 308 | float4 DownSample2(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 309 | return DownSample(xy, DownSam1, 8.0); } 310 | 311 | float4 DownSample3(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 312 | return DownSample(xy, DownSam2, 16.0); } 313 | 314 | float4 DownSample4(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 315 | return DownSample(xy, DownSam3, 32.0); } 316 | 317 | float4 DownSample5(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 318 | return DownSample(xy, DownSam4, 64.0); } 319 | 320 | float4 DownSample6(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 321 | return DownSample(xy, DownSam5, 128.0); } 322 | 323 | float4 DownSample7(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 324 | return DownSample(xy, DownSam6, 256.0); } 325 | //==== 326 | 327 | float4 UpSample000(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 328 | return lerp(tex2D(DownSam6, xy), UpSample(xy, DownSam7, 256.0), 0.3 * KERNEL_SHAPE); } 329 | 330 | float4 UpSample00(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 331 | return lerp(tex2D(DownSam5, xy), UpSample(xy, UpSam000, 128.0), 0.3 * KERNEL_SHAPE); } 332 | 333 | float4 UpSample0(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 334 | return lerp(tex2D(DownSam4, xy), UpSample(xy, UpSam00, 64.0), 0.4 * KERNEL_SHAPE); } 335 | 336 | float4 UpSample1(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 337 | return lerp(tex2D(DownSam3, xy), UpSample(xy, UpSam0, 32.0), 0.5 * KERNEL_SHAPE); } 338 | 339 | float4 UpSample2(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 340 | return lerp(tex2D(DownSam2, xy), UpSample(xy, UpSam1, 16.0), 0.6 * KERNEL_SHAPE); } 341 | 342 | float4 UpSample3(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 343 | return lerp(tex2D(DownSam1, xy), UpSample(xy, UpSam2, 8.0), 0.7 * KERNEL_SHAPE); } 344 | 345 | float4 UpSample4(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 346 | return lerp(tex2D(DownSam0, xy), UpSample(xy, UpSam3, 4.0), 0.8 * KERNEL_SHAPE); } 347 | 348 | float4 UpSample5(float4 vpos : SV_Position, float2 xy : TexCoord) : SV_Target { 349 | return lerp(tex2D(LightSam, xy), UpSample(xy, UpSam4, 2.0), 0.9 * KERNEL_SHAPE); } 350 | 351 | //============================================================================= 352 | //Blending 353 | //============================================================================= 354 | 355 | float3 QUARK_BLOOM(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target 356 | { 357 | float depth = 1f - ReShade::GetLinearizedDepth(texcoord); 358 | float3 input = tex2D(ReShade::BackBuffer, texcoord).rgb; 359 | input = InvReinhardtJ(input); 360 | 361 | float4 bloom = UpSample(texcoord, BloomSam, 1.0); 362 | 363 | bloom.rgb = pow(bloom.rgb / 4.75, 1.0 / PREXPOS); 364 | bloom.rgb = pow(bloom.rgb, POSXPOS); 365 | 366 | float4 dirt = bloom * tex2D(XenDirt, ASPECT_R * texcoord); 367 | bloom.rgb = lerp(bloom.rgb, bloom.rgb + dirt.rgb, DIRT_STRENGTH); 368 | 369 | float mask = exp(-max(depth - UpSample(texcoord, UpSam0, 32.0).a, 0.0) * DEPTH_MASK); 370 | 371 | input = lerp(input, bloom.rgb, mask * 0.3 * BLOOM_INTENSITY); 372 | 373 | 374 | if(DEBUG) return ReinhardtJ(mask * bloom.rgb); 375 | 376 | return ReinhardtJ(input); 377 | } 378 | 379 | technique Xenon < 380 | ui_label = "Quark: Xenon"; 381 | ui_tooltip = 382 | " Xenon Bloom - Made by Zenteon \n" 383 | "\n=================================================================================================" 384 | "\n" 385 | "\nXenon is a high quality artistic bloom." 386 | "\nIt features a uniquely shaped kernel to balance between wide bloom ranges and excellent precision" 387 | "\nwithout completely overpowering the image" 388 | "\n" 389 | "\n================================================================================================="; 390 | > 391 | { 392 | pass 393 | { 394 | VertexShader = PostProcessVS; 395 | PixelShader = BloomMap; 396 | RenderTarget = XEN::LightMap; 397 | } 398 | 399 | pass {VertexShader = PostProcessVS; PixelShader = DownSample0; RenderTarget = XEN::DownTex0; } 400 | pass {VertexShader = PostProcessVS; PixelShader = DownSample1; RenderTarget = XEN::DownTex1; } 401 | pass {VertexShader = PostProcessVS; PixelShader = DownSample2; RenderTarget = XEN::DownTex2; } 402 | pass {VertexShader = PostProcessVS; PixelShader = DownSample3; RenderTarget = XEN::DownTex3; } 403 | pass {VertexShader = PostProcessVS; PixelShader = DownSample4; RenderTarget = XEN::DownTex4; } 404 | pass {VertexShader = PostProcessVS; PixelShader = DownSample5; RenderTarget = XEN::DownTex5; } 405 | pass {VertexShader = PostProcessVS; PixelShader = DownSample6; RenderTarget = XEN::DownTex6; } 406 | pass {VertexShader = PostProcessVS; PixelShader = DownSample7; RenderTarget = XEN::DownTex7; } 407 | 408 | pass {VertexShader = PostProcessVS; PixelShader = UpSample000; RenderTarget = XEN::UpTex000; } 409 | pass {VertexShader = PostProcessVS; PixelShader = UpSample00; RenderTarget = XEN::UpTex00; } 410 | pass {VertexShader = PostProcessVS; PixelShader = UpSample0; RenderTarget = XEN::UpTex0; } 411 | pass {VertexShader = PostProcessVS; PixelShader = UpSample1; RenderTarget = XEN::UpTex1; } 412 | pass {VertexShader = PostProcessVS; PixelShader = UpSample2; RenderTarget = XEN::UpTex2; } 413 | pass {VertexShader = PostProcessVS; PixelShader = UpSample3; RenderTarget = XEN::UpTex3; } 414 | pass {VertexShader = PostProcessVS; PixelShader = UpSample4; RenderTarget = XEN::UpTex4; } 415 | pass {VertexShader = PostProcessVS; PixelShader = UpSample5; RenderTarget = XEN::BloomTex; } 416 | pass 417 | { 418 | VertexShader = PostProcessVS; 419 | PixelShader = QUARK_BLOOM; 420 | } 421 | } 422 | #else 423 | int Dx9Warning < 424 | ui_type = "radio"; 425 | ui_text = "Oops, looks like you're using DX9\n" 426 | "if you would like to use Quark Shaders in DX9 games, please use a wrapper like DXVK or dgVoodoo2"; 427 | ui_label = " "; 428 | > = 0; 429 | 430 | technique Xenon < 431 | ui_label = "Quark: Xenon"; 432 | ui_tooltip = 433 | " Xenon Bloom - Made by Zenteon \n" 434 | "\n=================================================================================================" 435 | "\n" 436 | "\nXenon is a high quality artistic bloom." 437 | "\nIt features a uniquely shaped kernel to balance between wide bloom ranges and excellent precision" 438 | "\nwithout completely overpowering the image" 439 | "\n" 440 | "\n================================================================================================="; 441 | > 442 | { } 443 | #endif 444 | -------------------------------------------------------------------------------- /Textures/QuarkBN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zenteon/QuarkFX/02c295117161d1f8a30a5bfa97e9264f96624dc1/Textures/QuarkBN.png -------------------------------------------------------------------------------- /Textures/QuarkDirt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zenteon/QuarkFX/02c295117161d1f8a30a5bfa97e9264f96624dc1/Textures/QuarkDirt.png --------------------------------------------------------------------------------