[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