词汇
Sobel Operator
内容
假设所使用模糊算法具有可分离性,将模糊分为两个1D模糊运算,用两个纹理分别绑定SRV和UAV进行处理。
对处理后的图像可以进行反复的模糊处理来打达到更好的模糊效果
void BlurApp::OnResize()
{
D3DApp::OnResize();
// The window resized, so update the aspect ratio and recompute the projection matrix.
XMMATRIX P = XMMatrixPerspectiveFovLH(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
XMStoreFloat4x4(&mProj, P);
if(mBlurFilter != nullptr)
{
mBlurFilter->OnResize(mClientWidth, mClientHeight);
}
}
void BlurFilter::OnResize(UINT newWidth, UINT newHeight)
{
if((mWidth != newWidth) || (mHeight != newHeight))
{
mWidth = newWidth;
mHeight = newHeight;
//用心的大小重新构建离屏纹理资源
BuildResources();
//为新的资源创建新的描述符
BuildDescriptors();
}
}
BlurFilter类
BlurFilter封装了纹理资源,为使用绘制/分派命令,则需要将这些资源绑定到渲染流水线上,因此需要为它们创建相应的描述符。要在D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV类型的描述符堆中开辟额外的空间存储这些描述符。
BlurFilter::BuildDescriptors方法:利用堆中起始位置的描述符句柄来存储BlurFilter类要用到的描述符。该方法缓存了模糊过程中所需的一切描述符句柄,并以此来创建相应的描述符。利用该函数缓存句柄的原因在于当窗口发生改变时,它可以随资源的变化重新创建这些描述符:
void BlurFilter::BuildDescriptors()
{
//保存对描述符的引用
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = mFormat;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
uavDesc.Format = mFormat;
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
uavDesc.Texture2D.MipSlice = 0;
md3dDevice->CreateShaderResourceView(mBlurMap0.Get(), &srvDesc, mBlur0CpuSrv);
md3dDevice->CreateUnorderedAccessView(mBlurMap0.Get(), nullptr, &uavDesc, mBlur0CpuUav);
md3dDevice->CreateShaderResourceView(mBlurMap1.Get(), &srvDesc, mBlur1CpuSrv);
md3dDevice->CreateUnorderedAccessView(mBlurMap1.Get(), nullptr, &uavDesc, mBlur1CpuUav);
}
//创建BlurFilter
mBlurFilter->BuildDescriptors(
CD3DX12_CPU_DESCRIPTOR_HANDLE(mCbvSrvUavDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), 3, mCbvSrvUavDescriptorSize),
CD3DX12_GPU_DESCRIPTOR_HANDLE(mCbvSrvUavDescriptorHeap->GetGPUDescriptorHandleForHeapStart(), 3, mCbvSrvUavDescriptorSize),
mCbvSrvUavDescriptorSize);
模糊处理是一项代价高昂的操作,耗费的时间与待处理的图像大小有关。一般情况下,将场景渲染到离屏纹理的时候会将离屏纹理大小设为后台缓冲区尺寸的四分之一来加快离屏纹理的绘制速度。然后再将屏幕分辨率展开为完整的屏幕分辨率。
假设需要处理的图像宽为w高为h,对于1D纵向模糊而言,一个线程组用256个线程处理水平方向上的线段,而每个线程负责图像中一个像素的模糊操作。因此为了图像中每个像素都会被模糊处理,则需要在x方向分派 c e i l ( w 256 ) ceil(\frac{w}{256}) ceil(256