본문 바로가기
DirectX11/정보정리

[DirectX11] DirectX3D 초기화(1)

by 마두식 2022. 10. 26.
반응형

※  아래의 내용들은 DirectX 11을 이용한 3D 게임 프로그래밍 입문 책의 내용을 바탕으로 작성된 것입니다.

 

DirectX3D 기본지식
  • Direct3D 개요

-  Direct3D는 응용 프로그램이 3차원 그래픽 가속 기능을 이용해서 3차원 세계를 렌더링할 수 있게 하는 저수준 API이다.
-  본질적으로 Direct3D는 그래픽 하드웨어를 제어할 수 있는 소프트웨어 인터페이스를 제공한다.

 

  • COM(Component Object Model)

-  DirectX의 프로그래맹 언어 독립성과 하위 호환성을 가능하게 하는 기술.
-  COM 객체를 흔히 인터페이스라고 부르며 이 책의 목적에서는 COM 객체를 C++ 클래스로 간주하고 사용한다.
-  C++로 DirectX 응용 프로그램을 프로그래밍 할 때 COM의 세부사항은 대부분 프로그래머에게 드러나지 않는다.
-  COM 인터페이스는 C++의 new 키워드로 생성하지 않는다. 또한, 사용이 끝난 후 delete로 삭제하지 않는다.
-  대신, 사용이 끝난 후 해당 인터페이스의 Release 메서드를 호출해 주어야 한다.
-  COM 객체들이 자신만의 고유한 방식으로 메모리를 관리하기 때문이다.

 

  • 텍스처 형식

-  n차원 텍스처는 자료 원소들의 n차원 배열이다.
-  2차원 텍스처의 한 가지 용도는 2차원 이미지 자료를 저장하는 것으로, 그런 경우 텍스처의 각 원소는 한 픽셀의 색상을 담는다.
-  텍스처라고 하면 흔히 위와 같이 이미지 자료의 저장만을 떠올리지만 그보다는 훨씬 범용적이다.

ex) 법선 매핑이라는 기법에서는 텍스처의 각 원소가 색상이 아니라 3차원 벡터를 담는다.

 

-  텍스처가 단순 자료 배열인 것만은 아니다.

ex) 텍스처에 밉맵 수준들이 존재할 수 있으며, GPU는 필터링, 다중표본화 등의 특별한 연산을 텍스처에 적용할 수 있다.

 

-  텍스처에는 아무 자료나 담을 수 있는 것은 아니다.

특정 형식(format)을 따르는 자료만 담을 수 있으며 구체적인 형식은 DXGI_FORMAT이라는 열거형으로 지정한다.

 

무형식 텍스처 형식도 존재한다.

메모리만 확보해두고 자료의 구체적인 해석 방식은 나중에 텍스처를 파이프라인에 묶을 때 지정한다(C++의 reinterpret_cast 와 유사)

 

  • 교환 사슬과 페이지 전환

-  애니메이션이 깜빡이는 현상을 방지하기 위해 애니메이션의 한 프레임 전체를 화면 바깥의 텍스처에 그린다.

=>  해당 텍스처를 후면 버퍼라고 한다.

 

-  후면 버퍼를 하나의 완전한 프레임으로서 화면에 표시한다.
-  이러한 버퍼링을 구현할 때에는 하드웨어로 두 개의 텍스처 버퍼를 관리한다.

=>  하나는 현재 모니터에 표시되는 이미지 자료를 담는 전면 버퍼, 또 하나는 위에서 말한 후면버퍼.

 

-  즉, 전면 버퍼가 화면에 표시된 동안 후면 버퍼에 애니메이션의 다음 프레임을 그린 후, 전면 버퍼와 후면 버퍼의 역할을 맞바꾼다.
-  후면 버퍼를 전면 버퍼와 교환해서 화면에 표시되게 하는 것을 제시(presenting)라고 부른다.

=>  버퍼의 내용을 서로 맞바꾸는게 아니라 현재 전면 버퍼로의 포인터와 후면 버퍼로의 포인터만 맞바꾸기 때문에 제시는 효율적인 연산이다.

 

-  전면 버퍼와 후면 버퍼는 하나의 교환 사슬(swap chain)을 형성한다.
-  하나의 교환 사슬은 IDXGISwapChain이라는 인터페이스로 대표된다.
-  두 개의 버퍼(전면과 후면)를 사용하는 것을 이중 버퍼링이라고 부른다.

=>  더 많은 버퍼를 사용하는 것도 가능하며, 버퍼 세 개를 사용하는 것을 삼중 버퍼링이라고 부른다.
=>  일반적으로 버퍼 두 개로 충분하다.

 

  • 깊이 버퍼링

-  깊이 버퍼는 이미지 자료를 담지 않는 텍스처의 한 예

=>  깊이 버퍼는 각 픽셀의 깊이 정보를 담는다.
=>  픽셀의 깊이는 0.0에서 1.0까지의 값.
=>  0.0은 관찰자와 최대한 가까운 픽셀, 1.0은 관찰자와 최대한 먼 픽셀

 

