1. EX App Program
1.1 Blur System
1.1.1 C++ 응용프로그램
void BlurFilter::BlurInPlace(ComPtr<ID3D11DeviceContext> dc,
ComPtr<ID3D11ShaderResourceView> inputSRV,
ComPtr<ID3D11UnorderedAccessView> inputUAV,
int32 blurCount)
- 계산 셰이더를 실행하여 Render to Texture를 흐림
- A에 대한 세이더 자원 뷰를 계산 셰이더의 입력, B에 대한 순서 없는 뷰를 계산 셰이더의 출력 설정
- 스레드 그룹들을 배분해서 수평 흐리기 작업을 수행
D3DX11_TECHNIQUE_DESC techDesc;
Effects::BlurFX->HorzBlurTech->GetDesc(&techDesc);
for (uint32 p = 0; p < techDesc.Passes; ++p)
{
Effects::BlurFX->SetInputMap(inputSRV);
Effects::BlurFX->SetOutputMap(_blurredOutputTexUAV);
Effects::BlurFX->HorzBlurTech->GetPassByIndex(p)->Apply(0, dc.Get());
uint32 numGroupsX = (uint32)ceilf(_width / 256.0f);
dc->Dispatch(numGroupsX, _height, 1);
}
- 자원의 효율적인 관리를 위해 입력 Texture를 계산 셰이더에서 떼어냄
- 출력 Texture 또한 계산 셰이더에서 떼어냄, 하나의 자원을 동시에 입력과 출력 모두 사용X
ID3D11ShaderResourceView* nullSRV[1] = { 0 }; dc->CSSetShaderResources(0, 1, nullSRV);
ID3D11UnorderedAccessView* nullUAV[1] = { 0 }; dc->CSSetUnorderedAccessViews(0, 1, nullUAV, 0);
- B에 대한 세이더 자원 뷰를 계산 셰이더의 입력, A에 대한 순서 없는 뷰를 계산 세이더의 출력으로 설정
- 스레드 그룹들을 배분해서 수직 흐리기 작업을 수행 후 입력, 출력 자원을 떼어냄
Effects::BlurFX->VertBlurTech->GetDesc(&techDesc);
for (uint32 p = 0; p < techDesc.Passes; ++p)
{
Effects::BlurFX->SetInputMap(_blurredOutputTexSRV);
Effects::BlurFX->SetOutputMap(inputUAV);
Effects::BlurFX->VertBlurTech->GetPassByIndex(p)->Apply(0, dc.Get());
uint32 numGroupsY = (uint32)ceilf(_height / 256.0f);
dc->Dispatch(_width, numGroupsY, 1);
}
dc->CSSetShaderResources(0, 1, nullSRV); dc->CSSetUnorderedAccessViews(0, 1, nullUAV, 0);
dc->CSSetShader(0, 0, 0); // 비활성화
1.1.2 Draw Scene
- 땅과 물을 렌더링할 때 Render to Texture에 렌더링 진행
ID3D11RenderTargetView* renderTargets[1] = { _offscreenRTV.Get()};
_deviceContext->OMSetRenderTargets(1, renderTargets, _depthStencilView.Get());
_deviceContext->ClearRenderTargetView(_offscreenRTV.Get(),
reinterpret_cast<const float*>(&Colors::Silver));
_deviceContext->ClearDepthStencilView(_depthStencilView.Get(),
D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
- 이 후 기존 Render Target View를 받아 설정하고 흐리기 알고리즘 적용
renderTargets[0] = _renderTargetView.Get();
_deviceContext->OMSetRenderTargets(1, renderTargets, _depthStencilView.Get());
_blur.BlurInPlace(_deviceContext, _offscreenSRV, _offscreenUAV, 4);
_deviceContext->ClearRenderTargetView(_renderTargetView.Get(),
reinterpret_cast<const float*>(&Colors::Silver));
_deviceContext->ClearDepthStencilView(_depthStencilView.Get(),
D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
- 마지막으로 흐려진 Texture를 화면 전체를 덮는 사각형에 입혀 후면 버퍼를 그림
DrawScreenQuad();
HR(_swapChain->Present(0, 0));
1.1.3 Effect File
- 스레드 그룹은 선분 형태로 구성된 스레드 256개이며, 각 스레드는 이미지의 픽셀 하나를 흐리는 역할 수행
- 앞에서 말한 흐리기 알고리즘을 구현
- 각 스레드가 현재 픽셀을 중심으로 한 이웃 픽셀들의 행 행렬의 가중 평균을 구하는 것은 비효율 적임
- 공유 메모리를 사용하여 비효율성을 극복
[numthreads(N, 1, 1)]
void HorzBlurCS(int3 groupThreadID : SV_GroupThreadID, int3 dispatchThreadID : SV_DispatchThreadID);
- 공유 메모리를 사용하여 픽셀 N개를 흐리려면 N + 2 * 반지름개의 픽셀을 읽어야 함
- 이미지 범위 밖의 표본을 이미지 경계로 한정
if (groupThreadID.x < gBlurRadius)
{
int x = max(dispatchThreadID.x - gBlurRadius, 0);
gCache[groupThreadID.x] = gInput[int2(x, dispatchThreadID.y)];
}
if (groupThreadID.x >= N - gBlurRadius)
{
int x = min(dispatchThreadID.x + gBlurRadius, gInput.Length.x - 1);
gCache[groupThreadID.x + 2 * gBlurRadius] = gInput[int2(x, dispatchThreadID.y)];
}
gCache[groupThreadID.x + gBlurRadius] = gInput[min(dispatchThreadID.xy, gInput.Length.xy - 1)];
- 모든 스레드가 여기까지의 작업을 완수할 때까지 기다림
GroupMemoryBarrierWithGroupSync();
- 각 픽셀을 반지름을 통해 개수를 확인하고 흐림
float4 blurColor = float4(0, 0, 0, 0);
[unroll]
for (int i = -gBlurRadius; i <= gBlurRadius; ++i)
{
int k = groupThreadID.x + gBlurRadius + i;
blurColor += gWeights[i + gBlurRadius] * gCache[k];
}
gOutput[dispatchThreadID.xy] = blurColor;
- 나머지 코드는 밑의 글에 있는 함수와 비슷하거나 동일
'C++ Algorithm & Study > Game Math & DirectX 11' 카테고리의 다른 글
[Direct11] 31. EX App Program - Quad Tesselation (0) | 2023.06.22 |
---|---|
[Direct11] 30. Direct3D Tesselation (0) | 2023.06.22 |
[Direct11] 28. Direct3D Compute Shader - Blur System (0) | 2023.06.21 |
[Direct11] 27. Direct3D Compute Shader - I/O Resource (0) | 2023.06.21 |
[Direct11] 26. Direct3D Compute Shader (0) | 2023.06.21 |