- 멀티 렌더타겟은 CCTV같이 화면 안에 화면을 표현할 때 주로 사용되는 기술이다.
- 하나 더 주요한 기능은 텍스쳐에 정보를 저장할 수 있다는 것인데,
- 원래 기존에 픽셀 쉐이더의 결과물이 단순히 색상값이었다면,
- 멀티 렌더타겟을 통해 텍스쳐에 픽셀 쉐이더의 결과를 저장하면 이후에 이 텍스쳐를 통해 그 정보를 재사용할 수 있다.
- 어떤 이점이 있는가?
- A라는 정보를 B, C, D라는 텍스쳐에 적용하고 싶은데 각각 적용하려면 전부 렌더링파이프라인을 처음부터 거쳐서 하나 하나 처리해야 한다.
- 그런데 텍스쳐에 저장해놓으면 한 번 계산된 값을 돌려쓸 수 있는 장점이 생겨서 성능 향상에 도움이 된다.
- 이런 기법을 Deferred Rendering 기법이라고 하고, 기존에 우리가 사용한 방법은 Forward Rendering이라고 한다.
struct PS_OUT
{
float4 position : SV_Target0;
float4 normal : SV_Target1;
float4 color : SV_Target2;
};
PS_OUT PS_Main(VS_OUT input)
{
PS_OUT output = (PS_OUT) 0;
float4 color = float4(1.f, 1.f, 1.f, 1.f);
if (g_tex_on_0)
color = g_tex_0.Sample(g_sam_0, input.uv);
float3 viewNormal = input.viewNormal;
if (g_tex_on_1)
{
// [0~255] 범위에서 [0~1]로 변환
float3 tangentSpaceNormal = g_tex_1.Sample(g_sam_0, input.uv).xyz;
// [0~1]을 [-1~1] 범위로 변환
tangentSpaceNormal = (tangentSpaceNormal - 0.5f) * 2.f;
// 좌표계 변환 행렬 계산
float3x3 matTBN = { input.viewTangent, input.viewBinormal, input.viewNormal };
viewNormal = normalize(mul(tangentSpaceNormal, matTBN));
}
output.position = float4(input.viewPos.xyz, 0.f);
output.normal = float4(viewNormal.xyz, 0.f);
output.color = color;
return output;
}
- PS_OUT이라는 구조체에 위치값, 노멀값, 색상값을 저장해서 반환하면 그 텍스쳐에 해당 정보가 그려진다.
#pragma region UI_Test
for (int i = 0; i < 3; ++i)
{
shared_ptr<GameObject> sphere = make_shared<GameObject>();
sphere->SetLayerIndex(GET_SINGLE(SceneManager)->LayerNameToIndex(L"UI"));
sphere->AddComponent(make_shared<Transform>());
sphere->GetTransform()->SetLocalScale(Vec3(100.f, 100.f, 100.f));
sphere->GetTransform()->SetLocalPosition(Vec3(-350.f + (i * 160), 250.f, 500.f));
shared_ptr<MeshRenderer> meshRenderer = make_shared<MeshRenderer>();
{
shared_ptr<Mesh> mesh = GET_SINGLE(Resources)->LoadRectangleMesh();
meshRenderer->SetMesh(mesh);
}
{
shared_ptr<Shader> shader = GET_SINGLE(Resources)->Get<Shader>(L"Forward");
shared_ptr<Texture> texture = GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::G_BUFFER)->GetRTTexture(i);
shared_ptr<Material> material = make_shared<Material>();
material->SetShader(shader);
material->SetTexture(0, texture);
meshRenderer->SetMaterial(material);
}
sphere->AddComponent(meshRenderer);
scene->AddGameObject(sphere);
}
#pragma endregion
- UI Test라는 항목에 Texture를 세팅하는 부분에 보면 여기서는 화면에 그려질 이미지를 저장한 텍스쳐를 넣어주는 것을 알 수 있다.
- 그래서 실행해보면 이 UI 3개 항목에 화면의 특정 정보가 그려지는 것을 확인할 수 있다.
이 작업을 하면서 기존에 SwapChain에서 관리하던 RenderTargetView와, DepthStencilBuffer 클래스에서 관리하는 내용들을 전부 RenderTargetGroup이라는 클래스에서 관리하게 되었다.
Texture는 그냥 사이즈와 타입만 가지고 화면 사이즈의 픽셀덩어리를 생성할 수 있게끔 Create라는 함수를 내부적으로 가지고 있게 되었고,
또 별도로 SwapChain을 생성하면 함께 동봉되는 Texture를 받아서 사용할 수 있도록 CreateFromResource 함수를 만들었다.
이걸 Resource Manager에서도 바로 적용할 수 있도록 함수를 래핑해서 Resource Manager에도 추가해주었다.
public:
// 디퍼드 쉐이더에서 각종 값들을 받아줄 텍스쳐를 로드하는건 좀 오바니까
// 만들어서 사용하기 위한 함수
void Create(DXGI_FORMAT format, uint32 width, uint32 height,
const D3D12_HEAP_PROPERTIES& heapProperty, D3D12_HEAP_FLAGS heapFlags,
D3D12_RESOURCE_FLAGS resFlags, Vec4 clearColor = Vec4());
// 리소스를 받아서 텍스쳐를 만들어주는 경우 (스왑 체인같은 경우)
// SwapChain의 경우 내부에 리소스가 생성되서 그걸 받아와서 사용했음
// 그 리소스를 받아서 텍스쳐 인스턴스를 생성하는 함수
void CreateFromResource(ComPtr<ID3D12Resource> tex2D);
- 그리는 순서는 Scene의 Render에서 우선 G_BUFFER에 그리고 나서, (정보를 담는 버퍼)
- SwapChain의 후면 버퍼에 그린다.
void Scene::Render()
{
PushLightData();
int8 backIndex = GEngine->GetSwapChain()->GetBackBufferIndex();
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::SWAP_CHAIN)->ClearRenderTargetView(backIndex);
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::G_BUFFER)->ClearRenderTargetView();
for (auto& gameObject : _gameObjects)
{
if (nullptr == gameObject->GetCamera())
continue;
gameObject->GetCamera()->SortGameObject();
// Deferred OMSet
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::G_BUFFER)->OMSetRenderTargets();
gameObject->GetCamera()->Render_Deferred();
// Light OMSet
// SwapChain OMSet
GEngine->GetRTGroup(RENDER_TARGET_GROUP_TYPE::SWAP_CHAIN)->OMSetRenderTargets(1, backIndex);
gameObject->GetCamera()->Render_Forward();
}
}
'DirectX > [Inflearn_rookiss] Part2: DirectX12' 카테고리의 다른 글
26. Particle System_1 (0) | 2023.02.13 |
---|---|
25. Compute Shader (0) | 2023.02.12 |
23. Orthographic Projection (0) | 2023.02.02 |
22. Quaternion - 개념과 사용 방법 (0) | 2023.02.01 |
21. Quaternion - 로드리게스 회전 (0) | 2023.01.31 |
댓글