-  깊이 버퍼의 원소들과 후면 버퍼의 픽셀들은 일대일로 대응된다.
-  한 물체의 픽셀들이 다른 물체보다 앞에 있는지 판정하기 위해 Direct3D는 깊이 버퍼링 또는 z-버퍼링이라는 기법을 사용한다.
-  깊이 버퍼링에서 물체들을 그리는 순서는 중요하지 않다.

=>  깊이 버퍼링을 사용하면 그리는 순서와 무관하게 물체들이 제대로 가려진다.
=>  깊이 버퍼링은 그래픽 하드웨어에서 공짜로 일어나며 맞물린 물체들에 대한 것도 제대로 처리된다.

 

깊이 버퍼링 알고리즘
1. 렌더링되는 각 픽셀의 깊이 값을 계산해서 깊이 판정 수행
2. 깊이 판정은 후면 버퍼의 특정 픽셀 위치에 기록될 픽셀들의 깊이들을 비교한다.
3. 깊이 값을 비교했을 때, 관찰자에게 가장 가까운 픽셀이 승자가 되어서 후면 버퍼에 기록된다.


-  깊이 버퍼도 하나의 텍스처이므로 특정한 자료 형식을 지정해서 생성해야 한다.

 

  • 텍스처 자원 뷰

-  렌더링 파이프라인에는 텍스처를 묶을(bind) 수 있는 단계들이 여럿 있다

1. 텍스처를 렌더 대상으로 묶는 것(Direct3D가 텍스처에 렌더링하는 경우)

2. 셰이더 자원으로서 묶는 것(셰이더 안에서 텍스처를 추출하는 경우)
위 두 가지 용도의 텍스처 생성 시, 텍스처를 묶을 두 파이프라인 단계를 지정할 결속 플래그(bind flag)를 사용한다.

 

-  어떤 용도이든 Direct3D에서 텍스처를 사용하려면 텍스처의 초기화 시점에 그 텍스처의 자원 뷰를 생성해야 한다.

=>  이렇게 하면 실행시점 모듈(런타임)과 구동기(드라이버)가 유혀성 점검과 매핑을 뷰 생성 시점에서 수행할 수 있기 때문에 결속 시점에서의 형식 점검이 최소화된다.

 

-  텍스처 자원이 파이프라인의 단계에 직접 묶이는 것이 아니라 실제로는 연관된 자원 뷰를 파이프라인 단계에 묶는다.
-  따라서 텍스처를 렌더 대상과 셰이더 자원으로 사용하는 예제를 위해서는 두 개의 뷰를 생성해야 한다.
-  자원 뷰들은 본질적으로 두 가지 일을 한다.

1. Direct3D에게 자원의 사용 방식(파이프라인의 어떤 단계에 묶을 것인지)을 알려주는 것
2. 생성 시점에서 무형식을 지정한 자원 형식의 구체적인 형식을 결정하는 것
=> 무형식 자원의 경우 텍스처 원소를 특정 파이프라인 단계에서는 부동소수점 값으로 사용하고 다른 단계에서는 정수로 사용하는 것이 가능함을 뜻함.

 

- 어떤 자원에 대해 특정 뷰를 생성하려면 해당 자원을 생성할 때 해당 결속 플래그를 지정해야 한다.
무작정 생성을 시도하면 오류가 발생함
- 무형식 자원은 해당 자원의 유연성이 꼭 필요한 경우에만 사용해야 하며, 그렇지 않다면 형식을 완전하게 지정한 자원을 사용하는 것이 좋다.

=>  형식이 완전하게 지정된 자원은 생성 시 지정된 형식으로만 사용할 수 있으므로 런타임은 자원 접근을 최적화 할 수 있다

 

  • 다중표본화의 이론

-  모니터 화면에 임의의 선을 완벽히 그리는 것은 불가능하다.

=>  선을 픽셀들의 배열로 근사할 때 "계단 현상"이라고도 하는 앨리어싱(aliasing)이 발생한다.

 

앨리어싱 제거를 위한 기법들이 존재한다.

1. 초과표본화
=>  후면 버퍼와 깊이 버퍼를 화면 해상도보다 4배 크게 잡는다
=>  3차원 장면을 4배 크기의 해상도에서 후면 버퍼에 렌더링하고, 이미지를 화면에 제시할 때 후면 버퍼를 원래 크기의 버퍼로 환원(resolving)한다. 이를 하향표준화(downsampling)라고 부른다.
=>  하향표준화는 4픽셀 블록의 네 색상의 평균을 최종 색상으로 사용한다.
=>  쉽게 말해 초과표본화는 화면 해상도를 소프트웨어에서 증가시키는 것이라 볼 수 있다.
=>  초과표본화는 픽셀 처리량과 메모리 소비량이 4배라서 비용이 크다.
2. 다중표본화
=>  일부 계산 결과를 부분픽셀들 사이에서 공유하므로 초과표본화보다 비용이 적음
=>  4X 다중표본화(픽셀당 부분픽셀 4개)의 경우 초과표본화처럼 화면 해상도보다 4배 큰 후면 버퍼와 깊이버퍼 사용
=>  그러나 다중표본화는 이미지 색상을 각 부분픽셀마다 계산하는 것이 아니라 픽셀당 한 번만 계산하고(픽셀의 중심에서), 그 색상과 부분픽셀들의 가시성(이를 위해 부분픽셀당 깊이 및 스텐실 판정이 일어남)과 포괄도(부분픽셀을 다각형이 어느정도나 덮고 있는지를 뜻하는 값)를 이용해서 최종 색상을 결정한다.

 

  • 기능수준

