필요한 개념
한번의 결과로 여러개의 결과를 얻을 수 있는 MRT에 대해 배운다.
Bloom을 배우기 위해 MRT를 배우지만, MRT는 다른데에서도 쓴다.
한번 렌더링으로 여러 픽셀을 만들고 이를 조합함
디퍼드라고 해서 한번에 계산하는 기법도 있지만, geometry Buffer할때도 MRT해서 씀
00_Render
CB_Perframe에서
float4 Culling[4] -> 퍼스턴 컬링
float4 Clipping -> 반사면, 불 같은거 할때 반사되지 않는 부분 잘라낼려고 씀, stencil 기법으로 보이고 싶지 않은 부분은 가리는데(미술시간에)
가려서 보일 부분만 보이고 싶다.
그런 발전하기 위해 필요한 것이 MRT이다.
MRT(Multi Render Target) : 한 번의 픽셀 셰이더 렌더링으로 여러 개의 장면을 얻어내는 방법
// SV_Target세팅하면 SV_Target0이렇게 세팅된다 -> RenderTarget0번에 세팅한다는 의미
// PixelShader의 SV_Target의 번호와 세팅한 RTV의 번호와 정확히 일치(OMSetRenderTargets() 한 번호와), 즉 1 : 1 순서가 대응된다.
// 이렇게 구조체를 주는 것이 편하다.
struct PixelOutput
{
// 0번째 RenderTarget에 렌더링이 됨
float4 Color0 : SV_Target0;
// 1번째 RenderTarget에 렌더링이 됨
float4 Color1 : SV_Target1;
float4 Color2 : SV_Target2;
};
PixelOutput PS_Diffuse(VertexOutput input) : SV_Target
{
PixelOutput output;
// 원본
output.Color0 = DiffuseMap.Sample(LinearSampler, input.Uv);
// 반전
output.Color1 = 1 - DiffuseMap.Sample(LinearSampler, input.Uv);
// 흑백
float3 color = DiffuseMap.Sample(LinearSampler, input.Uv);
float average = (color.r + color.g + color.b) / 3.0f;
output.Color2 = float4(average, average, average, 1.0f);
return output;
}
이렇게 한번에 렌더링해서 가능하다.
깊이(depth)는 여러개 못쓴다. MRT가 여러개여도 깊이는 1개이다.
RenderTarget.h 추가한 내용
class RenderTarget
{
...
public:
// static 이유는 렌더타킷을 여러개를 세팅할 거니까
// 2차원 배열로 들어감?
static void PreRender(RenderTarget** targets, UINT count, class DepthStencil* depthStencil);
}
RenderTarget.cpp 추가된 내용
...
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);
// depthStencil은 1개 세팅되었고, RTV는 여러개 세팅되었다.(분석 결과)
D3D::GetDC()->OMSetRenderTargets(rtvs.size(), &rtvs[0], depthStencil->DSV());
}
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* postEffect;
Billborad* 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);
shader = new Shader(L"96_Billboard.fxo");
float width = D3D::Width(), height = D3D::Height();
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()
{
// SRV, DSV를 세팅하고 그쪽 backBuffer를 클리어함
// 다른 렌더타킷으로 교체하기까지 여기다가 계속 그려짐
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 Billborad(shader);
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);
// 5(밑에 판 크기가 -5 ~ 5 -> 10) * 12(grid 크기) = 60
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(1.0f, 1.0f, 1.0f, 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(1.0f, 1.0f, 1.0f, 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(1.0f, 1.0f, 1.0f, 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);
}
103_Mrt.fx
#include "00_Global.fx"
#include "00_Light.fx"
float2 PixelSize;
struct VertexOutput
{
float4 Positon : SV_Position;
float2 Uv : Uv;
};
VertexOutput VS(float4 Position : Position)
{
VertexOutput output;
output.Positon = Position;
output.Uv.x = Position.x * 0.5f + 0.5f;
output.Uv.y = -Position.y * 0.5f + 0.5f;
return output;
}
// SV_Target세팅하면 SV_Target0이렇게 세팅된다 -> RenderTarget0번에 세팅한다는 의미
// PixelShader의 SV_Target의 번호와 세팅한 RTV의 번호와 정확히 일치(SetRenderTargets() 한 번호와)
// 이렇게 구조체를 주는 것이 편하다.
struct PixelOutput
{
// 0번째 RenderTarget에 렌더링이 됨
float4 Color0 : SV_Target0;
// 1번째 RenderTarget에 렌더링이 됨
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)
}
결과
'DirectX11 3D > 기본 문법' 카테고리의 다른 글
<DirectX11 3D> 105 - GaussianBlur (0) | 2022.03.22 |
---|---|
<DirectX11 3D> 104 - Blur (0) | 2022.03.22 |
<DirectX11 3D> 100 - ColorTone(PostEffect) (0) | 2022.03.21 |
<DirectX11 3D> 99 - RenderTargetView (0) | 2022.03.17 |
<DirectX11 3D> 96 - GS(Geometry Shader) (0) | 2022.03.16 |