이미지 필터는 화면 크기의 사각형을 그리는 쉐이더이다.
D3D11_SAMPLER_DESC sampDesc;
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
D3D11_RASTERIZER_DESC rastDesc;
rastDesc.DepthClipEnable = false;
이미지 처리를 할 때는 샘플러를 Clamp를 일반적으로 사용하기 때문에 Clamp로 해주고,
이미지이기 때문에 Depth가 필요없으므로 래스터라이저의 DepthClipEnable을 false로 해준다.
ZeroMemory(&m_viewport, sizeof(D3D11_VIEWPORT));
m_viewport.TopLeftX = 0;
m_viewport.TopLeftY = 0;
m_viewport.Width = float(width);
m_viewport.Height = float(height);
m_viewport.MinDepth = 0.0f;
m_viewport.MaxDepth = 1.0f;
이미지의 해상도에 따라 Viewport를 바꿔줘야 하므로 이미지 필터 내에서 Viewport를 따로 세팅해준다.
D3D11_TEXTURE2D_DESC txtDesc;
txtDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; // 이미지 처리용도
txtDesc.Usage = D3D11_USAGE_DEFAULT;
txtDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE |
D3D11_BIND_RENDER_TARGET;
텍스쳐의 BindFlag는 DEFAULT나 IMMUTABLE이 아닌 SHADER_RESOURCE | RENDER_TARGET이다.
이미지 처리할 때는 텍스쳐를 읽을 뿐만 아니라 쉐이더를 렌더링할 수 있어야 하기 때문이다.
원래는 SwapChain이 메모리에 렌더링한 결과를 보여줄 수 있게 버퍼를 교체하는 역할을 하는데,
여기서는 SwapChain을 거치지 않고 별도의 메모리를 만들어 그 텍스쳐에 렌더링하는 방식을 사용한다.
device->CreateTexture2D(&txtDesc, NULL, texture.GetAddressOf());
device->CreateRenderTargetView(texture.Get(), &viewDesc,
m_renderTargetView.GetAddressOf());
device->CreateShaderResourceView(texture.Get(), nullptr,
m_shaderResourceView.GetAddressOf());
m_pixelConstData.dx = 1.0f / width;
m_pixelConstData.dy = 1.0f / height;
CreateTexture2D로 텍스쳐를 만들고 그것을 이용해서 CreateRenderTargetView, CreateShaderResourceView를 한다.
이미지의 픽셀단위 간격을 알고 있으면 배열처럼 근처 픽셀 값들을 샘플링해서 가져올 수 있다.
DXGI_SWAP_CHAIN_DESC sd;
sd.BufferUsage = DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT;
이미지 후처리를 위해 SwapChain에서 RenderTarget을 출력할 뿐만 아니라 렌더링한 결과를 다시 한번 바꾸기 위해
Input으로 넣어줄 필요가 있기 때문에 Shader_Input을 추가한다.
m_device->CreateRenderTargetView(backBuffer.Get(), nullptr,
m_renderTargetView.GetAddressOf());
m_device->CreateShaderResourceView(backBuffer.Get(), nullptr,
m_shaderResourceView.GetAddressOf());
마찬가지로 AppBase::CreateRenderTargetView에서 백버퍼를 RenderTarget으로 사용할 뿐만 아니라 후처리를 위해
ShaderResource로도 사용할 것이므로 CreateShaderResourceView도 추가한다. 그러면 RenderTarget으로 사용되는 백버퍼를 ShaderResource로 이미지 필터에 넣어줄 수가 있다.
auto copyFilter =
make_shared<ImageFilter>(m_device, m_context, L"Sampling", L"Sampling",
m_screenWidth, m_screenHeight);
copyFilter->SetShaderResources({this->m_shaderResourceView});
m_filters.push_back(copyFilter);
auto finalFilter =
make_shared<ImageFilter>(m_device, m_context, L"Sampling", L"Sampling",
m_screenWidth, m_screenHeight);
finalFilter->SetShaderResources({m_filters.back()->m_shaderResourceView);
finalFilter->SetRenderTargets({this->m_renderTargetView});
m_filters.push_back(finalFilter);
그 후 초기화할 때 m_filters에 이미지 필터들을 넣어준다. 먼저 copyFilter에서 백버퍼의 shaderResourceView를 입력받는다. 그 입력받은 결과를 finalFilter에서 다시 shaderResource로 받아준다음 renderTarget으로 설정해 보여지게 한다.
for (auto &f : m_filters) {
f->Render(m_context);
}
그 후 Render에서 필터를 돌면서 후처리를 진행하게 된다.
'그래픽스' 카테고리의 다른 글
| [그래픽스] 쿼터니언(이론) (0) | 2023.07.19 |
|---|---|
| [그래픽스] Picking (렌더타겟 2개 이용, GPU->CPU로 데이터 복사) (0) | 2023.07.19 |
| [그래픽스] Texturing (0) | 2023.07.18 |
| [그래픽스] 투영 변환에서 z값을 나누는 시점 (0) | 2023.07.18 |
| [그래픽스] 렌더링 파이프라인 (0) | 2023.07.18 |