// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. /*============================================================================= PostProcessDownsample.usf: PostProcessing down sample. =============================================================================*/ #include "Common.usf" #include "PostProcessCommon.usf" // vertex shader entry point void MainDownsampleVS( in float4 InPosition : ATTRIBUTE0, in float2 UV : ATTRIBUTE1, out noperspective float2 OutUV : TEXCOORD0, out float4 OutPosition : SV_POSITION ) { DrawRectangle(InPosition, UV, OutPosition, OutUV); } float4 DownsampleCommon(in float2 InUV, in float2 Offset) { float4 OutColor; #if METHOD == 0 // Output: low quality, 1 filtered sample OutColor = Texture2DSampleLevel(PostprocessInput0, PostprocessInput0Sampler, InUV, 0); #elif METHOD == 1 // Output: float4(RGBA), 4 filtered samples float2 UV[4]; // blur during downsample (4x4 kernel) to get better quality especially for HDR content, can be made an option of this shader UV[0] = InUV + Offset * float2(-1, -1); UV[1] = InUV + Offset * float2( 1, -1); UV[2] = InUV + Offset * float2(-1, 1); UV[3] = InUV + Offset * float2( 1, 1); float4 Sample[4]; UNROLL for(uint i = 0; i < 4; ++i) { Sample[i] = Texture2DSampleLevel(PostprocessInput0, PostprocessInput0Sampler, UV[i], 0); } OutColor = (Sample[0] + Sample[1] + Sample[2] + Sample[3]) * 0.25f; // fixed rarely occuring yellow color tint of the whole viewport (certain view port size, need to investigate more) OutColor.rgb = max(float3(0,0,0), OutColor.rgb); #else // Output: float4(RGB,depth), 4 unfiltered samples (no leaking) float2 UV[4]; // no filtering (2x2 kernel) to get no leaking in Depth of Field UV[0] = InUV + Offset * float2(-1, -1); UV[1] = InUV + Offset * float2( 1, -1); UV[2] = InUV + Offset * float2(-1, 1); UV[3] = InUV + Offset * float2( 1, 1); float3 Sample[4]; UNROLL for(uint i = 0; i < 4; ++i) { Sample[i] = Texture2DSampleLevel(PostprocessInput0, PostprocessInput0Sampler, UV[i], 0).rgb; } // todo: this still leaks as we need to mask in focus pixels OutColor = float4((Sample[0] + Sample[1] + Sample[2] + Sample[3]) * 0.25f, CalcSceneDepth(UV[0])); #endif return OutColor; } // xy: UV offset, zw:unused float4 DownsampleParams; // pixel shader entry point void MainPS(noperspective float2 InUV : TEXCOORD0, out float4 OutColor : SV_Target0) { float2 Offset = DownsampleParams.xy; OutColor = DownsampleCommon(InUV, Offset); } #if COMPUTESHADER // xy: UVOffset, zw: ThreadToUVScale float4 DownsampleComputeParams; RWTexture2D OutComputeTex; [numthreads(THREADGROUP_SIZEX, THREADGROUP_SIZEY, 1)] void MainCS(uint2 DispatchThreadId : SV_DispatchThreadID) { float2 InUV = ((float2)DispatchThreadId + View.ViewRectMin.xy + 0.5f) * DownsampleComputeParams.zw; float2 Offset = DownsampleComputeParams.xy; if (IsComputeUVOutOfBounds(InUV)) { return; } float4 OutColor = DownsampleCommon(InUV, Offset); uint2 PixelPos = DispatchThreadId + (uint2)View.ViewRectMin.xy; OutComputeTex[PixelPos] = OutColor; } #endif