Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- // ReShade effect file
- // visit facebook.com/MartyMcModding for news/updates
- //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- // Ambient Obscurance with Indirect Lighting "MXAO" 1.5.7r by Marty McFly
- // Copyright © 2008-2016 Marty McFly
- //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- #define fMXAOAmbientOcclusionAmount 1.0 //[0.0 to 2.0] Linearly increases AO intensity. Can cause pitch black clipping if set too high.
- #define bMXAOIndirectLightingEnable 0 //[0 or 1] Enables Indirect Lighting calculation. Will cause a major fps hit.
- #define fMXAOIndirectLightingAmount 1.0 //[0.0 to 8.0] Linearly increases IL intensity.
- #define fMXAOIndirectLightingSaturation 1.0 //[0.0 to 3.0] Boosts IL saturation for more pronounced effect.
- #define fMXAOSampleRadius 4.5 //[0.5 to 20.0] Sample radius of GI, higher values drop performance. Heavily depending on game, GTASA: 10 = GTA V: 40ish
- #define iMXAOSampleCount 36 //[16 to 254] Amount of MXAO samples. Higher means more accurate and less noisy AO at the cost of fps.
- #define bMXAOSmartSamplingEnable 0 //[0 or 1] Enables smart sample count reduction for far areas. May look ugly when low sample count (16 or less) is used, turn it off then.
- #define iMXAOBayerDitherLevel 7 //[2 to 8] 2^ditherlevel: size of AO sampling pattern size. Lower values mean less distinctive sample dirs and haloing.
- #define fMXAONormalBias 0.2 //[0.0 to 0.4] Normals bias to reduce self-occlusion of surfaces that have a low angle to each other.
- #define bMXAOPerPixelNormalsEnable 1 //[0 or 1] TEST! Enables per pixel normals derived from color input so surfaces get some relief instead of being 100% flat.
- #define bMXAOBackfaceCheckEnable 0 //[0 or 1] For indirect lighting only! Enables back face check so surfaces facing away from the source position don't cast light. It comes with a slight fps drop.
- #define bMXAOBoundaryCheckEnable 0 //[0 or 1] Enables screen boundary check for samples. Can be useful to remove odd behaviour with too high sample radius / objects very close to camera. It comes with a slight fps drop.
- #define bMXAOLowPrecisionEnable 1 //[0 or 1] Enables lower bit mode for AO source texture (R32F vs R16F). This will improve performance but may introduce some artifacts at distant objects.
- #define fMXAOBlurSharpness 1.0 //[0.0 to 3.0] AO sharpness, higher means more sharp geometry edges but noisier AO, less means smoother AO but blurry in the distance.
- #define fMXAOBlurSteps 3 //[2 to 7] Offset count for AO smoothening. Higher means more smooth AO but also blurrier AO.
- #define fMXAOMipLevelIL 2 //[0 to 4] Miplevel of IL texture. 0 = fullscreen, 1 = 1/2 screen width/height, 2 = 1/4 screen width/height and so forth.
- #define fMXAOMipLevelAO 0 //[0 to 2] Miplevel of AO texture. 0 = fullscreen, 1 = 1/2 screen width/height, 2 = 1/4 screen width/height and so forth. Best results: IL MipLevel = AO MipLevel + 2
- #define bMXAODebugViewEnable 0 //[0 or 1] Enables raw AO/IL output for debugging and tuning purposes.
- //custom variables, depleted after Framework implementation.
- #define AO_FADE____START 0.6 //[0.0 to 1.0] Depth at which AO starts to fade out. 0.0 = camera, 1.0 = sky. Must be lower than AO fade end.
- #define AO_FADE____END 0.9 //[0.0 to 1.0] Depth at which AO completely fades out. 0.0 = camera, 1.0 = sky. Must be higher than AO fade start.
- #define MXAO_TOGGLEKEY 0x20 //SPACEBAR
- #pragma reshade showfps
- uniform float Timer < source = "timer"; >;
- #define PixelSize float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
- //textures
- texture2D texColor : COLOR;
- texture2D texDepth : DEPTH;
- texture2D texLOD { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; MipLevels = 5+fMXAOMipLevelIL;};
- #if(bMXAOLowPrecisionEnable != 0)
- texture2D texDepthLOD { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = R16F; MipLevels = 5+fMXAOMipLevelAO;};
- #else
- texture2D texDepthLOD { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = R32F; MipLevels = 5+fMXAOMipLevelAO;};
- #endif
- #if(bMXAOBackfaceCheckEnable != 0)
- texture2D texNormal { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; MipLevels = 5+fMXAOMipLevelIL;};
- #else
- texture2D texNormal { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
- #endif
- texture2D texSSAO { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA8; };
- sampler2D SamplerColor
- {
- Texture = texColor;
- MinFilter = LINEAR;
- MagFilter = LINEAR;
- MipFilter = LINEAR;
- AddressU = Clamp;
- AddressV = Clamp;
- };
- sampler2D SamplerDepth
- {
- Texture = texDepth;
- MinFilter = LINEAR;
- MagFilter = LINEAR;
- MipFilter = LINEAR;
- AddressU = Clamp;
- AddressV = Clamp;
- };
- sampler2D SamplerLOD
- {
- Texture = texLOD;
- MinFilter = LINEAR;
- MagFilter = LINEAR;
- MipFilter = LINEAR;
- AddressU = Clamp;
- AddressV = Clamp;
- };
- sampler2D SamplerDepthLOD
- {
- Texture = texDepthLOD;
- MinFilter = POINT;
- MagFilter = POINT;
- MipFilter = POINT;
- AddressU = Clamp;
- AddressV = Clamp;
- };
- sampler2D SamplerNormal
- {
- Texture = texNormal;
- MinFilter = LINEAR;
- MagFilter = LINEAR;
- MipFilter = LINEAR;
- AddressU = Clamp;
- AddressV = Clamp;
- };
- sampler2D SamplerSSAO
- {
- Texture = texSSAO;
- MinFilter = LINEAR;
- MagFilter = LINEAR;
- MipFilter = LINEAR;
- AddressU = Clamp;
- AddressV = Clamp;
- };
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- //
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- void VS_PostProcess(in uint id : SV_VertexID, out float4 pos : SV_Position, out float2 texcoord : TEXCOORD)
- {
- texcoord.x = (id == 2) ? 2.0 : 0.0;
- texcoord.y = (id == 1) ? 2.0 : 0.0;
- pos = float4(texcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
- }
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- //
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- #define RESHADE_DEPTH_LINEARIZATION_FAR_PLANE 1000.0
- float GetLinearDepth(float2 coords)
- {
- float depth = tex2Dlod(SamplerDepth, float4(coords.xy,0,0)).x;
- depth /= RESHADE_DEPTH_LINEARIZATION_FAR_PLANE - depth * RESHADE_DEPTH_LINEARIZATION_FAR_PLANE + depth;
- return depth;
- }
- float3 GetPosition(float2 coords)
- {
- float EyeDepth = GetLinearDepth(coords.xy)*RESHADE_DEPTH_LINEARIZATION_FAR_PLANE;
- return float3((coords.xy * 2.0 - 1.0)*EyeDepth,EyeDepth);
- }
- float3 GetPositionLOD(float2 coords, int mipLevel)
- {
- float EyeDepth = tex2Dlod(SamplerDepthLOD, float4(coords.xy,0,mipLevel)).x;
- return float3((coords.xy * 2.0 - 1.0)*EyeDepth,EyeDepth);
- }
- float3 GetNormalFromDepth(float2 coords)
- {
- float3 centerPos = GetPosition(coords.xy);
- float2 offs = PixelSize.xy*1.0;
- float3 ddx1 = GetPosition(coords.xy + float2(offs.x, 0)) - centerPos;
- float3 ddx2 = centerPos - GetPosition(coords.xy + float2(-offs.x, 0));
- float3 ddy1 = GetPosition(coords.xy + float2(0, offs.y)) - centerPos;
- float3 ddy2 = centerPos - GetPosition(coords.xy + float2(0, -offs.y));
- ddx1 = lerp(ddx1, ddx2, abs(ddx1.z) > abs(ddx2.z));
- ddy1 = lerp(ddy1, ddy2, abs(ddy1.z) > abs(ddy2.z));
- float3 normal = cross(ddy1, ddx1);
- return normalize(normal);
- }
- float3 GetNormalFromColor(float2 coords, float2 offset, float scale, float sharpness)
- {
- const float3 lumCoeff = float3(0.299,0.587,0.114);
- float hpx = dot(tex2Dlod(SamplerColor, float4(coords + float2(offset.x,0.0),0,0)).xyz,lumCoeff) * scale;
- float hmx = dot(tex2Dlod(SamplerColor, float4(coords - float2(offset.x,0.0),0,0)).xyz,lumCoeff) * scale;
- float hpy = dot(tex2Dlod(SamplerColor, float4(coords + float2(0.0,offset.y),0,0)).xyz,lumCoeff) * scale;
- float hmy = dot(tex2Dlod(SamplerColor, float4(coords - float2(0.0,offset.y),0,0)).xyz,lumCoeff) * scale;
- float dpx = GetLinearDepth(coords + float2(offset.x,0.0));
- float dmx = GetLinearDepth(coords - float2(offset.x,0.0));
- float dpy = GetLinearDepth(coords + float2(0.0,offset.y));
- float dmy = GetLinearDepth(coords - float2(0.0,offset.y));
- float2 xymult = float2(abs(dmx - dpx), abs(dmy - dpy)) * sharpness;
- xymult = max(0.0, 1.0 - xymult);
- float ddx = (hmx - hpx) / (2.0 * offset.x) * xymult.x;
- float ddy = (hmy - hpy) / (2.0 * offset.y) * xymult.y;
- return normalize(float3(ddx, ddy, 1.0));
- }
- float3 GetBlendedNormals(float3 n1, float3 n2)
- {
- //return normalize(float3(n1.xy*n2.z + n2.xy*n1.z, n1.z*n2.z));
- n1 += float3( 0, 0, 1);
- n2 *= float3(-1, -1, 1);
- return n1*dot(n1, n2)/n1.z - n2;
- }
- float4 GetBlurFactors(float2 coords)
- {
- return float4(tex2Dlod(SamplerNormal, float4(coords.xy,0,0)).xyz*2.0-1.0,GetLinearDepth(coords.xy));
- }
- float GetBlurWeight(float O, float4 z, float4 z0)
- {
- //GFSDK with my normal angle consideration
- const float BlurSigma = fMXAOBlurSteps+1.0;
- const float BlurFalloff = 1.0 / (2.0*BlurSigma*BlurSigma);
- float BlurFresnelFactor = saturate(min(-z0.z,-z.z));
- //we don't need any sigma etc for normals, angle is important
- float DeltaN = (1.0 + dot(-z.xyz,z0.xyz))*100.0*fMXAOBlurSharpness;
- float DeltaZ = (z.w-z0.w)*1000.0*BlurFresnelFactor*fMXAOBlurSharpness;
- return exp2(-O*O*BlurFalloff - DeltaZ*DeltaZ - DeltaN*DeltaN);
- }
- float GetBayerFromCoordLevel(float2 pixelpos, int maxLevel)
- {
- float finalBayer = 0.0;
- for(float i = 1-maxLevel; i<= 0; i++)
- {
- float bayerSize = exp2(i);
- float2 bayerCoord = floor(pixelpos * bayerSize) % 2.0;
- float bayer = 2.0 * bayerCoord.x - 4.0 * bayerCoord.x * bayerCoord.y + 3.0 * bayerCoord.y;
- finalBayer += exp2(2.0*(i+maxLevel))* bayer;
- }
- float finalDivisor = exp2(2.0 * maxLevel + 2.0)- 4.0;
- return finalBayer/ finalDivisor;
- }
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- //
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- void PS_AO_Pre(float4 vpos : SV_Position, float2 texcoord : TEXCOORD, out float4 color : SV_Target0, out float4 depth : SV_Target1, out float4 normal : SV_Target2)
- {
- color = tex2D(SamplerColor, texcoord.xy);
- depth = GetLinearDepth(texcoord.xy)*RESHADE_DEPTH_LINEARIZATION_FAR_PLANE;
- normal.xyz = GetNormalFromDepth(texcoord.xy).xyz;
- #if(bMXAOPerPixelNormalsEnable != 0)
- float3 ppnormal = GetNormalFromColor(texcoord.xy, 70.0 * PixelSize.xy / depth.x, 0.005, 1000.0);
- normal.xyz = GetBlendedNormals(normal.xyz,ppnormal.xyz);
- #endif
- normal.xyz = normal.xyz * 0.5 + 0.5;
- normal.w = GetBayerFromCoordLevel(vpos.xy,iMXAOBayerDitherLevel);
- }
- void PS_AO_Gen(float4 vpos : SV_Position, float2 texcoord : TEXCOORD, out float4 res : SV_Target0)
- {
- float4 normalSample = tex2D(SamplerNormal, texcoord.xy);
- float3 ScreenSpaceNormals = normalSample.xyz * 2.0 - 1.0;
- float3 ScreenSpacePosition = GetPositionLOD(texcoord.xy, 0);
- float scenedepth = ScreenSpacePosition.z / RESHADE_DEPTH_LINEARIZATION_FAR_PLANE;
- ScreenSpacePosition += ScreenSpaceNormals * scenedepth;
- #if(bMXAOSmartSamplingEnable != 0)
- float numSamples = lerp(iMXAOSampleCount,12,scenedepth / AO_FADE____END);
- #else
- float numSamples = iMXAOSampleCount;
- #endif
- float SampleRadiusScaled = fMXAOSampleRadius / (numSamples * ScreenSpacePosition.z * 0.625);
- float rotAngle = normalSample.w;
- float mipFactor = SampleRadiusScaled * numSamples * 19.7392088;
- float2 currentVector;
- sincos(6.283*rotAngle, currentVector.y, currentVector.x);
- currentVector *= SampleRadiusScaled;
- static const float fNegInvR2 = -1.0/(fMXAOSampleRadius*fMXAOSampleRadius);
- static const float Aspect = PixelSize.y/PixelSize.x;
- res = 0.0;
- [loop]
- for (int iSample=1; iSample <= numSamples; iSample++)
- {
- currentVector = mul(currentVector.xy, float2x2(0.575,0.81815,-0.81815,0.575));
- float2 currentOffset = texcoord.xy + currentVector.xy * iSample;
- #if(bMXAOBoundaryCheckEnable != 0)
- [branch]
- if(all(saturate(-currentOffset * currentOffset + currentOffset)))
- {
- #endif
- float mipLevel = clamp((int)floor(log2(mipFactor*iSample)) - 3, fMXAOMipLevelAO, 5);
- float3 occlVec = -ScreenSpacePosition + GetPositionLOD(currentOffset.xy, mipLevel);
- occlVec.x *= Aspect;
- float occlDistanceRcp = rsqrt(dot(occlVec,occlVec));
- float SurfaceAngle = dot(occlVec, ScreenSpaceNormals)*occlDistanceRcp;
- float fAO = saturate(1.0 + fNegInvR2/occlDistanceRcp) * saturate(SurfaceAngle - fMXAONormalBias);
- #if(bMXAOIndirectLightingEnable != 0)
- float3 fIL = tex2Dlod(SamplerLOD, float4(currentOffset,0,mipLevel + fMXAOMipLevelIL)).xyz;
- #if(bMXAOBackfaceCheckEnable != 0)
- float3 offsetNormals = tex2Dlod(SamplerNormal, float4(currentOffset,0,mipLevel + fMXAOMipLevelIL)).xyz * 2.0 - 1.0;
- float facingtoSource = dot(-occlVec,offsetNormals)*occlDistanceRcp;
- fIL *=smoothstep(-0.5,0.0,facingtoSource);
- #endif
- res.w += fAO*saturate(1-dot(fIL,float3(0.299,0.587,0.114)));
- res.xyz += fIL*fAO;
- #else
- res.w += fAO;
- #endif
- #if(bMXAOBoundaryCheckEnable != 0)
- }
- #endif
- }
- res = (AO_FADE____END < scenedepth) ? 0.0 : res / (0.05 * (1.0-fMXAONormalBias)*numSamples*fMXAOSampleRadius);
- }
- void PS_AO_Blur1(float4 vpos : SV_Position, float2 texcoord : TEXCOORD, out float4 res : SV_Target0)
- {
- //discrete sampling, I could either make this one *1.0 and in the loop every sample * 2.0
- //or do it like this and save that multiplication inside the loop.
- float4 total_ao = tex2D(SamplerSSAO, texcoord.xy) * 0.5;
- float total_weight = 0.5;
- float4 center_factor = GetBlurFactors(texcoord.xy);
- [unroll]
- for(float x = 1.0; x <= fMXAOBlurSteps; x++)
- {
- float2 blurdir = float2(2.0 * x - 0.5,0.0);
- float2 blurcoord = blurdir * PixelSize.xy + texcoord.xy;
- float4 temp_ao = tex2Dlod(SamplerSSAO, float4(blurcoord,0,0));
- float4 temp_factor = GetBlurFactors(blurcoord);
- float temp_weight = GetBlurWeight(blurdir.x, temp_factor, center_factor);
- total_ao += temp_ao * temp_weight;
- total_weight += temp_weight;
- blurcoord = -blurdir * PixelSize.xy + texcoord.xy;
- temp_ao = tex2Dlod(SamplerSSAO, float4(blurcoord,0,0));
- temp_factor = GetBlurFactors(blurcoord);
- temp_weight = GetBlurWeight(blurdir.x, temp_factor, center_factor);
- total_ao += temp_ao * temp_weight;
- total_weight += temp_weight;
- }
- total_ao /= total_weight;
- res = total_ao;
- }
- void PS_AO_Blur2(float4 vpos : SV_Position, float2 texcoord : TEXCOORD, out float4 res : SV_Target0)
- {
- float4 total_ao = tex2D(SamplerColor, texcoord.xy) * 0.5;
- float total_weight = 0.5;
- float4 center_factor = GetBlurFactors(texcoord.xy);
- [unroll]
- for(float y = 1.0; y <= fMXAOBlurSteps; y++)
- {
- float2 blurdir = float2(0.0, 2.0 * y - 0.5);
- float2 blurcoord = blurdir * PixelSize.xy + texcoord.xy;
- float4 temp_ao = tex2Dlod(SamplerColor, float4(blurcoord,0,0));
- float4 temp_factor = GetBlurFactors(blurcoord);
- float temp_weight = GetBlurWeight(blurdir.y, temp_factor, center_factor);
- total_ao += temp_ao * temp_weight;
- total_weight += temp_weight;
- blurcoord = -blurdir * PixelSize.xy + texcoord.xy;
- temp_ao = tex2Dlod(SamplerColor, float4(blurcoord,0,0));
- temp_factor = GetBlurFactors(blurcoord);
- temp_weight = GetBlurWeight(blurdir.y, temp_factor, center_factor);
- total_ao += temp_ao * temp_weight;
- total_weight += temp_weight;
- }
- total_ao /= total_weight;
- float4 mxao = saturate(total_ao);
- float scenedepth = GetLinearDepth(texcoord.xy); //might change center_factor so better fetch depth directly here.
- float4 color = max(0.0,tex2Dlod(SamplerLOD, float4(texcoord.xy,0,0))); //get miplevel 0 which was shifted prior in MipLODBias.
- float colorgray = dot(color.xyz,float3(0.299,0.587,0.114));
- mxao.xyz = lerp(dot(mxao.xyz,float3(0.299,0.587,0.114)),mxao.xyz,fMXAOIndirectLightingSaturation) * fMXAOIndirectLightingAmount;
- mxao.w = 1.0-pow(1.0-mxao.w, fMXAOAmbientOcclusionAmount * 2.0);
- #if(bMXAODebugViewEnable == 0)
- mxao = lerp(mxao, 0.0, pow(colorgray,2.0));
- #endif
- mxao.w = lerp(mxao.w, 0.0,smoothstep(AO_FADE____START, AO_FADE____END, scenedepth)); //AO FADEOUT
- mxao.xyz = lerp(mxao.xyz,0.0,smoothstep(AO_FADE____START*0.5, AO_FADE____END*0.5, scenedepth)); //AO FADEOUT //IL can look really bad on far objects.
- float3 GI = mxao.w - mxao.xyz*2;
- GI = max(0.0,1-GI);
- color.xyz *= GI;
- color.xyz += mxao.xyz * 0.05; //pitch black surfaces.
- #if(bMXAODebugViewEnable != 0)
- #if(bMXAOIndirectLightingEnable != 0)
- color.xyz = GI*0.5;
- #else
- color.xyz = GI;
- #endif
- #endif
- res = color;
- }
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- //
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- technique PostProcess < bool enabled = 1;toggle = MXAO_TOGGLEKEY;>
- {
- pass P0
- {
- VertexShader = VS_PostProcess;
- PixelShader = PS_AO_Pre;
- RenderTarget0 = texLOD;
- RenderTarget1 = texDepthLOD;
- RenderTarget2 = texNormal;
- }
- pass P1
- {
- VertexShader = VS_PostProcess;
- PixelShader = PS_AO_Gen;
- RenderTarget = texSSAO;
- }
- pass P2_0
- {
- VertexShader = VS_PostProcess;
- PixelShader = PS_AO_Blur1;
- }
- pass P2
- {
- VertexShader = VS_PostProcess;
- PixelShader = PS_AO_Blur2;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement