-
[DirectX11] Depth Stencil의 이해와 활용2024년 03월 06일
- 유니얼
-
작성자
-
2024.03.06.:14
728x90DirectX 11로 게임 엔진 아키텍처 만들기
3D 그래픽스와 게임 개발에서, 깊이(depth)와 스텐실(stencil) 버퍼는 시각적 효과를 향상시키고, 렌더링 성능을 최적화하는 데 중요한 역할을 합니다. DirectX11은 이러한 기능을 효율적으로 지원하며, 깊이와 스텐실 처리를 통해 더 사실적이고 복잡한 3D 환경을 구현할 수 있게 해줍니다. 본 글에서는 DirectX11을 사용하여 개발 중인 게임 엔진 아키텍처 내에서 Depth Stencil의 개념을 이해하고, 이를 적용한 예제 코드를 통해 그 활용 방법을 살펴보고자 합니다.
참고강의 링크:
Depth Stencil의 기본 개념
깊이 버퍼(Depth Buffer)
깊이 버퍼는 각 픽셀의 z값(화면으로부터의 깊이)을 저장하는데 사용되며, 이는 3D 씬에서 객체 간의 시각적 순서를 정확하게 결정하는 데 필수적입니다. 즉, 깊이 버퍼는 어떤 객체가 다른 객체보다 더 가까이에 있는지 판단하여, 가려진 객체는 화면에 렌더링되지 않도록 합니다.
스텐실 버퍼(Stencil Buffer)
스텐실 버퍼는 픽셀 단위로 정보를 저장하여 렌더링할 영역을 제어할 수 있습니다. 이를 통해 특정 조건에 따라 픽셀의 렌더링을 허용하거나 차단할 수 있으며, 복잡한 이미지 효과나 마스킹, 포털 등의 특수 효과 구현에 사용됩니다.
DirectX11에서의 Depth Stencil 활용
DirectX11에서 깊이와 스텐실 처리를 위해 ID3D11DepthStencilState 인터페이스를 사용합니다. 이를 통해 깊이 테스트, 스텐실 테스트의 동작 방식을 정의할 수 있고, 렌더링 파이프라인의 해당 단계에서 어떻게 동작할지 제어할 수 있습니다.
예제 코드: Depth Stencil 설정
위 코드는 깊이와 스텐실 테스트를 활성화하고, 깊이 쓰기를 허용하는 설정입니다. 스텐실 테스트는 항상 통과되도록 설정되어 있으며, 스텐실 테스트가 실패했을 때의 동작을 정의하고 있습니다.
void Graphics::CreateDepthStencilView() { { // 깊이 스텐실 텍스처를 위한 설명 구조체 초기화 D3D11_TEXTURE2D_DESC desc = { 0 }; ZeroMemory(&desc, sizeof(desc)); desc.Width = static_cast<uint32>(GAME->GetGameDesc().width); // 텍스처 너비 설정 desc.Height = static_cast<uint32>(GAME->GetGameDesc().height); // 텍스처 높이 설정 desc.MipLevels = 1; // 미맵 레벨 수 (1로 설정하여 미맵 없음) desc.ArraySize = 1; // 텍스처 배열의 크기 (1로 단일 텍스처) desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; // 24비트 깊이와 8비트 스텐실을 위한 포맷 desc.SampleDesc.Count = 1; // 멀티샘플링 설정 (1로 단일 샘플) desc.SampleDesc.Quality = 0; // 샘플 퀄리티 설정 desc.Usage = D3D11_USAGE_DEFAULT; // 텍스처 사용 방식 desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; // 깊이 스텐실 뷰로 바인딩 설정 desc.CPUAccessFlags = 0; // CPU 접근 방식 설정 desc.MiscFlags = 0; // 기타 플래그 설정 // 깊이 스텐실 텍스처 생성 HRESULT hr = DEVICE->CreateTexture2D(&desc, nullptr, _depthStencilTexture.GetAddressOf()); CHECK(hr); // 결과 확인 } { // 깊이 스텐실 뷰 설명 구조체 초기화 D3D11_DEPTH_STENCIL_VIEW_DESC desc; ZeroMemory(&desc, sizeof(desc)); desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; // 깊이 스텐실 포맷 desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; // 뷰 타입 설정 (2D 텍스처) desc.Texture2D.MipSlice = 0; // 사용할 미맵 슬라이스 설정 // 깊이 스텐실 뷰 생성 HRESULT hr = DEVICE->CreateDepthStencilView(_depthStencilTexture.Get(), &desc, _depthStencilView.GetAddressOf()); CHECK(hr); // 결과 확인 } }
프로젝트 호출
DepthStencilDemo.h
#pragma once #include "IExecute.h" #include "Geometry.h" #include "GameObject.h" class DepthStencilDemo : public IExecute { public: void Init() override; void Update() override; void Render() override; shared_ptr<Shader> _shader; //Object shared_ptr<GameObject> _obj; shared_ptr<GameObject> _obj2; shared_ptr<GameObject> _camera; };
DepthStencilDemo.cpp
#include "pch.h" #include "11. DepthStencilDemo.h" #include "GeometryHelper.h" #include "Camera.h" #include "CameraScript.h" #include "Transform.h" #include "Texture.h" #include "ResourceBase.h" #include "MeshRenderer.h" #include "GameObject.h" //#include "RenderManager.h" void DepthStencilDemo::Init() { RESOURCES->Init(); _shader = make_shared<Shader>(L"08. GlobalTest.fx"); // Camera _camera = make_shared<GameObject>(); _camera->GetOrAddTransform()->SetWorldPosition(Vec3{ 0.f, 0.f, -10.f }); _camera->AddComponent(make_shared<Camera>()); _camera->AddComponent(make_shared<CameraScript>()); // Object _obj = make_shared<GameObject>(); _obj->GetOrAddTransform(); _obj->AddComponent(make_shared<MeshRenderer>()); { _obj->GetMeshRenderer()->SetShader(_shader); } { auto mesh = RESOURCES->Get<Mesh>(L"Sphere"); _obj->GetMeshRenderer()->SetMesh(mesh); } { auto texture = RESOURCES->Load<Texture>(L"UnityLogo", L"..\\Resources\\Texture\\UnityLogo.png"); _obj->GetMeshRenderer()->SetTexture(texture); } //Object2 _obj2 = make_shared<GameObject>(); _obj2->GetOrAddTransform()->SetWorldPosition(Vec3{ 0.5f, 0.f, 2.f }); _obj2->AddComponent(make_shared<MeshRenderer>()); { _obj2->GetMeshRenderer()->SetShader(_shader); } { auto mesh = RESOURCES->Get<Mesh>(L"Cube"); _obj2->GetMeshRenderer()->SetMesh(mesh); } { auto texture = RESOURCES->Load<Texture>(L"UnityLogo", L"..\\Resources\\Texture\\UnityLogo.png"); _obj2->GetMeshRenderer()->SetTexture(texture); } // Object RENDER->Init(_shader); } void DepthStencilDemo::Update() { _camera->Update(); RENDER->Update(); _obj->Update(); _obj2->Update(); } void DepthStencilDemo::Render() { }
결론
Depth Stencil 기능은 DirectX11 게임 개발에서 중요한 요소 중 하나입니다. 정확한 깊이 처리를 통해 3D 씬의 사실성을 높이고, 스텐실 버퍼를 활용하여 다양한 그래픽 효과를 구현할 수 있습니다. 이 글을 통해 Depth Stencil의 기본적인 개념을 이해하고, DirectX11에서 이를 어떻게 활용할 수 있는지 알아보았습니다.
반응형다음글이전글이전 글이 없습니다.댓글