材料:
1.基于屏幕的:normal和深度贴图、噪波图
2.采样体积:14个向量组成的体积
用AO层管理上述材料(存在PSO中,再给寄存器调用)
对噪波进行双边模糊
采样体
struct FSampleVolumeBuffer
{
FSampleVolumeBuffer();
public:
void BuildVolumeBuffer();
void BuildRandomVolumeBuffer();
void Update(XMFLOAT4 *InBuffer);
public:
void* GetVolumeBuffer() {return VolumeBuffer.data();}
protected:
std::vector<fvector_4d> VolumeBuffer;
};
噪波图
不同:构建自己的上传堆
BuildDescriptors();
BuildRenderTargetRTV();
BuildSRVDescriptors();
BuildRTVDescriptors();
创建资源(定义颜色)
上传缓冲区
深度
:视口空间下,点的深度/Z坐标(直接采样自深度贴图)
a:视口空间下,点的位置
V:点的近剪裁面位置
:点的近剪裁面空间位置的Z坐标
b:在环境光反射方向上 长度为遮蔽距离的点(自己设置)——如果反射方向与反向方向相反,通过sign反转。然后根据b、c在近剪裁面UI坐标相同,采样深度,判断有无遮蔽。
根据A和C的位置关系累加一个值(这个值在反面为0,证明与C和A的距离有关)
这个值叫遮敝率:14条采样光线,判断有多少条被遮蔽()
可及率=1-这个值(有多少条关系没被遮蔽)
双边模糊(双边保留模糊)BilateralBlur
更加平滑
1.构建正态分布的模糊权重(卷积)
if (bReBuildBlurWeights)
{
BlurWeights.clear();
}
if (BlurWeights.size() == 0)
{
BlurRadius = ceil(InSigma * 2.f);
BlurWeights.resize(2.f * BlurRadius + 1);
float Len = 2.f * pow(InSigma, 2);
float Weights = 0.f;
for (int i = -BlurRadius;i<= BlurRadius; ++i)
{
float Value = (float)i;
BlurWeights[i + BlurRadius] = expf(-pow(Value, 2) / Len);
Weights += BlurWeights[i + BlurRadius];
}
//将权重值 映射到 0 - 1
for (int i = 0; i < BlurWeights.size(); i++)
{
BlurWeights[i] /= Weights;
}
}
模糊考虑的因素:1.法线 2.深度
根据UV采样AO图和原来的颜色混合,再乘以权重
结果除以总权重
Shader:
float4 PixelShaderMain(MeshVertexOut MVOut) :SV_TARGET
{
float BlurWeights[12] =
{
Float4BlurWeights[0].x, Float4BlurWeights[0].y, Float4BlurWeights[0].z,Float4BlurWeights[0].w,
Float4BlurWeights[1].x, Float4BlurWeights[1].y, Float4BlurWeights[1].z,Float4BlurWeights[1].w,
Float4BlurWeights[2].x, Float4BlurWeights[2].y, Float4BlurWeights[2].z,Float4BlurWeights[2].w,
};
//单位偏移值
float2 TexOffset;
if (bHorizontalBlur)
{
TexOffset = float2(InversionSize.x,0.f);
}
else
{
TexOffset = float2(0.f,InversionSize.y);
}
//中间的权重对应的法线核深度颜色
float Weights = BlurWeights[BlurRadius];
float4 Color = Weights * SampleAcceptMap.SampleLevel(TextureSampler, MVOut.TexCoord, 0.0f);
float3 MatchingNormal = SampleNormalMap.SampleLevel(TextureSampler, MVOut.TexCoord, 0.0f).xyz;
float MatchingViewDepth = DepthNdcSpaceToViewSpace(SampleDepthMap.SampleLevel(DepthSampler, MVOut.TexCoord, 0.0f).r);
//偏移后的权重对应的法线核深度颜色
for (float i = -BlurRadius; i <= BlurRadius; i++)
{
if (i == 0)
{
continue;
}
float2 TexCoord = MVOut.TexCoord + i * TexOffset;
float3 Normal = SampleNormalMap.SampleLevel(TextureSampler, TexCoord, 0.0f).xyz;
float ViewDepth = DepthNdcSpaceToViewSpace(SampleDepthMap.SampleLevel(DepthSampler, TexCoord, 0.0f).r);
if (dot(Normal, MatchingNormal) >= 0.8f && abs(ViewDepth - MatchingViewDepth) <= 0.2f)
{
float Weight = BlurWeights[BlurRadius + i];
Color += Weight * SampleAcceptMap.SampleLevel(TextureSampler,TexCoord, 0.0f);
Weights += Weight;
}
}
return Color / Weights;
}