[DirectX11] 103 MRT(Multiple Render Targets)
MRT(Multiple Render Targets)는 한 번의 추첨 통화에서 둘 이상의 렌더 대상에 렌더링할 수 있는 기능을 말한다. 기존 렌더링 파이프라인에서는 하나의 렌더링 대상(백 버퍼)만 사용하여 화면에 최종 결과를 표시한다. 그러나 복잡한 후 처리 효과를 구현하거나 지연된 렌더링 기법을 구현하거나 섀도 매핑을 수행하는 경우와 같이 여러 렌더 대상에 동시에 렌더링해야 하는 상황이 있다.
목차
MRT(Multiple Render Targets)
MRT(Multiple Render Targets)는 한 번의 추첨 통화에서 둘 이상의 렌더 대상에 렌더링할 수 있는 기능을 말한다.
기존 렌더링 파이프라인에서는 하나의 렌더링 대상(백 버퍼)만 사용하여 화면에 최종 결과를 표시한다. 그러나 복잡한 후 처리 효과를 구현하거나 지연된 렌더링 기법을 구현하거나 섀도 매핑을 수행하는 경우와 같이 여러 렌더 대상에 동시에 렌더링해야 하는 상황이 있다.
MRT를 사용하면 RTV(Render Target View)를 그래픽 파이프라인의 출력 병합 단계에 바인딩할 때 여러 렌더 대상을 지정할 수 있다. 렌더링 시 픽셀 셰이더의 출력이 지정된 모든 렌더링 대상에 동시에 기록된다. 이를 통해 특정 효과를 달성하는 데 필요한 추첨 통화 수를 크게 줄여 성능을 향상시킬 수 있다.
DirectX11에서 MRT를 사용하려면 원하는 렌더 대상 수에 대해 여러 렌더 대상 뷰를 만들어야 한다. 그런 다음 ID3D11 DeviceContext:를 사용하여 이러한 렌더 대상 뷰를 출력 병합 단계로 설정한다. 렌더링 시 픽셀 셰이더의 출력을 셰이더 코드의 SV_Target 의미를 사용하여 지정된 렌더 대상에 쓸 수 있다.
MRT는복잡한 장면과 후처리 효과를 보다 효율적으로 렌더링할 수 있다.
Shaders | |
Mrt.fx 생성 | |
Framework | |
Viewer | |
RenderTarget.h .cpp | |
UnitTest | |
PostEffects | |
MrtDemo.h .cpp 생성 |
Mrt.fx
Mrt.fx
#include "00_Global.fx" #include "00_Light.fx" float2 PixelSize; struct VertexOutput { float4 Position : SV_Position; float2 Uv : Uv; }; VertexOutput VS(float4 Position : Position) { VertexOutput output; output.Position = Position; output.Uv.x = Position.x * 0.5f + 0.5f; output.Uv.y = -Position.y * 0.5f + 0.5f; return output; } struct PixelOutput { float4 Color0 : SV_Target0; float4 Color1 : SV_Target1; float4 Color2 : SV_Target2; }; PixelOutput PS_Mrt(VertexOutput input) { PixelOutput output; output.Color0 = DiffuseMap.Sample(LinearSampler, input.Uv); output.Color1 = 1 - DiffuseMap.Sample(LinearSampler, input.Uv); float3 color = DiffuseMap.Sample(LinearSampler, input.Uv).rgb; float average = (color.r + color.g + color.b) / 3.0f; output.Color2 = float4(average, average, average, 1.0f); return output; } float4 PS(VertexOutput input) : SV_Target { return DiffuseMap.Sample(LinearSampler, input.Uv);; } technique11 T0 { P_VP(P0, VS, PS_Mrt) P_VP(P1, VS, PS) }
RenderTarget
RenderTarget.h
#pragma once class RenderTarget { public: RenderTarget(UINT width = 0, UINT height = 0, DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM); ~RenderTarget(); ID3D11RenderTargetView* RTV() { return rtv; } ID3D11ShaderResourceView* SRV() { return srv; } void SaveTexture(wstring file); void PreRender(class DepthStencil* depthStencil); static void PreRender(RenderTarget** targets, UINT count, class DepthStencil* depthStencil); private: UINT width, height; DXGI_FORMAT format; ID3D11Texture2D* texture; ID3D11RenderTargetView* rtv; ID3D11ShaderResourceView* srv; };
함수 추가
- static void PreRender(RenderTarget** targets, UINT count, class DepthStencil* depthStencil)
RenderTarget.cpjp
#include "Framework.h" #include "RenderTarget.h" RenderTarget::RenderTarget(UINT width, UINT height, DXGI_FORMAT format) : format(format) { this->width = (width < 1) ? (UINT)D3D::Width() : width; this->height = (height < 1) ? (UINT)D3D::Height() : height; D3D11_TEXTURE2D_DESC textureDesc; ZeroMemory(&textureDesc, sizeof(D3D11_TEXTURE2D_DESC)); textureDesc.Width = this->width; textureDesc.Height = this->height; textureDesc.ArraySize = 1; textureDesc.Format = format; textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; textureDesc.MipLevels = 1; textureDesc.SampleDesc.Count = 1; Check(D3D::GetDevice()->CreateTexture2D(&textureDesc, NULL, &texture)); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; ZeroMemory(&rtvDesc, sizeof(D3D11_RENDER_TARGET_VIEW_DESC)); rtvDesc.Format = format; rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; Check(D3D::GetDevice()->CreateRenderTargetView(texture, &rtvDesc, &rtv)); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; ZeroMemory(&srvDesc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); srvDesc.Format = format; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MipLevels = 1; Check(D3D::GetDevice()->CreateShaderResourceView(texture, &srvDesc, &srv)); } RenderTarget::~RenderTarget() { SafeRelease(texture); SafeRelease(rtv); SafeRelease(srv); } void RenderTarget::SaveTexture(wstring file) { Check(D3DX11SaveTextureToFile(D3D::GetDC(), texture, D3DX11_IFF_PNG, file.c_str())); } void RenderTarget::PreRender(DepthStencil * depthStencil) { D3D::GetDC()->OMSetRenderTargets(1, &rtv, depthStencil->DSV()); D3D::Get()->Clear(Color(0, 0, 0, 1), rtv, depthStencil->DSV()); } void RenderTarget::PreRender(RenderTarget ** targets, UINT count, DepthStencil * depthStencil) { vector<ID3D11RenderTargetView *> rtvs; for (UINT i = 0; i < count; i++) { ID3D11RenderTargetView* rtv = targets[i]->RTV(); rtvs.push_back(rtv); D3D::GetDC()->ClearRenderTargetView(rtv, Color(0, 0, 0, 1)); } D3D::GetDC()->ClearDepthStencilView(depthStencil->DSV(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0); D3D::GetDC()->OMSetRenderTargets(rtvs.size(), &rtvs[0], depthStencil->DSV()); }
함수 정의
- void RenderTarget::PreRender(RenderTarget ** targets, UINT count, DepthStencil * depthStencil)
MrtDemo
MrtDemo.h
#pragma once #include "Systems/IExecute.h" class MrtDemo : public IExecute { public: virtual void Initialize() override; virtual void Ready() override {} virtual void Destroy() override {} virtual void Update() override; virtual void PreRender() override; virtual void Render() override; virtual void PostRender() override; virtual void ResizeScreen() override {} private: void Billboards(); void Mesh(); void Airplane(); void Kachujin(); void KachujinCollider(); void KachujinWeapon(); void PointLighting(); void SpotLighting(); void Pass(UINT mesh, UINT model, UINT anim); private: Shader* shader; RenderTarget* renderTarget; RenderTarget* mrt[3]; DepthStencil* depthStencil; Viewport* viewport; Render2D* render2D; PostEffect* postEffect; Billboard* billboard; CubeSky* sky; Material* floor; Material* stone; Material* brick; Material* wall; MeshRender* cube; MeshRender* cylinder; MeshRender* sphere; MeshRender* grid; ModelRender* airplane = NULL; ModelAnimator* kachujin = NULL; Transform* colliderInitTransforms; ColliderObject** colliders; ModelRender* weapon = NULL; Transform* weaponInitTransform; vector<MeshRender *> meshes; vector<ModelRender *> models; vector<ModelAnimator *> animators; };
MrtDemo.cpp
#include "stdafx.h" #include "MrtDemo.h" void MrtDemo::Initialize() { Context::Get()->GetCamera()->RotationDegree(20, 0, 0); Context::Get()->GetCamera()->Position(1, 36, -85); ((Freedom *)Context::Get()->GetCamera())->Speed(50, 2); shader = new Shader(L"96_Billboard.fxo"); float width = D3D::Width(), height = D3D::Height(); width = height = 4096; renderTarget = new RenderTarget((UINT)width, (UINT)height); mrt[0] = new RenderTarget((UINT)width, (UINT)height); mrt[1] = new RenderTarget((UINT)width, (UINT)height); mrt[2] = new RenderTarget((UINT)width, (UINT)height); depthStencil = new DepthStencil((UINT)width, (UINT)height); viewport = new Viewport(width, height); render2D = new Render2D(); render2D->GetTransform()->Scale(355, 200, 1); render2D->GetTransform()->Position(200, 120, 0); postEffect = new PostEffect(L"103_Mrt.fxo"); postEffect->SRV(renderTarget->SRV()); sky = new CubeSky(L"Environment/GrassCube1024.dds"); Billboards(); Mesh(); Airplane(); Kachujin(); KachujinCollider(); KachujinWeapon(); PointLighting(); SpotLighting(); } void MrtDemo::Update() { sky->Update(); cube->Update(); grid->Update(); cylinder->Update(); sphere->Update(); airplane->Update(); kachujin->Update(); Matrix worlds[MAX_MODEL_TRANSFORMS]; for (UINT i = 0; i < kachujin->GetTransformCount(); i++) { kachujin->GetAttachTransform(i, worlds); weapon->GetTransform(i)->World(weaponInitTransform->World() * worlds[40]); } weapon->UpdateTransforms(); weapon->Update(); billboard->Update(); render2D->Update(); postEffect->Update(); } void MrtDemo::PreRender() { renderTarget->PreRender(depthStencil); viewport->RSSetViewport(); //Render { sky->Render(); Pass(0, 1, 2); wall->Render(); sphere->Render(); brick->Render(); cylinder->Render(); stone->Render(); cube->Render(); floor->Render(); grid->Render(); airplane->Render(); kachujin->Render(); weapon->Render(); billboard->Render(); } //Mrt { RenderTarget::PreRender(mrt, 3, depthStencil); viewport->RSSetViewport(); postEffect->SRV(renderTarget->SRV()); postEffect->Render(); } } void MrtDemo::Render() { } void MrtDemo::PostRender() { static UINT index = 0; ImGui::InputInt("Mrt Index", (int *)&index); index %= 3; postEffect->SRV(mrt[index]->SRV()); postEffect->Render(); render2D->SRV(renderTarget->SRV()); render2D->Render(); } void MrtDemo::Billboards() { billboard = new Billboard(shader); //billboard->Pass(3); billboard->Pass(4); billboard->AddTexture(L"Terrain/grass_14.tga"); billboard->AddTexture(L"Terrain/grass_07.tga"); billboard->AddTexture(L"Terrain/grass_11.tga"); for (UINT i = 0; i < 1200; i++) { Vector2 scale = Math::RandomVec2(1, 3); Vector2 position = Math::RandomVec2(-60, 60); billboard->Add(Vector3(position.x, scale.y * 0.5f, position.y), scale, 0); } for (UINT i = 0; i < 300; i++) { Vector2 scale = Math::RandomVec2(1, 3); Vector2 position = Math::RandomVec2(-60, 60); billboard->Add(Vector3(position.x, scale.y * 0.5f, position.y), scale, 1); } for (UINT i = 0; i < 700; i++) { Vector2 scale = Math::RandomVec2(1, 3); Vector2 position = Math::RandomVec2(-60, 60); billboard->Add(Vector3(position.x, scale.y * 0.5f, position.y), scale, 2); } } void MrtDemo::Mesh() { //Create Material { floor = new Material(shader); floor->DiffuseMap("Floor.png"); floor->Specular(1, 1, 1, 20); floor->SpecularMap("Floor_Specular.png"); floor->NormalMap("Floor_Normal.png"); stone = new Material(shader); stone->DiffuseMap("Stones.png"); stone->Specular(1, 1, 1, 20); stone->SpecularMap("Stones_Specular.png"); stone->Emissive(0.15f, 0.15f, 0.15f, 0.3f); stone->NormalMap("Stones_Normal.png"); brick = new Material(shader); brick->DiffuseMap("Bricks.png"); brick->Specular(1, 0.3f, 0.3f, 20); brick->SpecularMap("Bricks_Specular.png"); brick->Emissive(0.15f, 0.15f, 0.15f, 0.3f); brick->NormalMap("Bricks_Normal.png"); wall = new Material(shader); wall->DiffuseMap("Wall.png"); wall->Specular(1, 1, 1, 20); wall->SpecularMap("Wall_Specular.png"); wall->Emissive(0.15f, 0.15f, 0.15f, 0.3f); wall->NormalMap("Wall_Normal.png"); } //Create Mesh { Transform* transform = NULL; cube = new MeshRender(shader, new MeshCube()); transform = cube->AddTransform(); transform->Position(0, 5, 0); transform->Scale(20, 10, 20); grid = new MeshRender(shader, new MeshGrid(5, 5)); transform = grid->AddTransform(); transform->Position(0, 0, 0); transform->Scale(12, 1, 12); cylinder = new MeshRender(shader, new MeshCylinder(0.5f, 3.0f, 20, 20)); sphere = new MeshRender(shader, new MeshSphere(0.5f, 20, 20)); for (UINT i = 0; i < 5; i++) { transform = cylinder->AddTransform(); transform->Position(-30, 6, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); transform = cylinder->AddTransform(); transform->Position(30, 6, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); transform = sphere->AddTransform(); transform->Position(-30, 15.5f, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); transform = sphere->AddTransform(); transform->Position(30, 15.5f, -15.0f + (float)i * 15.0f); transform->Scale(5, 5, 5); } } sphere->UpdateTransforms(); cylinder->UpdateTransforms(); cube->UpdateTransforms(); grid->UpdateTransforms(); meshes.push_back(sphere); meshes.push_back(cylinder); meshes.push_back(cube); meshes.push_back(grid); } void MrtDemo::Airplane() { airplane = new ModelRender(shader); airplane->ReadMesh(L"B787/Airplane"); airplane->ReadMaterial(L"B787/Airplane"); Transform* transform = airplane->AddTransform(); transform->Position(2.0f, 9.91f, 2.0f); transform->Scale(0.004f, 0.004f, 0.004f); airplane->UpdateTransforms(); models.push_back(airplane); } void MrtDemo::Kachujin() { kachujin = new ModelAnimator(shader); kachujin->ReadMesh(L"Kachujin/Mesh"); kachujin->ReadMaterial(L"Kachujin/Mesh"); kachujin->ReadClip(L"Kachujin/Sword And Shield Idle"); kachujin->ReadClip(L"Kachujin/Sword And Shield Walk"); kachujin->ReadClip(L"Kachujin/Sword And Shield Run"); kachujin->ReadClip(L"Kachujin/Sword And Shield Slash"); kachujin->ReadClip(L"Kachujin/Salsa Dancing"); Transform* transform = NULL; transform = kachujin->AddTransform(); transform->Position(0, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(0, 0, 1.0f); transform = kachujin->AddTransform(); transform->Position(-15, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(1, 1, 1.0f); transform = kachujin->AddTransform(); transform->Position(-30, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(2, 2, 0.75f); transform = kachujin->AddTransform(); transform->Position(15, 0, -30); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayBlendMode(3, 0, 1, 2); kachujin->SetBlendAlpha(3, 1.5f); transform = kachujin->AddTransform(); transform->Position(30, 0, -32.5f); transform->Scale(0.075f, 0.075f, 0.075f); kachujin->PlayTweenMode(4, 4, 0.75f); kachujin->UpdateTransforms(); animators.push_back(kachujin); } void MrtDemo::KachujinCollider() { UINT count = kachujin->GetTransformCount(); colliders = new ColliderObject*[count]; colliderInitTransforms = new Transform(); colliderInitTransforms->Position(-2.9f, 1.45f, -50.0f); colliderInitTransforms->Scale(5, 5, 75); for (UINT i = 0; i < count; i++) { colliders[i] = new ColliderObject(); //colliders[i]->Init = new Transform(); //colliders[i]->Init->Position(0, 0, 0); //colliders[i]->Init->Scale(10, 30, 10); colliders[i]->Transform = new Transform(); //colliders[i]->Collider = new Collider(colliders[i]->Transform, colliders[i]->Init); colliders[i]->Collider = new Collider(colliders[i]->Transform, colliderInitTransforms); } } void MrtDemo::KachujinWeapon() { weapon = new ModelRender(shader); weapon->ReadMesh(L"Weapon/Sword"); weapon->ReadMaterial(L"Weapon/Sword"); UINT count = kachujin->GetTransformCount(); for (UINT i = 0; i < count; i++) weapon->AddTransform(); weapon->UpdateTransforms(); models.push_back(weapon); weaponInitTransform = new Transform(); weaponInitTransform->Position(-2.9f, 1.45f, -6.45f); weaponInitTransform->Scale(0.5f, 0.5f, 0.75f); weaponInitTransform->Rotation(0, 0, 1); } void MrtDemo::PointLighting() { PointLight light; light = { Color(0.0f, 0.0f, 0.0f, 1.0f), //Ambient Color(0.0f, 0.0f, 1.0f, 1.0f), //Diffuse Color(0.0f, 0.0f, 0.7f, 1.0f), //Specular Color(0.0f, 0.0f, 0.7f, 1.0f), //Emissive Vector3(-30, 10, -30), 5.0f, 0.9f }; Lighting::Get()->AddPointLight(light); light = { Color(0.0f, 0.0f, 0.0f, 1.0f), Color(1.0f, 0.0f, 0.0f, 1.0f), Color(0.6f, 0.2f, 0.0f, 1.0f), Color(0.6f, 0.3f, 0.0f, 1.0f), Vector3(15, 10, -30), 10.0f, 0.3f }; Lighting::Get()->AddPointLight(light); light = { Color(0.0f, 0.0f, 0.0f, 1.0f), //Ambient Color(0.0f, 1.0f, 0.0f, 1.0f), //Diffuse Color(0.0f, 0.7f, 0.0f, 1.0f), //Specular Color(0.0f, 0.7f, 0.0f, 1.0f), //Emissive Vector3(-5, 1, -17.5f), 5.0f, 0.9f }; Lighting::Get()->AddPointLight(light); light = { Color(0.0f, 0.0f, 0.0f, 1.0f), Color(0.0f, 0.0f, 1.0f, 1.0f), Color(0.0f, 0.0f, 0.7f, 1.0f), Color(0.0f, 0.0f, 0.7f, 1.0f), Vector3(-10, 1, -17.5f), 5.0f, 0.9f }; Lighting::Get()->AddPointLight(light); } void MrtDemo::SpotLighting() { SpotLight light; light = { Color(0.3f, 1.0f, 0.0f, 1.0f), Color(0.7f, 1.0f, 0.0f, 1.0f), Color(0.3f, 1.0f, 0.0f, 1.0f), Color(0.3f, 1.0f, 0.0f, 1.0f), Vector3(-15, 20, -30), 25.0f, Vector3(0, -1, 0), 30.0f, 0.4f }; Lighting::Get()->AddSpotLight(light); light = { Color(1.0f, 0.2f, 0.9f, 1.0f), Color(1.0f, 0.2f, 0.9f, 1.0f), Color(1.0f, 0.2f, 0.9f, 1.0f), Color(1.0f, 0.2f, 0.9f, 1.0f), Vector3(0, 20, -30), 30.0f, Vector3(0, -1, 0), 40.0f, 0.55f }; Lighting::Get()->AddSpotLight(light); } void MrtDemo::Pass(UINT mesh, UINT model, UINT anim) { for (MeshRender* temp : meshes) temp->Pass(mesh); for (ModelRender* temp : models) temp->Pass(model); for (ModelAnimator* temp : animators) temp->Pass(anim); }
실행화면

'⭐ DirectX > DirectX11 3D' 카테고리의 다른 글
[DirectX11] 106 Bloom (0) | 2023.05.03 |
---|---|
[DirectX11] 104-105 Blur, Gaussian Blur (0) | 2023.04.28 |
[DirectX11] 099~102 Render Target, Post Effect(Color Tone) (0) | 2023.04.18 |
[DirectX11] 096~98 Geometry Shader (0) | 2023.04.12 |
[DirectX11] 095 Particle Editor (0) | 2023.04.12 |
댓글
이 글 공유하기
다른 글
-
[DirectX11] 106 Bloom
[DirectX11] 106 Bloom
2023.05.03 -
[DirectX11] 104-105 Blur, Gaussian Blur
[DirectX11] 104-105 Blur, Gaussian Blur
2023.04.28 -
[DirectX11] 099~102 Render Target, Post Effect(Color Tone)
[DirectX11] 099~102 Render Target, Post Effect(Color Tone)
2023.04.18 -
[DirectX11] 096~98 Geometry Shader
[DirectX11] 096~98 Geometry Shader
2023.04.12
댓글을 사용할 수 없습니다.