우리가 카메라로 화면을 비추는것. 화면을 2D리소스로 활용할 수 있다.
이러한 RenderTarget은 화면 뷰에 대한 재처리작업을 통해 더 효율적으로 어둡게 만들거나, 색감을 전체적으로 조정하거나 하는데 사용한다.
외곽선처리또한가능하다.
원래 FrameWork에 추가하여 수정해보자.
우선, RenderTager과 DepthStencil을 정의해주는 함수를 작성한다.
#pragma once
// RenderTarget 클래스 정의
class RenderTarget
{
public:
// 생성자: 너비와 높이를 매개변수로 받아 기본값으로 초기화
RenderTarget(UINT width = WIN_WIDTH, UINT height = WIN_HEIGHT);
// 소멸자
~RenderTarget();
// 렌더 타겟 설정 함수
void Set(DepthStencil* depthStencil, Float4 clearColor = Float4(1, 1, 1, 1));
// 렌더 타겟의 렌더 타겟 뷰를 반환하는 함수
ID3D11RenderTargetView*& GetRTV() { return rtv; }
// 렌더 타겟의 셰이더 리소스 뷰를 반환하는 함수
ID3D11ShaderResourceView*& GetSRV() { return srv; }
public:
// 여러 렌더 타겟을 설정하는 정적 멤버 함수
static void SetMulti(RenderTarget** targets, UINT count, DepthStencil* depthStencil, Float4 clearColor = Float4(1, 1, 1, 1));
private:
// 렌더 타겟 텍스처를 생성하는 함수
void CreateRTVTexture();
// 렌더 타겟 뷰를 생성하는 함수
void CreateRTV();
// 셰이더 리소스 뷰를 생성하는 함수
void CreateSRV();
private:
// 렌더 타겟의 너비와 높이를 저장하는 변수
UINT width, height;
// 렌더 타겟 텍스처를 나타내는 변수
ID3D11Texture2D* rtvTexture;
// 렌더 타겟 뷰를 나타내는 변수
ID3D11RenderTargetView* rtv;
// 셰이더 리소스 뷰를 나타내는 변수
ID3D11ShaderResourceView* srv;
};
RenderTarget은 현재 출력되는 메인뷰를 정의해주는 것 으로, View가 정의된 데이터를 확인하고, 해당 View의 사이즈만큼 정의된 후, 데이터를 읽어오는 역할을 한다.
윈도우창의 사이즈가 같아야 한다.
만약, 반절 사이즈를 입력하면 반절만 2Dtexture로 가져올 수 있다.
#include "Framework.h"
// RenderTarget 클래스의 생성자
RenderTarget::RenderTarget(UINT width, UINT height)
: width(width), height(height)
{
// 렌더 타겟 텍스처 생성
CreateRTVTexture();
// 렌더 타겟 뷰 생성
CreateRTV();
// 셰이더 리소스 뷰 생성
CreateSRV();
}
// RenderTarget 클래스의 소멸자
RenderTarget::~RenderTarget()
{
// 생성된 자원들을 해제
rtvTexture->Release();
rtv->Release();
srv->Release();
}
// 렌더 타겟과 깊이 스텐실을 설정하는 함수
void RenderTarget::Set(DepthStencil* depthStencil, Float4 clearColor)
{
// 현재 렌더 타겟 및 깊이 스텐실을 설정
DC->OMSetRenderTargets(1, &rtv, depthStencil->GetDSV());
// 렌더 타겟 클리어
DC->ClearRenderTargetView(rtv, (float*)&clearColor);
// 깊이 스텐실 클리어
depthStencil->Clear();
// 환경 설정 적용
Environment::Get()->Set();
// 뷰포트 설정
Environment::Get()->SetViewport(width, height);
}
// 여러 렌더 타겟을 설정하는 정적 멤버 함수
void RenderTarget::SetMulti(RenderTarget** targets, UINT count, DepthStencil* depthStencil, Float4 clearColor)
{
// 렌더 타겟 뷰를 저장할 벡터 생성
vector<ID3D11RenderTargetView*> rtvs;
// 각 렌더 타겟에 대해 렌더 타겟 뷰를 벡터에 추가하고 클리어
FOR(count)
{
rtvs.push_back(targets[i]->GetRTV());
DC->ClearRenderTargetView(rtvs.back(), (float*)&clearColor);
}
// 깊이 스텐실 클리어
depthStencil->Clear();
// 현재 렌더 타겟들 및 깊이 스텐실을 설정
DC->OMSetRenderTargets(count, rtvs.data(), depthStencil->GetDSV());
// 환경 설정 적용
Environment::Get()->Set();
}
// 렌더 타겟 텍스처를 생성하는 함수
void RenderTarget::CreateRTVTexture()
{
// D3D11_TEXTURE2D_DESC 구조체 초기화
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
// 렌더 타겟 텍스처 생성
DEVICE->CreateTexture2D(&desc, nullptr, &rtvTexture);
}
// 렌더 타겟 뷰를 생성하는 함수
void RenderTarget::CreateRTV()
{
// D3D11_RENDER_TARGET_VIEW_DESC 구조체 초기화
D3D11_RENDER_TARGET_VIEW_DESC desc = {};
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
// 렌더 타겟 뷰 생성
DEVICE->CreateRenderTargetView(rtvTexture, &desc, &rtv);
}
// 셰이더 리소스 뷰를 생성하는 함수
void RenderTarget::CreateSRV()
{
// D3D11_SHADER_RESOURCE_VIEW_DESC 구조체 초기화
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2DArray.MipLevels = 1;
// 셰이더 리소스 뷰 생성
DEVICE->CreateShaderResourceView(rtvTexture, &srvDesc, &srv);
}
정의된 방법대로 RenderTarget을 초기화해준다.
각 WinAPI방식을 따른다.
#pragma once
// 깊이 스텐실(DepthStencil) 클래스 정의
class DepthStencil
{
public:
// 생성자: 너비와 높이, 스텐실 사용 여부를 매개변수로 받아 기본값으로 초기화
DepthStencil(UINT width = WIN_WIDTH, UINT height = WIN_HEIGHT, bool isStencil = false);
// 소멸자
~DepthStencil();
// 깊이 스텐실을 클리어하는 함수
void Clear();
// 깊이 스텐실 뷰를 반환하는 함수
ID3D11DepthStencilView* GetDSV() { return dsv; }
// 셰이더 리소스 뷰를 반환하는 함수
ID3D11ShaderResourceView* GetSRV() { return srv; }
private:
// 깊이 스텐실 텍스처를 생성하는 함수
void CreateDSVTexture();
// 깊이 스텐실 뷰를 생성하는 함수
void CreateDSV();
// 셰이더 리소스 뷰를 생성하는 함수
void CreateSRV();
private:
// 깊이 스텐실의 너비와 높이를 저장하는 변수
UINT width, height;
// 스텐실을 사용할 지 여부를 저장하는 변수
bool isStencil;
// 깊이 스텐실 텍스처를 나타내는 변수
ID3D11Texture2D* dsvTexture;
// 깊이 스텐실 뷰를 나타내는 변수
ID3D11DepthStencilView* dsv;
// 셰이더 리소스 뷰를 나타내는 변수
ID3D11ShaderResourceView* srv;
};
#include "Framework.h"
// DepthStencil 클래스 생성자
DepthStencil::DepthStencil(UINT width, UINT height, bool isStencil)
: width(width), height(height), isStencil(isStencil)
{
// 깊이 스텐실 텍스처 생성
CreateDSVTexture();
// 깊이 스텐실 뷰 생성
CreateDSV();
// 셰이더 리소스 뷰 생성
CreateSRV();
}
// DepthStencil 클래스 소멸자
DepthStencil::~DepthStencil()
{
// 생성된 자원들을 해제
dsvTexture->Release();
dsv->Release();
srv->Release();
}
// 깊이 스텐실을 클리어하는 함수
void DepthStencil::Clear()
{
// 현재 깊이 스텐실 뷰 클리어
DC->ClearDepthStencilView(dsv, D3D11_CLEAR_DEPTH, 1.0f, 0);
}
// 깊이 스텐실 텍스처를 생성하는 함수
void DepthStencil::CreateDSVTexture()
{
// D3D11_TEXTURE2D_DESC 구조체 초기화
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = isStencil ? DXGI_FORMAT_R24G8_TYPELESS : DXGI_FORMAT_R32_TYPELESS;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
// 깊이 스텐실 텍스처 생성
DEVICE->CreateTexture2D(&desc, nullptr, &dsvTexture);
}
// 깊이 스텐실 뷰를 생성하는 함수
void DepthStencil::CreateDSV()
{
// D3D11_DEPTH_STENCIL_VIEW_DESC 구조체 초기화
D3D11_DEPTH_STENCIL_VIEW_DESC depthViewDesc = {};
depthViewDesc.Format = isStencil ? DXGI_FORMAT_D24_UNORM_S8_UINT : DXGI_FORMAT_D32_FLOAT;
depthViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
// 깊이 스텐실 뷰 생성
DEVICE->CreateDepthStencilView(dsvTexture, &depthViewDesc, &dsv);
}
// 셰이더 리소스 뷰를 생성하는 함수
void DepthStencil::CreateSRV()
{
// D3D11_SHADER_RESOURCE_VIEW_DESC 구조체 초기화
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = isStencil ? DXGI_FORMAT_R24_UNORM_X8_TYPELESS : DXGI_FORMAT_R32_FLOAT;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2DArray.MipLevels = 1;
// 셰이더 리소스 뷰 생성
DEVICE->CreateShaderResourceView(dsvTexture, &srvDesc, &srv);
}
깊이뷰를 정의해주는 함수이다.
각 깊이뷰를 정의해주고, 해당 깊이 스텐실에 따라 텍스처를 생성한 뒤, 넘겨주는 역할을 한다.
우리는 렌더 정의부에서 PreRender부분에서 작업을 하고, Device를 초기화해준 다음, 다음 렌더로 넘어갈 것 이다.
OM의 초기화방법이 위와같이 다름으로, Clear시 OM을 초기화할 수 있도록 Deivce함수를 수정해준다.
void Device::Clear()
{
deviceContext->OMSetRenderTargets(1, &renderTargetView, depthStencilView);
float clearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f };
deviceContext->ClearRenderTargetView(renderTargetView, clearColor);
deviceContext->ClearDepthStencilView(depthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
}
Device가 Clear될 때, OM의 RenderTarget을 바꾸어주어야 한다.
각각 다른 뷰포트와 깊이스텐실을 사용하기 때문.
정의가 다 끝났으면, 쉐이더를 만들어보자.
제작할 쉐이더는, Grayscale로 조정하는 쉐이더와 Sepia로 조정하는 쉐이더 이다.
#include "../VertexHeader.hlsli"
#include "../PixelHeader.hlsli"
struct PixelInput
{
float4 pos : SV_POSITION;
float2 uv : UV;
};
PixelInput VS(VertexUV input)
{
PixelInput output;
output.pos = mul(input.pos, world);
output.pos = mul(output.pos, view);
output.pos = mul(output.pos, projection);
output.uv = input.uv;
return output;
}
float4 PS(PixelInput input) : SV_TARGET
{
float4 baseColor = diffuseMap.Sample(samp, input.uv);
//float scale = (baseColor.r + baseColor.g + baseColor.b) / 3;
//float3 grayColor;
//grayColor.r = baseColor.r * 0.3f;
//grayColor.g = baseColor.g * 0.59f;
//grayColor.b = baseColor.b * 0.11f;
//
//float scale = grayColor.r + grayColor.g + grayColor.b;
float scale = dot(baseColor.rgb, float3(0.3f, 0.59f, 0.11f));
return float4(scale.xxx, 1.0f) * mDiffuse;
}
#include "../VertexHeader.hlsli"
#include "../PixelHeader.hlsli"
struct PixelInput
{
float4 pos : SV_POSITION;
float2 uv : UV;
};
PixelInput VS(VertexUV input)
{
PixelInput output;
output.pos = mul(input.pos, world);
output.pos = mul(output.pos, view);
output.pos = mul(output.pos, projection);
output.uv = input.uv;
return output;
}
float4 PS(PixelInput input) : SV_TARGET
{
float4 baseColor = diffuseMap.Sample(samp, input.uv);
float4 sepia = 1;
sepia.r = dot(baseColor.rgb, float3(0.393f, 0.769f, 0.189f));
sepia.g = dot(baseColor.rgb, float3(0.349f, 0.646f, 0.168f));
sepia.b = dot(baseColor.rgb, float3(0.272f, 0.534f, 0.131f));
return sepia * mDiffuse;
}
각각 그레이스케일과 세피아로 조정해주는 쉐이더이다.
rgb에 따른 객체데이터를 일정비율로 조정해주는 것 은. 3개의 색갈이 전부 같게 나와야 하기 때문에, 벡터의 내적과 같은 결과물이 나타난다.
그럼으로, 내적으로 계산해준다.
#include "Framework.h"
#include "RenderTargetScene.h"
RenderTargetScene::RenderTargetScene()
{
CreateObjects();
renderTarget = new RenderTarget();
depthStencil = new DepthStencil();
Texture* target = Texture::Add(L"Target", renderTarget->GetSRV());
targetQuad = new Quad(Float2(WIN_WIDTH, WIN_HEIGHT));
//targetQuad = new Quad();
targetQuad->GetMaterial()->SetShader(L"PostEffect/Sepia.hlsl");
targetQuad->GetMaterial()->SetDiffuseMap(target);
targetQuad->SetLocalPosition({ CENTER_X, CENTER_Y, 0 });
targetQuad->UpdateWorld();
}
RenderTargetScene::~RenderTargetScene()
{
delete quad;
delete model;
delete sphere;
delete targetQuad;
}
void RenderTargetScene::Update()
{
quad->UpdateWorld();
model->UpdateWorld();
sphere->UpdateWorld();
}
void RenderTargetScene::PreRender()
{
renderTarget->Set(depthStencil);
quad->Render();
model->Render();
sphere->Render();
}
void RenderTargetScene::Render()
{
}
void RenderTargetScene::PostRender()
{
targetQuad->Render();
}
void RenderTargetScene::GUIRender()
{
//quad->GUIRender();
//model->GUIRender();
//sphere->GUIRender();
//sphere->GetMaterial()->GUIRender();
targetQuad->GetMaterial()->GUIRender();
}
void RenderTargetScene::CreateObjects()
{
quad = new Quad();
quad->Load();
model = new Model("StanfordBunny");
model->Load();
sphere = new Sphere();
//sphere->GetMaterial()->Load("TextData/Materials/FieldStone.mat");
sphere->Load();
}
이제, scene를 구상하여, 렌더타입을 조정해준다.
우리는 PreRender에서 데이터를 렌더하고, targetQuad를 PostRender를 통해 View에 깊이값을 적용하지 않은 상태에서 렌더 시켜줄 것 이다.
'서울게임아카데미 교육과정 6개월 국비과정' 카테고리의 다른 글
20231214 51일차 ComputerShading (0) | 2023.12.14 |
---|---|
20231213 50일차 ShaderBluer (0) | 2023.12.13 |
20231211 48일차 AnimationInstancing응용7 (0) | 2023.12.11 |
20231208 47일차 AnimationInstancing응용6 (0) | 2023.12.09 |
20231207 46일차 AnimationInstancing응용5 (0) | 2023.12.08 |