-  Direct3D 11은 기능 수준이라는 개념을 도입했다. 

=>  D3D_FEATURE_LEVEL이라는 열거형으로 대표된다

 

- 기능 수준들은 엄밀한 기능성 집합을 정의한다
- 사용자의 하드웨어가 특정 기능 수준을 지원하지 않는다면 그보다 더 낮은(오래된) 기능 수준으로 내려가서 응용 프로그램을 실행한다
- 실제 응용 프로그램이라면 대상 사용자층을 최대화하기 위해 구형 하드웨어의 자원에도 신경을 써야 한다.

 

 

 

Direct3D의 초기화
  • Direct3D 초기화 과정

-  정확하게는 4X 다중표본화를 사용하는 전형적인 Direct3D 11 응용 프로그램의 초기화 과정을 뜻한다.

1. D3D11CreateDevice 함수를 이용해서 장치, 즉 ID3D11Device 인터페이스와 장치 문맥, 즉 ID3D11DeviceContext 인터페이스를 생성
2. ID3D11Device::CheckMultisampleQualityLevels 메서드를 이용해서 4X MSAA(multisample anti-aliasing, 다중표본화를 이용한 앨리어싱 제거) 품질 수준 지원 여부를 점검.
3. 생성할 교환 사슬의 특성을 서술하는 DXGI_SWAP_CHAIN_DESC 구조체를 채운다.
4. 장치를 생성하는데 사용했던 IDXGIFactory 인터페이스를 질의해서 IDXGISwapChain 인스턴스 생성
5. 교환 사슬의 후면 버퍼에 대한 렌더 대상 뷰를 생성
6. 깊이, 스텐실 버퍼와 그에 연결되는 깊이, 스텐실 뷰 생성
7. 렌더 대상 뷰와 깊이,스텐실 뷰를 Direct3D가 사용할 수 있도록 렌더링 파이프라인의 출력 병합기 단계에 묶는다.
8. 뷰포트를 설정한다.

 

  • 장치와 장치 문맥 생성

-  Direct3D 초기화의 시작은 Direct3D 11 장치(ID3D11Device)와 그 문맥(ID3D11DeviceContext)을 생성하는 것
-  위 두 인터페이스는 Direct3D의 주된 인터페이스로, 물리적인 그래픽 장치 하드웨어에 대한 소프트웨어 제어기라고 생각할 수 있다.

=>  즉, 응용 프로그램은 이 인터페이스들을 통해서 하드웨어에게 할 일(GPU 메모리에 자원 할당, 기하구조 그리기 등)을 지시한다.

 

-  ID3D11Device 인터페이스는 기능 지원 점검과 자원 할당에 쓰인다.
-  ID3D11DeviceContext 인터페이스는 렌더 대상 설정, 자원을 그래픽 파이프라인에 묶고, GPU가 수행할 렌더링 명령들을 지시하는데 쓰인다.
-  아래는 장치와 장치 문맥을 생성하는 함수이다.

HRESULT D3D11CreateDevice (
IDXGIAdapter *pAdapter,
D3D_DRIVER_TYPE DriverType,
HMODULE Software,
UINT Flags,
CONST D3D_FEATURE_LEVEL *pFeatureLevels,
UINT FeatureLevels,
UINT SDKVersion,
ID3D11Device **ppDevice,
D3D_FEATURE_LEVEL *pFeatureLevel,
ID3D11DeviceContext **ppImmediateContext
);

각 매개변수별 역할은 교재 116p ~ 118p 에 설명되어 있다.

 

 

 


 

 

 

기본적으로 DirectX 11 책을 바탕으로 공부하면서 헷갈리는 개념들에 대한 부분은 인터넷 자료들을 찾아보며 정리하였습니다. 공부하면서 보았던 블로그들을 아래에 링크로 첨부해두겠습니다.

 

틀린 부분이나 이상한 부분이 있으면 댓글로 편하게 지적해주세요.

감사합니다!

 

 

 

참고 링크

4-1. Direct3D 기초 : COM, 텍스쳐 형식, 교환사슬과 페이지 전환, 깊이 버퍼링, 다중 표본화, DXGI, 상주성 (koreanfoodie.me)

[DirectX 12] 기본지식 - 다중 샘플링(Multisampling) (tistory.com)

반응형

'DirectX11 > 정보정리' 카테고리의 다른 글

[DirectX11] 렌더링 파이프라인(1)  (0) 2022.11.03
[DirectX11] 색상  (0) 2022.11.03
[DirectX11] DirectX3D 초기화(2)  (0) 2022.10.28
[DirectX11] 행렬과 변환  (0) 2022.10.25
[DirectX11] 벡터 조작  (0) 2022.10.24

댓글