You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
4.6 KiB
105 lines
4.6 KiB
// This file is part of the FidelityFX SDK.
|
|
//
|
|
// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// 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.
|
|
|
|
|
|
#include "../common/ffx_core.h"
|
|
#include "ffx_cacao_defines.h"
|
|
#include "ffx_cacao_utils.h"
|
|
|
|
void FFX_CACAO_Apply(FfxUInt32x2 coord)
|
|
{
|
|
FfxFloat32 ao;
|
|
FfxFloat32x2 inPos = coord;
|
|
FfxUInt32x2 pixPos = coord;
|
|
FfxUInt32x2 pixPosHalf = pixPos / FfxUInt32x2(2, 2);
|
|
|
|
// calculate index in the four deinterleaved source array texture
|
|
FfxInt32 mx = FfxInt32(pixPos.x % 2);
|
|
FfxInt32 my = FfxInt32(pixPos.y % 2);
|
|
FfxInt32 ic = mx + my * 2; // center index
|
|
FfxInt32 ih = (1 - mx) + my * 2; // neighbouring, horizontal
|
|
FfxInt32 iv = mx + (1 - my) * 2; // neighbouring, vertical
|
|
FfxInt32 id = (1 - mx) + (1 - my) * 2; // diagonal
|
|
|
|
FfxFloat32x2 centerVal = FFX_CACAO_Apply_LoadSSAOPass(FfxInt32x2(pixPosHalf), ic);
|
|
|
|
ao = centerVal.x;
|
|
|
|
#if 1 // change to 0 if you want to disable last pass high-res blur (for debugging purposes, etc.)
|
|
FfxFloat32x4 edgesLRTB = FFX_CACAO_UnpackEdges(centerVal.y);
|
|
|
|
// return 1.0 - FfxFloat32x4( edgesLRTB.x, edgesLRTB.y * 0.5 + edgesLRTB.w * 0.5, edgesLRTB.z, 0.0 ); // debug show edges
|
|
|
|
// convert index shifts to sampling offsets
|
|
FfxFloat32 fmx = FfxFloat32(mx);
|
|
FfxFloat32 fmy = FfxFloat32(my);
|
|
|
|
// in case of an edge, push sampling offsets away from the edge (towards pixel center)
|
|
FfxFloat32 fmxe = (edgesLRTB.y - edgesLRTB.x);
|
|
FfxFloat32 fmye = (edgesLRTB.w - edgesLRTB.z);
|
|
|
|
// calculate final sampling offsets and sample using bilinear filter
|
|
FfxFloat32x2 uvH = (inPos.xy + FfxFloat32x2(fmx + fmxe - 0.5, 0.5 - fmy)) * 0.5 * SSAOBufferInverseDimensions();
|
|
FfxFloat32 aoH = FFX_CACAO_Apply_SampleSSAOUVPass(uvH, ih);
|
|
FfxFloat32x2 uvV = (inPos.xy + FfxFloat32x2(0.5 - fmx, fmy - 0.5 + fmye)) * 0.5 * SSAOBufferInverseDimensions();
|
|
FfxFloat32 aoV = FFX_CACAO_Apply_SampleSSAOUVPass(uvV, iv);
|
|
FfxFloat32x2 uvD = (inPos.xy + FfxFloat32x2(fmx - 0.5 + fmxe, fmy - 0.5 + fmye)) * 0.5 * SSAOBufferInverseDimensions();
|
|
FfxFloat32 aoD = FFX_CACAO_Apply_SampleSSAOUVPass(uvD, id);
|
|
|
|
// reduce weight for samples near edge - if the edge is on both sides, weight goes to 0
|
|
FfxFloat32x4 blendWeights;
|
|
blendWeights.x = 1.0;
|
|
blendWeights.y = (edgesLRTB.x + edgesLRTB.y) * 0.5;
|
|
blendWeights.z = (edgesLRTB.z + edgesLRTB.w) * 0.5;
|
|
blendWeights.w = (blendWeights.y + blendWeights.z) * 0.5;
|
|
|
|
// calculate weighted average
|
|
FfxFloat32 blendWeightsSum = dot(blendWeights, FfxFloat32x4(1.0, 1.0, 1.0, 1.0));
|
|
ao = dot(FfxFloat32x4(ao, aoH, aoV, aoD), blendWeights) / blendWeightsSum;
|
|
#endif
|
|
ao.x = pow(ao.x, 2.2);
|
|
FFX_CACAO_Apply_StoreOutput(FfxInt32x2(coord), ao.x);
|
|
}
|
|
|
|
|
|
// edge-ignorant blur & apply (for the lowest quality level 0)
|
|
void FFX_CACAO_NonSmartApply(FfxUInt32x2 tid)
|
|
{
|
|
FfxFloat32x2 inUV = FfxFloat32x2(tid) * OutputBufferInverseDimensions();
|
|
FfxFloat32 a = FFX_CACAO_Apply_SampleSSAOUVPass(inUV.xy, 0);
|
|
FfxFloat32 b = FFX_CACAO_Apply_SampleSSAOUVPass(inUV.xy, 1);
|
|
FfxFloat32 c = FFX_CACAO_Apply_SampleSSAOUVPass(inUV.xy, 2);
|
|
FfxFloat32 d = FFX_CACAO_Apply_SampleSSAOUVPass(inUV.xy, 3);
|
|
FfxFloat32 avg = (a + b + c + d) * 0.25f;
|
|
|
|
FFX_CACAO_Apply_StoreOutput(FfxInt32x2(tid), avg);
|
|
}
|
|
|
|
// edge-ignorant blur & apply, skipping half pixels in checkerboard pattern (for the Lowest quality level 0 and Settings::SkipHalfPixelsOnLowQualityLevel == true )
|
|
void FFX_CACAO_NonSmartHalfApply(FfxUInt32x2 tid)
|
|
{
|
|
FfxFloat32x2 inUV = FfxFloat32x2(tid) * OutputBufferInverseDimensions();
|
|
FfxFloat32 a = FFX_CACAO_Apply_SampleSSAOUVPass(inUV.xy, 0);
|
|
FfxFloat32 d = FFX_CACAO_Apply_SampleSSAOUVPass(inUV.xy, 3);
|
|
FfxFloat32 avg = (a + d) * 0.5f;
|
|
|
|
FFX_CACAO_Apply_StoreOutput(FfxInt32x2(tid), avg);
|
|
}
|