/* ======================================================================== Copyright (c) Afzaal. All rights reserved. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ======================================================================== GitHub : https://github.com/umar-afzaal/LumeniteFX Discord : https://discord.gg/deXJrW2dx6 Filename : lumenite_TRAA.fx Version : 2026.07.28 Author : Afzaal (Kaidō) Description: Temporal Reprojection Anti-Aliasing License : AGNYA License (https://github.com/nvb-uy/AGNYA-License) ======================================================================== */ /*------------------. | :: DEFINITIONS :: | '------------------*/ #ifndef ENABLE_DLAA #define ENABLE_DLAA 1 #endif /*--------------. | :: HEADERS :: | '--------------*/ #include "ReShade.fxh" #include "./include/lumenite_ColorManagement.fxh" #include "./include/lumenite_Helpers.fxh" /*---------------. | :: UNIFORMS :: | '---------------*/ uniform int SHOW_STATUS < ui_type = "radio"; ui_label = " "; #if ENABLE_DLAA ui_text = "DLAA Prepass: Enabled."; #else ui_text = "DLAA Prepass: Disabled."; #endif >; #if ENABLE_DLAA uniform bool DEBUG_EDGES < ui_label = "Show Edge Mask"; ui_tooltip = "Paints the detected edge mask over black background."; > = false; uniform int EDGE_MODE < ui_type = "combo"; ui_label = "Edge Detection"; ui_items = "Luma\0Geometric\0"; ui_tooltip = "Luma: shading and texture edges as well; the classic DLAA mask.\n" "Geometric: silhouettes only, ignores flat UI."; > = 0; #endif uniform float HISTORY_BLEND < ui_type = "slider"; ui_min = 0.0; ui_max = 1.0; ui_step = 0.01; ui_label = "Temporal Blend"; hidden = false; > = 0.9; uniform float SHARP_STRENGTH < ui_type = "drag"; ui_min = 0; ui_max = 2.0; ui_step = 0.05; ui_label = "Adaptive Sharpen"; hidden = false; > = 1.0; uniform float MAX_SHARP_DIFF < ui_type = "drag"; ui_min = 0.05; ui_max = 0.25; ui_step = 0.01; ui_label = "Sharpen Guard"; ui_tooltip = "Higher = more aggressive sharpening allowed.\nLower = tighter anti-ringing clamp."; hidden = true; > = 0.1; uniform float HFI_INTENSITY < ui_type = "drag"; ui_min = 0.0; ui_max = 0.1; ui_step = 0.001; ui_label = "High-Frequency Injection"; ui_tooltip = "Re-injects detail lost during Temporal blend."; > = 0.01; /*--------------. | :: IMPORTS :: | '--------------*/ namespace Kernel { texture2D tFlow { Width = BUFFER_WIDTH/8; Height = BUFFER_HEIGHT/8; Format = RG16F; }; sampler2D sFlow { Texture = tFlow; MagFilter = POINT; MinFilter = POINT; }; texture2D tConfidence { Width = BUFFER_WIDTH/8; Height = BUFFER_HEIGHT/8; Format = R16F; }; sampler2D sConfidence { Texture = tConfidence; }; texture tNormals { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; MipLevels = 4; }; sampler sNormals { Texture = tNormals; }; texture2D tDepth { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = R16F; MipLevels = 4; }; sampler2D sDepth { Texture = tDepth; }; } namespace LumeniteTRAA { /*---------------------. | :: RENDER TARGETS :: | '---------------------*/ #if ENABLE_DLAA texture tDLAAPreFilter { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; }; sampler sDLAAPreFilter { Texture = tDLAAPreFilter; MinFilter = LINEAR; MagFilter = LINEAR; MipFilter = LINEAR; }; texture tDLAAPrePass { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; }; sampler sDLAAPrePass { Texture = tDLAAPrePass; MagFilter = POINT; MinFilter = POINT; }; #endif texture tCurrHistory { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; }; sampler sCurrHistory { Texture = tCurrHistory; MagFilter = LINEAR; MinFilter = LINEAR; MipFilter = LINEAR; }; texture tPrevHistory { Width = BUFFER_WIDTH; Height = BUFFER_HEIGHT; Format = RGBA16F; }; sampler sPrevHistory { Texture = tPrevHistory; MagFilter = LINEAR; MinFilter = LINEAR; MipFilter = LINEAR; }; /*--------------. | :: HELPERS :: | '--------------*/ //5-Tap 2D Catmull-Rom Filter (Brian Karis / Unreal Engine) float3 SampleCatmullRom5Tap(sampler tex, float2 uv) { float2 pos = uv * float2(BUFFER_WIDTH, BUFFER_HEIGHT); float2 centerPos = floor(pos - 0.5) + 0.5; float2 f = pos - centerPos; //1D Catmull-Rom weights float2 f2 = f * f; float2 f3 = f2 * f; float2 w0 = f * (-0.5 + f * (1.0 - 0.5 * f)); float2 w1 = 1.0 + f2 * (-2.5 + 1.5 * f); float2 w2 = f * (0.5 + f * (2.0 - 1.5 * f)); float2 w3 = f2 * (-0.5 + 0.5 * f); //group the inner positive lobes (w1, w2) for bilinear hardware float2 w12 = w1 + w2; float2 offset12 = w2 / (w12 + 0.00001); // Prevent div by zero //5-tap texture fetch in a cross pattern float2 texCoord0 = (centerPos - float2(1.0, 0.0) + float2(0.0, offset12.y)) * BUFFER_PIXEL_SIZE; //left float2 texCoord1 = (centerPos + float2(2.0, 0.0) + float2(0.0, offset12.y)) * BUFFER_PIXEL_SIZE; //right float2 texCoord2 = (centerPos + float2(offset12.x, -1.0)) * BUFFER_PIXEL_SIZE; //top float2 texCoord3 = (centerPos + float2(offset12.x, 2.0)) * BUFFER_PIXEL_SIZE; //bottom float2 texCoord4 = (centerPos + offset12) * BUFFER_PIXEL_SIZE; //center //final 2D weights for the 5 taps float weight0 = w0.x * w12.y; //left float weight1 = w3.x * w12.y; //right float weight2 = w12.x * w0.y; //top float weight3 = w12.x * w3.y; //bottom float weight4 = w12.x * w12.y; //center //normalize weights because we dropped the 4 corner taps (sum would be slightly < 1.0) float weightSum = weight0 + weight1 + weight2 + weight3 + weight4; weightSum = max(weightSum, 0.0001); weight0 /= weightSum; weight1 /= weightSum; weight2 /= weightSum; weight3 /= weightSum; weight4 /= weightSum; //sample w. hw bilinear filtering (offsets take care of the interpolation) float3 color0 = tex2Dlod(tex, float4(texCoord0, 0, 0)).rgb; float3 color1 = tex2Dlod(tex, float4(texCoord1, 0, 0)).rgb; float3 color2 = tex2Dlod(tex, float4(texCoord2, 0, 0)).rgb; float3 color3 = tex2Dlod(tex, float4(texCoord3, 0, 0)).rgb; float3 color4 = tex2Dlod(tex, float4(texCoord4, 0, 0)).rgb; float3 result = color0 * weight0 + color1 * weight1 + color2 * weight2 + color3 * weight3 + color4 * weight4; //anti-ringing clamp float3 minColor = min(min(min(color0, color1), min(color2, color3)), color4); float3 maxColor = max(max(max(color0, color1), max(color2, color3)), color4); return clamp(result, minColor, maxColor); } //if ray misses the bounding box (tEnter > tExit), returning t = 1.0 is the safe fallback float3 YCoCgLineBoxClip(float3 historyYCoCg, float3 meanYCoCg, float3 colorMin, float3 colorMax) { float3 rayDir = meanYCoCg - historyYCoCg; rayDir = abs(rayDir) < 0.0001 ? float3(0.0001, 0.0001, 0.0001) : rayDir; //avoid div by zero //compute t for intersection with min and max bounds per-channel float3 tMin = (colorMin - historyYCoCg) / rayDir; float3 tMax = (colorMax - historyYCoCg) / rayDir; float3 t1 = min(tMin, tMax); float3 t2 = max(tMin, tMax); tMin = t1; tMax = t2; //entry and exit points for ray-box intersection float tEnter = max(max(tMin.x, tMin.y), tMin.z); float tExit = min(min(tMax.x, tMax.y), tMax.z); //if ray misses the box; fallback to 1.0 (mean) to discard history //else, clamp the entry point to [0, 1] to clip exactly at the box edge float t = tEnter > tExit ? 1.0 : clamp(tEnter, 0.0, 1.0); return historyYCoCg + rayDir * t; } /*--------------. | :: SHADERS :: | '--------------*/ #if ENABLE_DLAA float4 PS_DLAAPreFilter(float4 vpos : SV_Position, float2 uv : TexCoord) : SV_Target { float3 center = sqrt(max(GetLinearColor(uv, false), 0.0)); float edge; if (!EDGE_MODE) { //luma edge in perceptual space; the extra sqrt fattens the mask float2 px = float2(BUFFER_PIXEL_SIZE.x, 0.0); float2 py = float2(0.0, BUFFER_PIXEL_SIZE.y); float3 left = sqrt(max(GetLinearColor(uv - px, false), 0.0)); float3 right = sqrt(max(GetLinearColor(uv + px, false), 0.0)); float3 top = sqrt(max(GetLinearColor(uv - py, false), 0.0)); float3 bottom = sqrt(max(GetLinearColor(uv + py, false), 0.0)); float3 edges = 4.0 * abs((left + right + top + bottom) - 4.0 * center); edge = GetLuminance(sqrt(max(edges, 0.0))); //recursive gamma compression: do another sqrt(), fattens the edge mask } else { float4 s0 = tex2Dlod(Kernel::sNormals, float4(uv + BUFFER_PIXEL_SIZE * float2(-1,-1), 0, 0)); float4 s1 = tex2Dlod(Kernel::sNormals, float4(uv + BUFFER_PIXEL_SIZE * float2( 0,-1), 0, 0)); float4 s2 = tex2Dlod(Kernel::sNormals, float4(uv + BUFFER_PIXEL_SIZE * float2( 1,-1), 0, 0)); float4 s3 = tex2Dlod(Kernel::sNormals, float4(uv + BUFFER_PIXEL_SIZE * float2(-1, 0), 0, 0)); float4 s4 = tex2Dlod(Kernel::sNormals, float4(uv, 0, 0)); float4 s5 = tex2Dlod(Kernel::sNormals, float4(uv + BUFFER_PIXEL_SIZE * float2( 1, 0), 0, 0)); float4 s6 = tex2Dlod(Kernel::sNormals, float4(uv + BUFFER_PIXEL_SIZE * float2(-1, 1), 0, 0)); float4 s7 = tex2Dlod(Kernel::sNormals, float4(uv + BUFFER_PIXEL_SIZE * float2( 0, 1), 0, 0)); float4 s8 = tex2Dlod(Kernel::sNormals, float4(uv + BUFFER_PIXEL_SIZE * float2( 1, 1), 0, 0)); //3x3 depth Sobel float dC = s4.a; float sxD = -s0.a + s2.a - 2.0 * s3.a + 2.0 * s5.a - s6.a + s8.a; float syD = -s0.a - 2.0 * s1.a - s2.a + s6.a + 2.0 * s7.a + s8.a; float depthEdge = saturate(sqrt(sxD * sxD + syD * syD) / (dC + 1e-5)); //3x3 normal Sobel float3 sxN = -s0.xyz + s2.xyz - 2.0 * s3.xyz + 2.0 * s5.xyz - s6.xyz + s8.xyz; float3 syN = -s0.xyz - 2.0 * s1.xyz - s2.xyz + s6.xyz + 2.0 * s7.xyz + s8.xyz; float normalEdge = saturate(length(sxN) + length(syN)); edge = max(depthEdge, normalEdge); } return float4(center, edge); } #define SAMPLE_G(uv, dx, dy) tex2Dlod(sDLAAPreFilter, float4((uv) + float2(dx, dy) * BUFFER_PIXEL_SIZE, 0, 0)) float4 PS_DLAA(float4 vpos : SV_Position, float2 uv : TexCoord) : SV_Target { float4 center = SAMPLE_G(uv, 0.0, 0.0); float4 left01 = SAMPLE_G(uv, -1.5, 0.0); float4 right01 = SAMPLE_G(uv, 1.5, 0.0); float4 top01 = SAMPLE_G(uv, 0.0, -1.5); float4 bottom01 = SAMPLE_G(uv, 0.0, 1.5); //flat-region early exit float localEdges = max(center.a, max(max(left01.a, right01.a), max(top01.a, bottom01.a))); if (localEdges < 0.05) return float4(center.xyz * center.xyz, 1.0); float4 wH = 2.0 * (left01 + right01); float4 wV = 2.0 * (top01 + bottom01); float4 edgeH = abs(wH - 4.0 * center) / 4.0; float4 edgeV = abs(wV - 4.0 * center) / 4.0; float4 blurredH = (wH + 2.0 * center) / 6.0; float4 blurredV = (wV + 2.0 * center) / 6.0; float edgeHLum = GetLuminance(edgeH.xyz); float edgeVLum = GetLuminance(edgeV.xyz); float blurredHLum = GetLuminance(blurredH.xyz); float blurredVLum = GetLuminance(blurredV.xyz); const float kLambda = 3.0; const float kEpsilon = 0.1; float edgeMaskH = saturate((kLambda * edgeHLum - kEpsilon) / (blurredVLum + 1e-5)); float edgeMaskV = saturate((kLambda * edgeVLum - kEpsilon) / (blurredHLum + 1e-5)); float gate = (!EDGE_MODE) ? 1.0 : center.a; edgeMaskH *= gate; edgeMaskV *= gate; float4 clr = center; clr = lerp(clr, blurredH, edgeMaskV); clr = lerp(clr, blurredV, edgeMaskH * 0.5); //skip unnecessary work on long-edges if (localEdges > 0.5) { float4 h0 = right01; float4 h1 = SAMPLE_G(uv, 3.5, 0.0); float4 h2 = SAMPLE_G(uv, 5.5, 0.0); float4 h3 = SAMPLE_G(uv, 7.5, 0.0); float4 h4 = left01; float4 h5 = SAMPLE_G(uv, -3.5, 0.0); float4 h6 = SAMPLE_G(uv, -5.5, 0.0); float4 h7 = SAMPLE_G(uv, -7.5, 0.0); float4 v0 = bottom01; float4 v1 = SAMPLE_G(uv, 0.0, 3.5); float4 v2 = SAMPLE_G(uv, 0.0, 5.5); float4 v3 = SAMPLE_G(uv, 0.0, 7.5); float4 v4 = top01; float4 v5 = SAMPLE_G(uv, 0.0, -3.5); float4 v6 = SAMPLE_G(uv, 0.0, -5.5); float4 v7 = SAMPLE_G(uv, 0.0, -7.5); float longEdgeMaskH = (h0.a + h1.a + h2.a + h3.a + h4.a + h5.a + h6.a + h7.a) / 8.0; float longEdgeMaskV = (v0.a + v1.a + v2.a + v3.a + v4.a + v5.a + v6.a + v7.a) / 8.0; longEdgeMaskH = saturate(longEdgeMaskH * 2.0 - 1.0); longEdgeMaskV = saturate(longEdgeMaskV * 2.0 - 1.0); if (abs(longEdgeMaskH - longEdgeMaskV) > 0.2) { float4 left = SAMPLE_G(uv, -1.0, 0.0); float4 right = SAMPLE_G(uv, 1.0, 0.0); float4 top = SAMPLE_G(uv, 0.0, -1.0); float4 bottom = SAMPLE_G(uv, 0.0, 1.0); float4 longBlurredH = (h0 + h1 + h2 + h3 + h4 + h5 + h6 + h7) / 8.0; float4 longBlurredV = (v0 + v1 + v2 + v3 + v4 + v5 + v6 + v7) / 8.0; float lbHLum = GetLuminance(longBlurredH.xyz); float lbVLum = GetLuminance(longBlurredV.xyz); float centerLum = GetLuminance(center.xyz); float leftLum = GetLuminance(left.xyz); float rightLum = GetLuminance(right.xyz); float topLum = GetLuminance(top.xyz); float bottomLum = GetLuminance(bottom.xyz); float4 clrV = center; float4 clrH = center; float hx = saturate(0.0 + (lbHLum - topLum) / (centerLum - topLum + 1e-6)); float hy = saturate(1.0 + (lbHLum - centerLum) / (centerLum - bottomLum + 1e-6)); float vx = saturate(0.0 + (lbVLum - leftLum) / (centerLum - leftLum + 1e-6)); float vy = saturate(1.0 + (lbVLum - centerLum) / (centerLum - rightLum + 1e-6)); float4 vhxy = float4(vx, vy, hx, hy); vhxy.x = (vhxy.x == 0.0) ? 1.0 : vhxy.x; vhxy.y = (vhxy.y == 0.0) ? 1.0 : vhxy.y; vhxy.z = (vhxy.z == 0.0) ? 1.0 : vhxy.z; vhxy.w = (vhxy.w == 0.0) ? 1.0 : vhxy.w; clrV = lerp(left, clrV, vhxy.x); clrV = lerp(right, clrV, vhxy.y); clrH = lerp(top, clrH, vhxy.z); clrH = lerp(bottom, clrH, vhxy.w); clr = lerp(clr, clrV, longEdgeMaskV); clr = lerp(clr, clrH, longEdgeMaskH); } } //highlight protection float4 r0 = SAMPLE_G(uv, -1.5, -1.5); float4 r1 = SAMPLE_G(uv, 1.5, -1.5); float4 r2 = SAMPLE_G(uv, -1.5, 1.5); float4 r3 = SAMPLE_G(uv, 1.5, 1.5); float4 r = (4.0 * (r0 + r1 + r2 + r3) + center + top01 + bottom01 + left01 + right01) / 25.0; float mask = saturate(r.a * 3.0 - 2.0); clr = lerp(clr, center, mask); return float4(clr.xyz * clr.xyz, 1.0); //store linear color here! } #endif float4 PS_TRAA(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target { //3x3 neighborhood from DLAA prepass static const float2 offsets[9] = { float2(-1, -1), float2(0, -1), float2(1, -1), float2(-1, 0) , float2(0, 0) , float2(1, 0), float2(-1, 1) , float2(0, 1) , float2(1, 1) }; float3 samples[9]; float3 samplesYCoCg[9]; float3 meanYCoCg = float3(0, 0, 0); for (int i = 0; i < 9; i++) { float2 samplePos = texcoord + BUFFER_PIXEL_SIZE * offsets[i]; #if ENABLE_DLAA samples[i] = tex2Dlod(sDLAAPrePass, float4(samplePos, 0, 0)).rgb; #else samples[i] = GetLinearColor(samplePos, false); #endif samplesYCoCg[i] = linearToYCoCg(samples[i]); meanYCoCg += samplesYCoCg[i]; } meanYCoCg /= 9.0; //standard deviation per channel float3 stddev = float3(0, 0, 0); for (int i = 0; i < 9; i++) { float3 diff = samplesYCoCg[i] - meanYCoCg; stddev += diff * diff; } stddev = sqrt(stddev / 9.0); //variance-scaled bounding box in YCoCg float3 colorMin = meanYCoCg - stddev * 1.25; float3 colorMax = meanYCoCg + stddev * 1.25; float2 flow = tex2D(Kernel::sFlow, texcoord).xy; float confidence = tex2D(Kernel::sConfidence, texcoord).x; confidence = saturate(confidence + 0.11 * 4.0 * confidence * (1.0 - confidence)); float2 historyUV = texcoord + flow; historyUV = clamp(historyUV, BUFFER_PIXEL_SIZE, 1.0 - BUFFER_PIXEL_SIZE); float3 historyRGB = SampleCatmullRom5Tap(sPrevHistory, historyUV); float3 historyYCoCg = linearToYCoCg(historyRGB); //clip history to current neighborhood bounds via line-box intersection float3 clippedHistoryYCoCg = YCoCgLineBoxClip(historyYCoCg, meanYCoCg, colorMin, colorMax); //re-inject current pixel's detail into clipped history float3 centerYCoCg = samplesYCoCg[4]; //blend against the center pixel (index 4 of the 3x3 grid) float3 injectedHistory = clippedHistoryYCoCg + (centerYCoCg - meanYCoCg) * HFI_INTENSITY; //blend clipped history with current in YCoCg space float blendVal = min(0.98, HISTORY_BLEND); float3 blendedYCoCg = lerp(centerYCoCg, injectedHistory, confidence * blendVal); float3 output = YCoCgToLinear(blendedYCoCg); return float4(output, 1.0); } float4 PS_ToDisplay(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target { #if ENABLE_DLAA if (DEBUG_EDGES) { float edgeDbg = tex2D(sDLAAPreFilter, texcoord).a; static const float3 edgeTint = float3(0.125, 0.698, 0.667) * float3(0.125, 0.698, 0.667); //target color squared so lands on the real hue return float4(ToOutputColorspace(edgeTint * saturate(edgeDbg), false), 1.0); } #endif float3 c = tex2D(sCurrHistory, texcoord).rgb; float3 sharpened = c; if (SHARP_STRENGTH > 0) { float2 off = BUFFER_PIXEL_SIZE * 0.5; float3 ne = tex2D(sCurrHistory, texcoord + float2( off.x, off.y)).rgb; float3 sw = tex2D(sCurrHistory, texcoord + float2(-off.x, -off.y)).rgb; float3 se = tex2D(sCurrHistory, texcoord + float2( off.x, -off.y)).rgb; float3 nw = tex2D(sCurrHistory, texcoord + float2(-off.x, off.y)).rgb; //bounds for the neighborhood float3 local_min = min(min(min(ne, nw), min(se, sw)), c); float3 local_max = max(max(max(ne, nw), max(se, sw)), c); //high-pass float3 diag_max = max(max(ne, nw), max(se, sw)); float3 diag_min = min(min(ne, nw), min(se, sw)); float3 diff_rgb = 2.0 * c + (ne + nw + se + sw) - 3.0 * (diag_max + diag_min); static const float3 luma_weight = float3(0.2126, 0.7152, 0.0722); float luma_c = dot(c, luma_weight); float luma_diff = dot(diff_rgb, luma_weight); //rational limit float max_allowed = MAX_SHARP_DIFF * (luma_c + 0.1); luma_diff = luma_diff / (rcp(SHARP_STRENGTH) + abs(luma_diff) / max(max_allowed, 0.001)); //lower epsilon (0.005) for more dark-area detail float ratio = (luma_c + luma_diff) / max(luma_c, 0.005); //allow up to 3x brightness for extreme highlights ratio = clamp(ratio, 0.3, 3.0); sharpened = c * ratio; //anti-ringing //instead of clamping strictly to min/max, we allow a 20% overshoot //perceived "sharpness" while capping fireflies float3 overshoot_min = local_min * 0.8; float3 overshoot_max = local_max * 1.2; sharpened = clamp(sharpened, overshoot_min, overshoot_max); } return float4(ToOutputColorspace(sharpened, false), 1.0); } float4 PS_StoreHistory(float4 vpos : SV_Position, float2 texcoord : TexCoord) : SV_Target { float3 taaResult = tex2D(sCurrHistory, texcoord).rgb; return float4(taaResult, 1.0); } /*----------------. | :: TECHNIQUE :: | '----------------*/ technique Lumenite_TRAA < ui_label = "LUMENITE: TRAA"; ui_tooltip = "Temporal Reprojection Anti-Aliasing."; > { #if ENABLE_DLAA pass { VertexShader = PostProcessVS; PixelShader = PS_DLAAPreFilter; RenderTarget = tDLAAPreFilter; } pass { VertexShader = PostProcessVS; PixelShader = PS_DLAA; RenderTarget = tDLAAPrePass; } //spatial filter #endif pass { VertexShader = PostProcessVS; PixelShader = PS_TRAA; RenderTarget = tCurrHistory; } //temporal filter pass { VertexShader = PostProcessVS; PixelShader = PS_ToDisplay; } pass { VertexShader = PostProcessVS; PixelShader = PS_StoreHistory; RenderTarget = tPrevHistory; } } }