264 lines
7.5 KiB
HLSL
264 lines
7.5 KiB
HLSL
// Copyright (C) 2020, Dmitry Maluev (dmaluev@gmail.com)
|
|
|
|
#include "Lib.hlsl"
|
|
#include "LibDeferredShading.hlsl"
|
|
#include "LibDepth.hlsl"
|
|
#include "Blur.inc.hlsl"
|
|
|
|
ConstantBuffer<UB_BlurVS> g_ubBlurVS : register(b0, space0);
|
|
ConstantBuffer<UB_BlurFS> g_ubBlurFS : register(b0, space1);
|
|
ConstantBuffer<UB_ExtraBlurFS> g_ubExtraBlurFS : register(b0, space2);
|
|
|
|
Texture2D g_tex : register(t1, space1);
|
|
SamplerState g_sam : register(s1, space1);
|
|
Texture2D g_texGBuffer1 : register(t1, space2);
|
|
SamplerState g_samGBuffer1 : register(s1, space2);
|
|
Texture2D g_texDepth : register(t2, space2);
|
|
SamplerState g_samDepth : register(s2, space2);
|
|
|
|
struct VSI
|
|
{
|
|
VK_LOCATION_POSITION float4 pos : POSITION;
|
|
};
|
|
|
|
struct VSO
|
|
{
|
|
float4 pos : SV_Position;
|
|
float2 tc0 : TEXCOORD0;
|
|
};
|
|
|
|
struct FSO
|
|
{
|
|
float4 color : SV_Target0;
|
|
};
|
|
|
|
#ifdef _VS
|
|
VSO mainVS(VSI si)
|
|
{
|
|
VSO so;
|
|
|
|
// Standard quad:
|
|
so.pos = float4(mul(si.pos, g_ubBlurVS._matW), 1);
|
|
so.tc0 = mul(si.pos, g_ubBlurVS._matV).xy;
|
|
|
|
return so;
|
|
}
|
|
#endif
|
|
|
|
#ifdef _FS
|
|
FSO mainFS(VSO si)
|
|
{
|
|
FSO so;
|
|
|
|
#if _ANISOTROPY_LEVEL > 4
|
|
const int stride = 2;
|
|
#else
|
|
const int stride = 4;
|
|
#endif
|
|
|
|
float4 acc = 0.0;
|
|
#ifdef DEF_SSAO
|
|
const float weightSum = 2.0;
|
|
[unroll] for (int i = -1; i <= 1; i += 2)
|
|
#else
|
|
float weightSum = _SINGULARITY_FIX;
|
|
[unroll] for (int i = -8; i <= 7; i += stride)
|
|
#endif
|
|
{
|
|
#ifdef DEF_VERTICAL
|
|
const int2 offset = int2(0, i);
|
|
#else
|
|
const int2 offset = int2(i, 0);
|
|
#endif
|
|
|
|
#ifdef DEF_SSAO
|
|
const float weight = 1.0;
|
|
#else
|
|
const float weight = smoothstep(0.0, 1.0, (1.0 - abs(i) * 0.1));
|
|
weightSum += weight;
|
|
#endif
|
|
|
|
#if defined(DEF_SSAO) && defined(DEF_VERTICAL) // Sampling from sRGB, use alpha channel:
|
|
acc += g_tex.SampleLevel(g_sam, si.tc0, 0.0, offset).aaaa;
|
|
#else
|
|
acc += g_tex.SampleLevel(g_sam, si.tc0, 0.0, offset) * weight;
|
|
#endif
|
|
}
|
|
acc *= (1.0 / weightSum);
|
|
|
|
so.color = acc;
|
|
#if defined(DEF_SSAO) && !defined(DEF_VERTICAL) // Make sure to write R channel to alpha, destination is sRGB.
|
|
so.color = acc.rrrr;
|
|
#endif
|
|
|
|
return so;
|
|
}
|
|
#endif
|
|
|
|
#ifdef _VS
|
|
VSO mainAntiAliasingVS(VSI si)
|
|
{
|
|
VSO so;
|
|
|
|
// Standard quad:
|
|
so.pos = float4(mul(si.pos, g_ubBlurVS._matW), 1);
|
|
so.tc0 = mul(si.pos, g_ubBlurVS._matV).xy;
|
|
|
|
return so;
|
|
}
|
|
#endif
|
|
|
|
#ifdef _FS
|
|
FSO mainAntiAliasingFS(VSO si)
|
|
{
|
|
FSO so;
|
|
|
|
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
|
|
const float3 normalWV = DS_GetNormal(rawGBuffer1);
|
|
const float coarseAlpha = normalWV.b * normalWV.b * normalWV.b;
|
|
|
|
// <DepthBased>
|
|
float3 coarseNorm;
|
|
float originDeeper;
|
|
float depthBasedEdge;
|
|
{
|
|
const float rawOriginDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).r;
|
|
const float originDepth = ToLinearDepth(rawOriginDepth, g_ubExtraBlurFS._zNearFarEx);
|
|
const float4 rawKernelDepths = float4(
|
|
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0, int2(-2, +0)).r, // L
|
|
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0, int2(+0, -2)).r, // T
|
|
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0, int2(+2, +0)).r, // R
|
|
g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0, int2(+0, +2)).r); // B
|
|
const float4 kernelDepths = ToLinearDepth(rawKernelDepths, g_ubExtraBlurFS._zNearFarEx);
|
|
const float minDepth = min(min(kernelDepths[0], kernelDepths[1]), min(kernelDepths[2], kernelDepths[3]));
|
|
const float equalize = max(1.0 / originDepth, 0.05);
|
|
originDeeper = saturate((originDepth - minDepth) * equalize);
|
|
const float4 depthOffsets = abs((originDepth - kernelDepths) * equalize);
|
|
depthBasedEdge = saturate(dot(depthOffsets, 1.0));
|
|
|
|
const float3 v0 = float3(1, 0, kernelDepths[0] - kernelDepths[2]);
|
|
const float3 v1 = float3(0, 1, kernelDepths[3] - kernelDepths[1]);
|
|
coarseNorm = normalize(cross(v0, v1));
|
|
}
|
|
// </DepthBased>
|
|
|
|
// <NormalBased>
|
|
float normalBasedEdge;
|
|
{
|
|
const float4 rawNrmLT = float4(
|
|
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(-2, +0)).rg,
|
|
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(+0, -2)).rg);
|
|
const float4 rawNrmRB = float4(
|
|
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(+2, +0)).rg,
|
|
g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0, int2(+0, +2)).rg);
|
|
const float4 diffA = rawNrmLT - rawNrmRB;
|
|
const float4 diffB = rawNrmLT - rawNrmRB.zwxy;
|
|
const float4 dots = float4(
|
|
dot(diffA.xy, diffA.xy),
|
|
dot(diffA.zw, diffA.zw),
|
|
dot(diffB.xy, diffB.xy),
|
|
dot(diffB.zw, diffB.zw));
|
|
const float maxDot = max(max(dots.x, dots.y), max(dots.z, dots.w));
|
|
normalBasedEdge = saturate(maxDot * maxDot * 10.0);
|
|
}
|
|
// </NormalBased>
|
|
|
|
// Directional blur:
|
|
const float3 normal = lerp(normalWV, coarseNorm, coarseAlpha * 0.5);
|
|
// {y, -x} is perpendicular vector. Also flip Y axis: normal XY to texture UV.
|
|
const float3 perp = normal.yxz;
|
|
const float omni = max(perp.z * perp.z * perp.z, originDeeper);
|
|
const float2 dirs[4] =
|
|
{
|
|
lerp(perp.xy * +4.0, float2(-0.6, -0.3), omni),
|
|
lerp(perp.xy * -2.0, float2(+0.3, -0.6), omni),
|
|
lerp(perp.xy * -4.0, float2(-0.3, +0.6), omni),
|
|
lerp(perp.xy * +2.0, float2(+0.6, +0.3), omni)
|
|
};
|
|
const float2 offsetScale = g_ubExtraBlurFS._textureSize.zw * max(normalBasedEdge, depthBasedEdge);
|
|
const float3 kernelColors[4] =
|
|
{
|
|
g_tex.SampleLevel(g_sam, si.tc0 + dirs[0] * offsetScale, 0.0).rgb,
|
|
g_tex.SampleLevel(g_sam, si.tc0 + dirs[1] * offsetScale, 0.0).rgb,
|
|
g_tex.SampleLevel(g_sam, si.tc0 + dirs[2] * offsetScale, 0.0).rgb,
|
|
g_tex.SampleLevel(g_sam, si.tc0 + dirs[3] * offsetScale, 0.0).rgb
|
|
};
|
|
so.color.rgb = (kernelColors[0] + kernelColors[1] + kernelColors[2] + kernelColors[3]) * 0.25;
|
|
so.color.a = 1.0;
|
|
|
|
return so;
|
|
}
|
|
#endif
|
|
|
|
#ifdef _VS
|
|
VSO mainMotionVS(VSI si)
|
|
{
|
|
VSO so;
|
|
|
|
// Standard quad:
|
|
so.pos = float4(mul(si.pos, g_ubBlurVS._matW), 1);
|
|
so.tc0 = mul(si.pos, g_ubBlurVS._matV).xy;
|
|
|
|
return so;
|
|
}
|
|
#endif
|
|
|
|
#ifdef _FS
|
|
FSO mainMotionFS(VSO si)
|
|
{
|
|
FSO so;
|
|
|
|
const float3 rand = Rand(si.pos.xy);
|
|
const float offsetScale = 0.5 + 0.3 * rand.x; // Blur 50% - 80% of frame time.
|
|
|
|
const int sampleCount = max(4, _ANISOTROPY_LEVEL);
|
|
|
|
const float4 rawGBuffer1 = g_texGBuffer1.SampleLevel(g_samGBuffer1, si.tc0, 0.0);
|
|
|
|
const float rawOriginDepth = g_texDepth.SampleLevel(g_samDepth, si.tc0, 0.0).r;
|
|
const float originDepth = ToLinearDepth(rawOriginDepth, g_ubExtraBlurFS._zNearFarEx);
|
|
|
|
float2 tcFrom;
|
|
{
|
|
const float2 ndcPos = ToNdcPos(si.tc0);
|
|
const float3 posW = DS_GetPosition(rawOriginDepth, g_ubExtraBlurFS._matInvVP, ndcPos);
|
|
const float4 prevClipSpacePos = mul(float4(posW, 1), g_ubExtraBlurFS._matPrevVP);
|
|
const float2 prevNdcPos = prevClipSpacePos.xy / prevClipSpacePos.w;
|
|
tcFrom = ToTexCoords(prevNdcPos);
|
|
}
|
|
|
|
const float2 stride = (si.tc0 - tcFrom) * offsetScale / (sampleCount - 1);
|
|
const float2 tcOrigin = lerp(tcFrom, si.tc0, 0.7);
|
|
|
|
float4 acc = float4(g_tex.SampleLevel(g_sam, si.tc0, 0.0).rgb, 1);
|
|
[unroll] for (int i = 0; i < sampleCount; i++)
|
|
{
|
|
if (i == sampleCount / 2)
|
|
continue;
|
|
|
|
const float2 kernelCoords = tcOrigin + stride * i;
|
|
|
|
const float rawKernelDepth = g_texDepth.SampleLevel(g_samDepth, kernelCoords, 0.0).r;
|
|
const float kernelDepth = ToLinearDepth(rawKernelDepth, g_ubExtraBlurFS._zNearFarEx);
|
|
const float kernelDeeper = kernelDepth - originDepth;
|
|
const float allowed = saturate(kernelDeeper * 0.2 + 1.0) * rawGBuffer1.a;
|
|
const float weight = saturate(kernelDeeper * 0.2) + 1.0;
|
|
|
|
const float3 kernelColor = g_tex.SampleLevel(g_sam, kernelCoords, 0.0).rgb;
|
|
acc += lerp(0.0, float4(kernelColor * weight, weight), allowed);
|
|
}
|
|
acc /= acc.a;
|
|
|
|
so.color = float4(acc.rgb, 1);
|
|
|
|
return so;
|
|
}
|
|
#endif
|
|
|
|
//@main:#H
|
|
//@main:#V VERTICAL
|
|
//@main:#HSsao SSAO
|
|
//@main:#VSsao SSAO VERTICAL
|
|
//@mainAntiAliasing:#AntiAliasing AA
|
|
//@mainMotion:#Motion MOTION
|