카메라 좌표계, 투영 좌표계
Depth에 따라 그려야할 부분 그리지 않아야 할 부분을 구분할 수 있다.
참고로 현재는
void Game::Init(const WindowInfo& info)
{
GEngine->Init(info);
vector<Vertex> vec(4);
vec[0].pos = Vec3(-0.5f, 0.5f, 0.5f); // 세 번째 float이 depth값
vec[0].color = Vec4(1.f, 0.f, 0.f, 1.f);
vec[0].uv = Vec2(0.f, 0.f);
// ...
이런식으로 pos의 세 번째 float을 depth로 받고있지만 사용은 하지 않고 있다.
네모를 두 개 그리고 depth값에 따라 어떤 네모가 앞에 혹은 뒤에 오는지 살펴보자.
Stencil 이란?
- 판에 구멍을 뚫고 잉크를 통과시켜 찍어내는 공판화 기법
- 특정 Stencil 값에 따라 픽셀을 어떻게 처리하겠다 이런 처리가 가능
- 예를 들어 Stencil 값이 5인 pixel은 특정색을 입히겠다. 이런 연산이 가능해진다.
- 알아만 두자, 강좌에서 쓰진 않을 것
우선 네모를 두 개 그려보자.
VS_OUT VS_Main(VS_IN input)
{
VS_OUT output = (VS_OUT)0;
output.pos = float4(input.pos, 1.f);
// 참고로 depth값을 무조건 1로 만들고 있음을 보인다.
output.pos += offset0;
output.color = input.color;
output.uv = input.uv;
return output;
}
void Game::Update()
{
GEngine->RenderBegin();
shader->Update();
{
Transform t;
t.offset = Vec4(0.25f, 0.25f, 0.2f, 0.f);
mesh->SetTransform(t);
mesh->SetTexture(texture);
mesh->Render();
}
{
Transform t;
t.offset = Vec4(0.f, 0.f, 0.3f, 0.f);
mesh->SetTransform(t);
mesh->SetTexture(texture);
mesh->Render();
}
GEngine->RenderEnd();
}
이렇게 하면 두 개의 네모가 출력됨.
이제 depth에 따라 네모를 다르게 출력하게 해보자.
DepthStencilBuffer 클래스
#pragma once
class DepthStencilBuffer
{
public:
void Init(const WindowInfo& window, DXGI_FORMAT dsvFormat = DXGI_FORMAT_D32_FLOAT);
D3D12_CPU_DESCRIPTOR_HANDLE GetDSVCpuHandle() { return _dsvHandle; }
DXGI_FORMAT GetDSVFormat() { return _dsvFormat; }
private:
// Depth Stencil View
ComPtr<ID3D12Resource> _dsvBuffer;
ComPtr<ID3D12DescriptorHeap> _dsvHeap;
D3D12_CPU_DESCRIPTOR_HANDLE _dsvHandle = {};
DXGI_FORMAT _dsvFormat = {};
};
#include "pch.h"
#include "DepthStencilBuffer.h"
#include "Engine.h"
void DepthStencilBuffer::Init(const WindowInfo& window, DXGI_FORMAT dsvFormat)
{
_dsvFormat = dsvFormat;
D3D12_HEAP_PROPERTIES heapProperty = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT);
D3D12_RESOURCE_DESC desc = CD3DX12_RESOURCE_DESC::Tex2D(_dsvFormat, window.width, window.height);
desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
D3D12_CLEAR_VALUE optimizedClearValue = CD3DX12_CLEAR_VALUE(_dsvFormat, 1.0f, 0);
DEVICE->CreateCommittedResource(
&heapProperty,
D3D12_HEAP_FLAG_NONE,
&desc,
D3D12_RESOURCE_STATE_DEPTH_WRITE,
&optimizedClearValue,
IID_PPV_ARGS(&_dsvBuffer));
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
heapDesc.NumDescriptors = 1;
heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
DEVICE->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&_dsvHeap));
_dsvHandle = _dsvHeap->GetCPUDescriptorHandleForHeapStart();
DEVICE->CreateDepthStencilView(_dsvBuffer.Get(), nullptr, _dsvHandle);
}
void CommandQueue::RenderBegin(const D3D12_VIEWPORT* vp, const D3D12_RECT* rect)
{
// ...
// DepthStencil
D3D12_CPU_DESCRIPTOR_HANDLE depthStencilView = GEngine->GetDepthStencilBuffer()->GetDSVCpuHandle();
_cmdList->OMSetRenderTargets(1, &backBufferView, FALSE, &depthStencilView);
// DepthStencil을 기본적으로 1로 밀어줌
_cmdList->ClearDepthStencilView(depthStencilView, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
}
void Shader::Init(const wstring& path)
{
CreateVertexShader(path, "VS_Main", "vs_5_0");
CreatePixelShader(path, "PS_Main", "ps_5_0");
D3D12_INPUT_ELEMENT_DESC desc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
};
_pipelineDesc.InputLayout = { desc, _countof(desc) };
_pipelineDesc.pRootSignature = ROOT_SIGNATURE.Get();
_pipelineDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
_pipelineDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
// DepthStencil을 쓴다고 선언
_pipelineDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
_pipelineDesc.SampleMask = UINT_MAX;
_pipelineDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
_pipelineDesc.NumRenderTargets = 1;
_pipelineDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
_pipelineDesc.SampleDesc.Count = 1;
// DepthStencil Format도 받아온다.
_pipelineDesc.DSVFormat = GEngine->GetDepthStencilBuffer()->GetDSVFormat();
DEVICE->CreateGraphicsPipelineState(&_pipelineDesc, IID_PPV_ARGS(&_pipelineState));
}
#include "pch.h"
#include "Game.h"
#include "Engine.h"
shared_ptr<Mesh> mesh = make_shared<Mesh>();
shared_ptr<Shader> shader = make_shared<Shader>();
shared_ptr<Texture> texture = make_shared<Texture>();
void Game::Init(const WindowInfo& info)
{
GEngine->Init(info);
vector<Vertex> vec(4);
vec[0].pos = Vec3(-0.5f, 0.5f, 0.5f);
vec[0].color = Vec4(1.f, 0.f, 0.f, 1.f);
vec[0].uv = Vec2(0.f, 0.f);
vec[1].pos = Vec3(0.5f, 0.5f, 0.5f);
vec[1].color = Vec4(0.f, 1.f, 0.f, 1.f);
vec[1].uv = Vec2(1.f, 0.f);
vec[2].pos = Vec3(0.5f, -0.5f, 0.5f);
vec[2].color = Vec4(0.f, 0.f, 1.f, 1.f);
vec[2].uv = Vec2(1.f, 1.f);
vec[3].pos = Vec3(-0.5f, -0.5f, 0.5f);
vec[3].color = Vec4(0.f, 1.f, 0.f, 1.f);
vec[3].uv = Vec2(0.f, 1.f);
vector<uint32> indexVec;
{
indexVec.push_back(0);
indexVec.push_back(1);
indexVec.push_back(2);
}
{
indexVec.push_back(0);
indexVec.push_back(2);
indexVec.push_back(3);
}
mesh->Init(vec, indexVec);
shader->Init(L"..\\Resources\\Shader\\default.hlsli");
texture->Init(L"..\\Resources\\Texture\\veigar.jpg");
GEngine->GetCmdQueue()->WaitSync();
}
void Game::Update()
{
GEngine->RenderBegin();
shader->Update();
{
Transform t;
t.offset = Vec4(0.25f, 0.25f, 0.2f, 0.f);
mesh->SetTransform(t);
mesh->SetTexture(texture);
mesh->Render();
}
{
Transform t;
t.offset = Vec4(0.f, 0.f, 0.3f, 0.f);
mesh->SetTransform(t);
mesh->SetTexture(texture);
mesh->Render();
}
GEngine->RenderEnd();
}