1. 3D Direct Application
1.1 Dynamic Cube Mapping System
1.1.1 Dynamic Cube Mapping
- 장면에 움직이는 물체들이 많은 경우, 미리 생성된 입방체 맵은 그러한 움직임을 포착하지 못함
- 입방체 맵을 실생시점에서 생성, 매 프레임마다 입방체 맵의 중심에 카메라를 두고 여섯 가지 축 방향마다 각각 장면을 렌더링해서 입방체 맵의 여섯 면을 생성
- 입방체 맵을 매 프레임마다 생성하면 장면 안에서 움직이는 물체들이 고스란히 입방체 맵에 포착
- 결과적으로 반사 물체 주변의 움직이는 물체들이 제대로 반사
1.1.1.1 Render Target View & Shader Resoure View
- 입방체 맵 Texture Resource를 생성하려면 원소가 여섯 개인 Texture 배열이 필요
static const int CubeMapSize = 256;
- 배열을 입방체 면들을 그려 넣을 렌더 대상으로 묶고 픽셀 셰이더에서 사용할 수 있도록 셰이더 뷰 자원으로도 묶음
D3D11_TEXTURE2D_DESC texDesc; /* 필요 부분만 작성 */
texDesc.Width = CubeMapSize; texDesc.Height = CubeMapSize;
texDesc.ArraySize = 6;
texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
texDesc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS | D3D11_RESOURCE_MISC_TEXTURECUBE;
ComPtr<ID3D11Texture2D> cubeTex;
HR(_device->CreateTexture2D(&texDesc, 0, cubeTex.GetAddressOf()));
- 입방체 맵 Texture 배열의 각 원소에 대해 렌더 대상 뷰를 생성, 각 입방체 면에 장면을 렌더링 할 수 있음
- 배열의 한 원소에 대한 뷰만 생성하고 i번째 원소에 대한 렌더 대상 뷰를 생성
ComPtr<ID3D11RenderTargetView> _dynamicCubeMapRTV[6];
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = texDesc.Format;
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
rtvDesc.Texture2DArray.ArraySize = 1; rtvDesc.Texture2DArray.MipSlice = 0;
for (int32 i = 0; i < 6; ++i)
{
rtvDesc.Texture2DArray.FirstArraySlice = i;
HR(_device->CreateRenderTargetView(cubeTex.Get(), &rtvDesc, _dynamicCubeMapRTV[i].GetAddressOf()));
}
- 반사 효과를 위해 픽셀 셰이더에서 입방체 맵을 물체에 입힐 수 있으려면 셰이더 자원 뷰도 생성
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = texDesc.Format;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
srvDesc.TextureCube.MostDetailedMip = 0; srvDesc.TextureCube.MipLevels = -1;
HR(_device->CreateShaderResourceView(cubeTex.Get(), &srvDesc, _dynamicCubeMapSRV.GetAddressOf()));
1.1.1.2 Depth/Stencil View & Viewport
- 입방체 맵 면들에 장면을 렌더링하려면 입방체 맵 면의 해상도에 맞는 크기의 깊이 버퍼가 필요
D3D11_TEXTURE2D_DESC depthTexDesc; /* 구조체 생략 */
ComPtr<ID3D11Texture2D> depthTex;
HR(_device->CreateTexture2D(&depthTexDesc, 0, depthTex.GetAddressOf()));
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; /* 구조체 생략 */
HR(_device->CreateDepthStencilView(depthTex.Get(), &dsvDesc, _dynamicCubeMapDSV.GetAddressOf()));
- 입방체 맵 면의 해상도가 주 후면 버퍼의 해상도가 다르다는 것은 뷰포드 역시 새로 생성
D3D11_VIEWPORT _cubeMapViewport;
_cubeMapViewport.TopLeftX = 0.0f; _cubeMapViewport.TopLeftY = 0.0f;
_cubeMapViewport.Width = (float)CubeMapSize; _cubeMapViewport.Height = (float)CubeMapSize;
_cubeMapViewport.MinDepth = 0.0f; _cubeMapViewport.MaxDepth = 1.0f;
1.1.1.3 Cube Map Camera
void DynamicCubeMapDemo::BuildCubeFaceCamera(float x, float y, float z);
- 수직, 수평 시야각 모두 90도인 카메라를 장면의 어떤 물체의 중심에 두고 각각 장면에 렌더링해 이미지 저장
- 주어진 위치에서 입방체의 여섯 면을 렌더링하기 위해 카메라 여섯 개를 미리 생성
Camera _cubeMapCamera[6];
- 카메라의 위치 및 카메라의 상향 벡터를 사용하여 각 좌표축 방향을 바라보는 시선 벡터 및 상향 벡터 생성
- 좌표축 방향을 바라보는 상향 벡터에서 Y축 방향 제외 모두 동일하게 설정
XMFLOAT3 center(x, y, z); XMFLOAT3 worldUp(0.0f, 1.0f, 0.0f);
XMFLOAT3 targets[6]; XMFLOAT3 ups[6]; /* 내용 생략 */
- 마지막으로 여섯개의 카메라에 대해 설정
for (int32 i = 0; i < 6; ++i)
{
_cubeMapCamera[i].LookAt(center, targets[i], ups[i]);
_cubeMapCamera[i].SetLens(0.5f * XM_PI, 1.0f, 0.1f, 1000.0f);
_cubeMapCamera[i].UpdateViewMatrix();
}
1.1.1.4 Draw Scene
- 렌더링을 수행하는 함수에서 장면 중앙의 구를 제외한 장면 전체를 입방체 맵에 렌더링
- 중앙 구에 대해 동적 입방체 매핑 적용
- 장면을 입방체 맵 각 면에 렌더링해서 입방체 맵을 생성, 이전에 생성한 뷰포트를 사용하여 적용
ID3D11RenderTargetView* renderTargets[1];
_deviceContext->RSSetViewports(1, &_cubeMapViewport);
or (int i = 0; i < 6; ++i) { /* ... */ }
- 입방체 맵 면과 깊이 버퍼를 지우고 입방체 맵 면을 렌더 대상으로 묶음
- 또한 중앙 구를 제외한 장면을 입방체 맵에 그림
_deviceContext->ClearRenderTargetView(_dynamicCubeMapRTV[i].Get(),
reinterpret_cast<const float*>(&Colors::Silver));
_deviceContext->ClearDepthStencilView(_dynamicCubeMapDSV.Get(),
D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
renderTargets[0] = _dynamicCubeMapRTV[i].Get();
_deviceContext->OMSetRenderTargets(1, renderTargets, _dynamicCubeMapDSV.Get());
DrawScene(_cubeMapCamera[i], false);
- 기존 뷰포트와 렌더 대상을 복원한 후 하드웨어가 입방체 맵의 하위 밉맵 수준들을 생성
_deviceContext->RSSetViewports(1, &_viewport); renderTargets[0] = _renderTargetView.Get();
_deviceContext->OMSetRenderTargets(1, renderTargets, _depthStencilView.Get());
_deviceContext->GenerateMips(_dynamicCubeMapSRV.Get());
- 중앙의 구를 포함한 장면 전체를 보통의 방식으로 그림
_deviceContext->ClearRenderTargetView(_renderTargetView.Get(),
reinterpret_cast<const float*>(&Colors::Silver));
_deviceContext->ClearDepthStencilView(_depthStencilView.Get(),
D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
DrawScene(_camera, true); HR(_swapChain->Present(0, 0));
'C++ Algorithm & Study > Game Math & DirectX 11' 카테고리의 다른 글
[Direct11] 38. 3D Direct Application - Displacement Mapping (0) | 2023.06.30 |
---|---|
[Direct11] 37. 3D Direct Application - Normal Mapping (0) | 2023.06.30 |
[Direct11] 35. 3D Direct Application - Cube Mapping System (0) | 2023.06.27 |
[Direct11] 34. 3D Direct Application - Picking System (0) | 2023.06.27 |
[Direct11] 33. 3D Direct Application - Instancing & Culling (0) | 2023.06.26 |