4장 부분이 내용과 코드가 많아서 나눠서 올리겠습니다.
[ Goal ]
- 하드웨어와 Direct3D의 관계
- COM의 정의 및 역할
- 저장방식, 페이지 전환, 깊이 버퍼링, 다중표본화 같은 기초 그래픽 개념
1. 기본지식
- Direct3D 12의 개요
- Direct3D 는 GPU를 제어하고 프로그래밍 하는 저수준 API ( application programming inerface )
- 저수준일수록 GPU와 가깝게 동작하므로 더욱 빠른 동작이 가능함.
- 고수준 API는 디스플레이 생성하는 드라이버를 필요로 한다.\
- Direct3D 12와 11의 차이점
- 다중 스레드 지원 개선
- CPU부담 크게 줄임
- 추상화가 줄고 개발자가 관리할게 많아져 어려웠지만 성능 개선
- Direct3D 는 GPU를 제어하고 프로그래밍 하는 저수준 API ( application programming inerface )
COM ( Component object Model )
- DirectX의 프로그래밍 언어 독립성과 하위 호환성을 가능하게 하는 기술
- 예를 들어 C++에서 만들고 Visual Basic 문서화된 컨트롤을 사용하는 JScript 애플리케이션을 작성할 수 있습니다.
- COM 객체를 C++ 클래스로 간주하면 이해하기 쉽다.
- 알아야 할 것 : COM 인터페이스를 가르키는 포인터 얻는 방법
- 함수 이용
- COM 인터페이스의 메서드를 이용
- 생성시 new 키워드를 사용할 필요는 없지만 delete가 아닌 release 키워드를 통해 메모리 해제해야 한다.
- Mirocsoft::WRL::ComPtr 클래스를 사용하면 자동으로 release 되어 사용자가 직접 release 할 필요가 없다.
- WRL : Windows Runtime Library ( 사용하기 위해 wrl.h 헤더가 필요함 )
- ComPtr은 쉽게 생각해 COM 객체를 위한 똑똑한 포인터라 할 수 있다.
- ComPtr의 주요 메소드
- Get : COM 인터페이스를 가르키는 포인터 반환
- GetAddressOf : COM 인터페이스를 가르키는 포인터의 값( 주소 )를 반환
- Reset : ComPtr 인스턴스를 nullptr로 설정하고 바탕 COM 인터페이스의 참조 횟수를 1 감소
- Mirocsoft::WRL::ComPtr 클래스를 사용하면 자동으로 release 되어 사용자가 직접 release 할 필요가 없다.
- COM 인터페이스들은 이름이 대문자 I로 시작한다.
텍스처 형식
- 텍스처는 행렬 ( 배열 ) 이라 생각하면 된다.
- 2차원 텍스처는 이미지 자료를 저장하는데 사용된다.
- 사실 텍스처가 단순한 자료 배열은 아니다. ( 여러 방법에 사용됨 )
- 텍스처에는 밉맵 수준들이 존재 할 수 있다.
- GPU 필터링, 다중 표본화 등의 특별한 연산에도 사용된다.
- 특정 자료형들만 저장할 수 있다.
https://learn.microsoft.com/en-us/windows/win32/api/dxgiformat/ne-dxgiformat-dxgi_format
DXGI_FORMAT (dxgiformat.h) - Win32 apps
Resource data formats, including fully-typed and typeless formats. A list of modifiers at the bottom of the page more fully describes each format type.
learn.microsoft.com
저장할 수 있는 자료형들을 확인 할 수 있다.
교환 사슬과 페이지 전환
- 용어 정리
- 버퍼 : 주기억 장치와 주변장치 사이에서 데이터를 주고받을 때, 둘 사이의 전송속도 차이를 해결하기 위해 전송할 정보를 임시로 저장하는 고속 기억장치
- 애니메이션이 껌벅이는 현상을 피하기 위한 과정 ( 이중 버퍼링 )
- 한 프레임 전체를 화면 바깥에서 그린다. ( 후면 버퍼 )
- 후면 버퍼가 완성이 되면 하나의 완전한 프레임으로써 화면이 표시한다. ( 후면 버퍼 -> 전면 버퍼 )
- 표시 되는동안 다시 화면 바깥에서 후면 버퍼를 준비한다.
- 위와 같은 과정을 하기위해 계속 후면 버퍼를 생성하기에는 메모리 낭비이다.
- 해결하기 위해서는 버퍼를 2개만 생성해두고 교차해 가며 화면에 표시하는 방법이다.
- 즉 각 프레임마다 버퍼 포인터를 교차해 가면서 화면에 표시해 나가면 된다. ( 교환 사슬 생성 )
- 만약 버퍼를 3개를 사용하면 삼중 버퍼링이라 하며 일반적으로는 버퍼 두개로 충분하다.
깊이 버퍼링
- 용어 정리
- 렌더링 : 컴퓨터 프로그램을 사용하여 모델 또는 이들을 모아놓은 장면인 씬 파일(scene file)로부터 영상을 만들어내는 과정
- 각 물체의 깊이 정보를 담는다. ( 즉 거리를 계산한다. )
- 이미지 자료를 담지 않는 텍스처의 한 예시
- 픽셀의 값은 0~1 사이의 값으로 값이 클수록 멀리 있는 물체에 해당된다.
- 예를 들어 1280 X 1024 해상도에서는 깊이 버퍼는 1280 X 1024 개의 원소들로 구성되어있다.
- Direct3D는 깊이 버퍼링 또는 z-버퍼링이라 하는 기법을 사용한다.
- 깊이 버퍼링을 통해 한 픽셀에 그려질 물체가 정해지는 과정 ( 렌더링 과정 )
- 깊이 버퍼값을 1.0 값으로 초기화하고 색상은 검은색 또는 흰색으로 초기화한다.
- 렌더링 순서대로 물체를 가져온다.
- 렌더링 할 물체의 깊이 버퍼 값이 기존의 깊이 버퍼값과 비교하여 깊이 판정을 수행한다.
- 기존 깊이보다 낮으면 색과 깊이 버퍼값을 갱신한다.
- 만약 크다면 갱신하지 않고 다음 렌더링 물체를 가져온다.
- 렌더링 할 물체 모두 가져와 갱신한다.
- 최종적으로는 가장 가까운 물체가 해당 픽셀을 차지하게 된다.
- 깊이 버퍼는 하나의 텍스처 이므로 생성 시 특정한 자료형식을 지정할 필요가 있다.
자원과 서술자
- 용어 정리
- 바인딩 : 프로그램에 사용된 구성 요소의 실제 값 또는 프로퍼티를 결정짓는 행위를 의미한다. 예를 들어 함수를 호출하는 부분에서 실제 함수가 위치한 메모리를 연결하는 것도 바로 바인딩이다.
- 파이프라인 : 파이프라인(영어: pipeline)은 한 데이터 처리 단계의 출력이 다음 단계의 입력으로 이어지는 형태로 연결된 구조를 가리킨다.
- 서술자 ( Descriptor 또는 View ) : 하나의 리소스에 대한 정보를 담은 자료구조
- 렌더링 과정에서 GPU는 자료를 기록하거나 자료를 읽어온다.
- GPU가 그리기 명령을 수행하기 전에 먼저 해당 그리기 호출이 참조할 자원들을 렌더링 파이프라인에 바인드 해야한다.
- 실제로 바인딩 되는것은 해당 자원을 참조하는 서술자이다. 실제 자원이 바인드 되는것이 아니다.
- 이처럼 서술자들을 거치는 추가적인 간접층을 두는 이유는 GPU자원이라는 것이 범용적인 메모리 조각이기 때문이다. 즉 같은 자원들 서로 다른 렌더링 단계에서 사용 될 수 있기 때문이다.
- 또한 자원의 일부 영역만 사용하거나 이 자원이 깊이로 사용되어야할지 렌더 대상으로 사용되어야 할지 GPU는 모르기 떄문에 이러한 정보를 서술자가 가지고 있다.
- 서술자의 형식
- CBV/SRV/UAV : 순서대로 contant buffer( 상수 버퍼 ), shader resource ( 셰이더 자원 ), unorderd aceess view ( 순서 없는 접근 ) 을 가르킨다.
- RTV : render target ( 렌더 대상 ) 을 가르킨다.
- DSV : depth/stencil ( 깊이. 스텐실 ) 자원을 가르킨다.
- 표본 추출기 서술자는 텍스처 적용에 쓰이는 표본 추출기 자원을 서술한다.
- DirectX SDK 문서화에는 무형식 자원은 유연성이 꼭 필요할 때에만 만들고 그렇지 않은 경우에는 형식을 완전히 지정해서 자원을 만들어야 한다고 서술한다.
- 즉 어떤 용도이든 텍스처를 사용하기 위해서는 초기화 시점에 그 텍스처의 Resource View를 생성해야 한다.
- Resource View의 역할
- DirectEd에게 Resource의 사용 방식 즉 PipeLine의 어떤 단계에서 바인드 할것인지 알려주는 것
- 생성 시점에서 Typeless Resource의 Tpye을 지정하는것
이 부분은 아직 이해가 잘 안되어서 책을 한번 다 읽어보고 다시 이해해봐야겠다.
다중표본화
- 용어 정리
- 엘리어싱 : 컴퓨터의 이미지 표현 방식이 아날로그 방식이 아닌 디지털 방식이기 떄문에 정확한 선을 나타낼때 계단처럼 끊어지는 현상이 나타난다. 이를 앨리어싱 현상이라 한다.
- 앨리어싱 현상을 방지 하기 위해서 렌더링 과정에서 화면 해상도의 4배만큼으로 후면 버퍼의 크기를 결정한다.
- 이후 색을 결정하고 전면 버퍼로 옮길때 화면 해상도의 크기로 다시 환원하는데 이를 하향 표본화라 한다.
- 색을 결정하는 방법에 따라 그리고 계산하는 방법에 따라 2가지 기법이 나뉜다.
초과 표본화 | 다중 표본화 |
4배만큼 커진 후면 버퍼에서 각 픽셀마다 색의 값을 계산한다. 이후 하향 표본화 시 4개의 픽셀의 평균으로 해당 픽셀의 값을 결정한다. |
4배만큼 커진 후면 버퍼에서 4개의 픽셀의 색을 하나의 색으로 통일시킨다. 이후 4개의 픽셀에 대한 가시성, 포괄도를 계산하여 최종 색상을 결정한다. |
좀더 정확한 표현이 가능하지만 자원을 많이 쓴다. 각 픽셀별로 계산하기 때문에 |
덜 정확한 표현을 하지만 자원을 조금 쓴다. 4개의 픽셀에 대해 중심의 색으로 색을 결정하기 때문에 |
- Direct3D 의 다주 표본화
- 다중 표본화를 위해서는 DXGI_SAMPLE_DESC 라는 구조체를 적절히 채워야 한다.
typedef struct DXGI_SAMPLE_DESC
{
UINT Count; // 픽셀당 추출할 표본의 갯수
UINT Quality; // 품질 수준 ( 하드웨어 제조사마다 다를 수 있다. )
} DXGI_SAMPLE_DESC;
DXGI
- 용어 정리
- 디스플레이 어댑터 : 물리적인 하드웨어 장치 ( 예를 들어 그래픽 카드 )
- DXGI : Direct3D와 함께 쓰이는 API.
- DXGI는 여러 가지 공통적인 그래픽 기능성을 처리한다.
- 전체화면 모드 전환, 디스플레이 어댑터나 모니터, 지원되는 디스플레이 모드 같은 그래픽 시스템 정보의 열거 등
- 초기화 과정에서 쓰이는 인터페이스
- IDXGIFactory : DXGI 객체들을 생성하는 메소드를 구현
- 소프트웨어 어댑터 생성
- 스왑체인 생성
- 어댑터 열거
- 전체화면으로 전환을 제어하는 윈도우 반환
- WIndow Association 생성
- IDXGIAdapter : 컴퓨터의 하드웨어 및 소프트웨어 기능을 추상화 한것
- 시스템이 그래픽 구성 요소에 대한 장치 인터페이스를 지원하는지 확인
- 어댑터 출력을 열거
- 어댑터의 DXGI 1.0 설명을 가져옴
- IDXGIFactory : DXGI 객체들을 생성하는 메소드를 구현
이 부분은 아직 이해가 잘 안되어서 책을 한번 다 읽어보고 다시 이해해봐야겠다.
참고 : DirectX 12 를 이용한 3D 게임 프로그래밍 입문 / 한빛미디어
'독학 > DirectX' 카테고리의 다른 글
[ DirectX ] 기초 수학 3. 변환 (0) | 2022.11.09 |
---|---|
[ DirectX ] 기초 수학 2. 행렬 대수 (1) | 2022.11.09 |
[ DirectX ] 기초 수학 1. 벡터 대수 (0) | 2022.11.09 |