float4 RenderUpsamplingPS( OutputVS inPixel ) : SV_TARGET
{
const
float2 kScreenSize = g_ScreenParam.xy * 2.0;
const
float2 kScreenHalfSize = g_ScreenParam.xy;
const
float4 kBilinearWeights[4] =
{
float4( 9.0/16.0, 3.0/16.0, 3.0/16.0, 1.0/16.0 ),
float4( 3.0/16.0, 9.0/16.0, 1.0/16.0, 3.0/16.0 ),
float4( 3.0/16.0, 1.0/16.0, 9.0/16.0, 3.0/16.0 ),
float4( 1.0/16.0, 3.0/16.0, 3.0/16.0, 9.0/16.0 )
};
int2 hiResUV = (int2)(inPixel.texCoord0 * kScreenSize + float2(0.1, 0.1));
int
hiResIndex = (1 - (hiResUV.y & 0x01)) * 2 + (1 - (hiResUV.x & 0x01));
float4 hiResND = texNormalDepth.Load( int3(hiResUV, 0), int2(0, 0) );
int2 lowResUV = (int2)(inPixel.texCoord0 * kScreenHalfSize.xy + float2(0.1, 0.1));
float4 lowResND[4];
float
lowResAO[4];
switch
(hiResIndex)
{
case
0:
lowResND[0] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(0, 0) );
lowResND[1] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(1, 0) );
lowResND[2] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(0, 1) );
lowResND[3] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(1, 1) );
lowResAO[0] = texHDAO.Load( int3(lowResUV, 0), int2(0, 0) ).r;
lowResAO[1] = texHDAO.Load( int3(lowResUV, 0), int2(1, 0) ).r;
lowResAO[2] = texHDAO.Load( int3(lowResUV, 0), int2(0, 1) ).r;
lowResAO[3] = texHDAO.Load( int3(lowResUV, 0), int2(1, 1) ).r;
break
;
case
1:
lowResND[0] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(-1, 0) );
lowResND[1] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(0, 0) );
lowResND[2] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(-1, 1) );
lowResND[3] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(0, 1) );
lowResAO[0] = texHDAO.Load( int3(lowResUV, 0), int2(-1, 0) ).r;
lowResAO[1] = texHDAO.Load( int3(lowResUV, 0), int2(0, 0) ).r;
lowResAO[2] = texHDAO.Load( int3(lowResUV, 0), int2(-1, 1) ).r;
lowResAO[3] = texHDAO.Load( int3(lowResUV, 0), int2(0, 1) ).r;
break
;
case
2:
lowResND[0] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(0, -1) );
lowResND[1] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(1, -1) );
lowResND[2] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(0, 0) );
lowResND[3] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(1, 0) );
lowResAO[0] = texHDAO.Load( int3(lowResUV, 0), int2(0, -1) ).r;
lowResAO[1] = texHDAO.Load( int3(lowResUV, 0), int2(1, -1) ).r;
lowResAO[2] = texHDAO.Load( int3(lowResUV, 0), int2(0, 0) ).r;
lowResAO[3] = texHDAO.Load( int3(lowResUV, 0), int2(1, 0) ).r;
break
;
case
3:
lowResND[0] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(-1, -1) );
lowResND[1] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(0, -1) );
lowResND[2] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(-1, 0) );
lowResND[3] = texHalfNormalDepth.Load( int3(lowResUV, 0), int2(0, 0) );
lowResAO[0] = texHDAO.Load( int3(lowResUV, 0), int2(-1, -1) ).r;
lowResAO[1] = texHDAO.Load( int3(lowResUV, 0), int2(0, -1) ).r;
lowResAO[2] = texHDAO.Load( int3(lowResUV, 0), int2(-1, 0) ).r;
lowResAO[3] = texHDAO.Load( int3(lowResUV, 0), int2(0, 0) ).r;
break
;
}
float
totalWeight = 0.0;
float
ao = 0.0;
for
(
int
i = 0; i < 4; ++i )
{
float
normalWeight = dot( lowResND[i].xyz, hiResND.xyz );
normalWeight =
pow
( saturate(normalWeight), 32.0 );
float
depthDiff = hiResND.w - lowResND[i].w;
float
depthWeight = 1.0 / (1.0 +
abs
(depthDiff));
float
weight = normalWeight * depthWeight * kBilinearWeights[hiResIndex][i];
totalWeight += weight;
ao += lowResAO[i] * weight;
}
ao /= totalWeight;
return
float4(ao, ao, ao, 1);
}