본문 바로가기
대학생활/수업

게임그래픽프로그래밍심화 3주차 - 그래픽스 API 초기화 및 렌더링

by se.jeon 2023. 9. 11.
728x90
반응형

Direct3D 초기화

DirectX와 COM(Component Object Model)

COM은 마이크로소프트가 개발한 소프트웨어 컴포넌트 간의 통신을 위한 바이너리 인터페이스 표준.

DirectX는 COM 기반의 아키텍처로 설계되어, COM 인터페이스를 사용하며, 이를 통해 DirectX 기능 사용 가능

DirectX의 오브젝트들은 COM 인터페이스를 사용하므로 COM에서 사용되는 참조 카운팅 방식으로 생명주기 관리

오브젝트 미사용시 반드시 메모리 해제를 위한 Release 메서드 호출

DirectX 초기화 전체 과정

- D3D11CreateDevice 이용한 ID3D11Device, ID3D11DeviceContext 생성
- ID3D11Device::CheckMultisampleQualityLevels 통한 4X MSAA 품질 수준 지원 여부 확인
   * MSAA (Multi-Sample Anti-Aliasing) : 계단 현상 완화를 통한 품질 향상 기술
- 생성할 SwapChain을 위해서 DXGI_SWAP_CHAIN_DESC 구조체 내용 구성
   * SwapChain : 사용자에게 frame을 표시하기 위해 사용되는 버퍼의 집합체
- 일반적으로 frontbuffer 하나와 backbuffer 하나 이상 구성
- IDXGIFactory 인터페이스를 통해 IDXGISwapChain 인스턴스 생성

 

- SwapChain의 BackBuffer에 대한 Render Target View 생성

- Depth Buffer, Stencil Buffer 생성 및 Depth Buffer, Stencil Buffer 연결하는 Depth View, Stencil View 생성
   * DirectX에서는 buffer, texture등의 리소스들은 데이터 저장소로
- View는 GPU에서 어떻게 적용하고 해석할지 결정하는 용도로 처리
- Render Target View, Depth View, Stencil Viewe들을 DirectX Rendering Pipeline의 OutMerge단계에서 설정
- Viewport에 대한 설정

DirectX 초기화 1단계 : 디바이스와 컨텍스트 생성

DirectX Device와 Device Context 객체
→ 객체를 할당,삭제, 기본 형식 렌더링, 그래픽 드라이버 및 H/W 통신

 

디바이스 객체 : 리소스를 만들기 위함

디바이스 컨텍스트 객체 : 렌더링을 수행

 

한 디바이스에서 만든 객체는 다른 디바이스에서 직접 사용 불가
→ 여러 디바이스 데이터 공유를 위해서는 공유 리소스를 사용하여 공유, 객체를 만든 디바이스에서만 사용 가능

DirectX 디바이스 생성

리소스 생성 및 디스플레이 어댑터의 기능 열거할 때 사용
Direct3D11에서 디바이스 ID3D11Device 인터페이스로 표시

 

D3D11CreateDevice 함수를 사용해서 디바이스 생성
게임에서는 일반적으로 하나의 디바이스만 생성

D3D_DRIVER_TYPE 플래그를 사용하여 드라이버 유형 지정 가능

각 디바이스는 디바이스 컨텍스트를 하나 이상 사용 가능

DirectX Context(컨텍스트) 생성

→ 렌더링을 하기 위해서 필요함
→ 디바이스가 사용되는 상황 또는 설정 포함
→ 렌더링 파이프라인 상태를 설정하고, 디바이스가 소유한 리소스를
사용하여 렌더링 명령을 생성하는데 사용
→ ID3D11DeviceContext 인터페이스로 표시
→ D3D11CreateDevice 함수를 사용해서 컨텍스트 생성
→ Direct3D 11은 즉시 컨텍스트와 지연 컨텍스트 지원

 

 

Immediate Context : 즉시 콘텍스트, Immediate Context를 사용하여 명령 목록을 즉각적으로 렌더링
→ 각 디바이스에서는 GPU에서 데이터를 검색할 수 있는 하나의 Immediate Context가 존재

 

Deferred Context : 지연 콘텍스트, 명령 목록에 GPU 명령을 기록 후, 다중 스레드 애플리케이션에서 사용
→ 기본 랜더링 스레드 대신 작업자 스레드에서 사용

DirectX에서 디바이스와 컨텍스트 역할

GPU에 대한 전반적인 소프트웨어 제어 기능 역할

- 애플리케이션에서 해당 디바이스와 컨텍스트 인터페이스들을 통해 GPU에서 해야 할 여러가지 일들을 지시

- 디바이스와 컨텍스트 모두 D3D11CreateDevice를 통해 생성
- ID3D11Device : 기능 지원 확인 및 리소스 할당
- ID3D11DeviceContext : 렌더링 대상 설정, 리소스를 렌더링 파이프라인에서 사용하고, GPU가 수행할 명령들을 수행

 

 

D3D11CreateDevice의 ID3D11Device와 ID3D11DeviceContext 는 왜 이중 포인터를 사용했을까?
→ COM기반 객체를 반환하거나 함수내에서 포인터 값을 직접 변경하기 위해서 필요로 함.

결국 COM으로 구현된 Interface가 포인터로 접근 가능하도록 DirectX가 설계되어 있기 때문임.

 

→ 포인터의 포인터를 사용한 이중 포인터는 원래 값 자체를 가져옴
→ 포인터(Pointer) : 주소값을 갖는 변수
→ 이중포인터(Double Pointer) : 포인터 변수의 주소값을 갖는 변수

 

 

int GameVal = 1999;
→ int* pGameVal = &GameVal;
→ int** ppGameVal = &pGameVal;

→ *pGameVal은 GameVal이며, *ppGameVal은 pGameVal임
→ *(*ppGameVal)은 GameVal임

DirectX 초기화 2단계 : H/W의 4X MSAA 품질 수준 지원 여부 확인

D3D11은 모든 렌더링 대상 형식에 대해서 4X MSAA 품질 지원

 

* Aliasing (앨리어싱) : 계단 현상
수식을 통해서 선을 완벽하게 구하기 위해선 충분한 해상도 필요
선이 자연스럽게 연결되지 않고 계단처럼 보이는 현상

 

MSAA(Multi Sampling Anti-Aliasing)
폴리곤의 외곽선만을 우선 추출
주변의 Pixel 색상들의 평균 연산을 통해 최종 Pixel의 색상값 결정

 

DirectX 초기화 3단계 : 구조체 내용 구성

SwapChain생성을 위해 DXGI_SWAP_CHAIN_DESC 구조체 내용 구성


IDXGISwapChain의 주요 역할
→ 화면에 렌더링을 위한, FrontBuffer 및 BackBuffer 관리
→ Present 메서드 통해 BackBuffer 내용 FrontBuffer에 전화 및 화면 표시
→ 창의 크기변화에 따른 그래픽 출력 유지, 전체화면/창 모드 전환

DirectX 초기화 4단계 : SwapChain의 생성

→ dxgi.lib 링크 필수
→ 이전 단계 ID3D11Device에 사용한 IDXGIFactory 객체 사용 필수
→ IDXGIDevice와 IDXGIAdapter를 통해 IDXGIFactory 인터페이스 얻어 옴
→ IDXGIFactory 인터페이스의 CreateSwapChain 메서드 사용

DXGI (DirectX Graphics Infrastructure)

- Direct3D와는 개별적인 API
- SwapCahin설정, Graphics H/W 목록들 표시, 전체/창 모드 설정 등 그래픽에 관련된 저수준 작업 처리
- DXGI는 모두 그래픽에 관련된 작업을 처리
- Direct관련 그래픽 API들은 공통적인 DXGI API를 사용 (Direct3D와 Direct2D )
- 주요 인터페이스 : IDXGIFactory, IDXGIAdapter, IDXGIDevice, IDXGISwapChain

 

IDXGIDevice
DirectDeivce와 연결, QueryInterface를 통해 현재 Adapter를 반환

 

IDXGIAdapter
컴퓨터의 그래픽 카드들을 열거, GetParent를 통해 IDXGIFactory를 확인

 

IDXGIFactory
DXGI 객체를 생성 및 관리, DXGIAdapter 열거 기능, CreateSwapChain 제공

 

IDXGISwapChain
렌더링된 콘텐츠 화면 표시, Present를 통해 화면에 표시, 전체/창 모드 관리

 

DirectX 초기화 5단계 : Render Target View 생성 

SwapChain의 BackBuffer에 대한 Render Target View 생성

 

- Resource는 View를 생성 후 View를 렌더링 파이프라인에 결합 필수.
- BackBuffer를 Output Merger 단계에 결합하기 위해선 BackBuffer에 대한 render target view가 필요하므로 먼저 생성

DirectX 초기화 6단계 : Depth Buffer, Stencil Buffer 생성 및 View 생성

- 깊이 정보와 스텐실 정보를 담는 2차원 텍스처 형식 (깊이, 스텐실 버퍼)
- 2차원 텍스처를 생성하는 방법
- D3D11_TEXTURE2D_DESC 구조체 생성 및 정보 설정
- ID3D11Device::CreateTextrue2D 를 통해서 생성
- Depth Buffer, Stencil Buffer 사용을 위해 Depth, Stencil View 생성
- ID3D11Device::CreateDepthStencilView 로 View 생성
- 렌더링 파이프라인의 Output Merger 단계의 결합도 필수

DirectX 초기화 7단계 : OutMerge단계의 결합 설정

RenderTargetView, Depth, Stencil View를 렌더링 파이프라인의 OutMerge단계의 결합 설정
이전 단계에서 생성한 RenderTarget, Depth, Stencil View를 생성한 ID3D11DeviceContext::OMSetRenderTargets으로 OutMerge 단계 설정

DirectX 초기화 8단계 : Viewport에 대한 설정

뷰포트는 3D 렌더링 된 모습을 2D 디스플레이에 어떻게 보이게 할지 결정하는 영역
BackBuffer에 렌더링된 부분에서 일부분 혹은 전체를 그리기 가능

 

Direct3D 초기화 실습

1. 프로젝트들을 관리하기 위한 솔루션 생성

2. 프로젝트 생성을 위한 Windows 데스크톱 애플리케이션 생성

3. DirectX를 초기화하기 위해서 Windows 데스크톱 애플리케이션 생성

4. 제공한 압축 Common 압축해제하고 Solution 폴더에 복사 및 설정

- 레거시 DX11에 대한 설정 때문에 오류 발생
- 해당 프로젝트에 새 필터 추가 -> Common으로 이름 설정

- Common폴더에 있는 d3dApp와 d3dUtil, GameTimer 추가

- 추가로 Common 폴더에 있는 LightHelper, MathHelper 추가

5. 추가 DX11 라이브러리 추가 (d3d11.lib)

6. CX_DX_01_InitDevice 파일들 수정

7. CX_DX_01_InitDevice.cpp에서 WinMain 수정 후 실행

 

렌더링 파이프라인

그래픽데이터가 모델링, 셰이딩, 라이팅 등의 핵심 과정을 거쳐 화면에 2차원 픽셀로 표시되는 과정

 

1. Input assembler Stage

2. Vertex Shader Stage

3. Hull Shader Stage

4. Tessellator Stage

5. Domain shader Stage

6. Geometry Shader Stage

=== Stream Output Stage ===

7. Rasterizer Stage

8. Pixel Shader Stage

9. Output Merge Stage

<= Memory Resources (Memory, Constant Buffer, Texture)

일반적인 렌더링 파이프라인

기본 렌더링 파이프라인

1. Input assembler Stage

2. Vertex Shader Stage

3. Rasterizer Stage

4. Pixel Shader Stage

5. Output Merge Stage

 

확장된 기본 렌더링 파이프라인

1. Input assembler Stage (IA)

2. Vertex Shader Stage (VS)

3. Tessellator Stage

4. Geometry Shader Stage (GS)

5. Rasterizer Stage

6. Pixel Shader Stage (PS)

7. Output Merge Stage (OM)

Input assembler Stage (IA : 입력 어셈블러 단계)

- 메모리에서 정점이나 인덱스들을 입력데이터로 읽어 기본도형을 구성
- 정점들은 Direct3D의 VertexBuffer를 통해 저장

 

Direct3D에서 지원하는 Primitive Topology의 주요 유형
- D3D11_PRIMITIVE_TOPOLOGY_POINTLIST
- D3D11_PRIMITIVE_TOPOLOGY_LINELIST
- D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP
- D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
- D3D11_PRIMITIVE_TOPOLOGY_ TRIANGLESTRIP

 

Direct3D에서 기본도형의 위상구조와 어떻게 렌더링 할지 결정한다.
ID3D11DeviceContext::IASetPrimitiveTopology

 

 

Direct3D 의 Primitive Topology 열거형

Direct3D의 주요 기본 도형들

Vertex Shader Stage (VS : 정점 셰이더 단계)

프로그래머가 직접 작성해서 GPU에서 실행 가능한 단계이다.
입력해서 들어온 하나의 정점을 하나의 정점으로 출력하는 단계.
화면에 그려지는 모든 정점은 VS 단계를 거쳐 가게 된다.

 

정점 ,텍스처, 광원 등의 정보 등을 GPU 메모리에서 접근이 가능하다.
새로운 정점을 생성하거나 기존 정점들은 삭제 불가능하다.

 

Per-Vertex Lighting, Skinning , Transformation 등을 처리한다.
Local Space -> World Space -> View Space -> Clip Space 변환

Tessellation Stage (테셀레이션 단계)

주어진 삼각형을 더 작고 상세한 새로운 삼각형으로 만드는 과정이다.

 

테셀레이션의 장점
- 카메라의 거리에 따라서 테셀레이션을 통해서 LOD 구현 가능하다.
- Low Polygon 정보만으로 High Polygon 구현 가능하다. (메모리 절약)
- 애니메이션이나 물리 적용시 Low Polygon으로 적용 후 테셀레이션된 High Polygon으로 렌더링 (계산량 축소)

 

DX11에서 GPU 상에서 테셀리이션을 수행할 수 있는 방법 제공
DX11 이전에는 CPU에서 삼각형 분할 후에 GPU에 다시 올려서 렌더링

Geometry Shader Stage (기하 셰이더 단계 : GS)

렌더링 파이프라인에서 옵션 단계로써 생략 가능하다.
입력 받은 기본도형의 모양을 정점의 변화를 통해서 변경 가능하다.
입력 받은 정점들을 변화 시켜 입력과 다른 기본도형으로 확장 가능하다.
입력 받은 정정들을 변화 시켜 입력 기본도형을 삭제 가능하다.
GS에서는 하나의 점이나 선분, 혹은 적은 수의 점들을 입력받아서 선분이나, 사각형, 혹은 다각형, 다면체로 확장
GS는 출력 정점 데이터가 Stream Output Stage를 통해 메모리 버퍼에 저장 후 나중에 사용 가능하다.

Rasterizer Stage (레스터화 단계)

투영된 정점들을 이용해서 지정된 기본도형 형태로 내부 영역을 픽셀로 변환하는 과정이다.

 

- Clipping : 시야 절두체에서 벗어난 부분을 잘라버린다.
- 뷰포트 변환 : 디스플레이에 2D 결과화면을 가시화하는 단계.
- BackFace Culling : 뒷면으로 지정된 면은 그리지 않는다.
- Scan Conversion : 기본 도형 경계를 바탕으로 내부를 픽셀로 변환한다.

Pixel Shader Stage (픽셀 셰이더 단계 : PS)

프로그래머가 직접 작성해서 GPU에서 실행 가능한 단계이다.
보간된 정점 특성 정보를 바탕으로 하나의 최종적인 색상을 출력한다.
특정 색깔 표현, 텍스처 색상, 픽셀 별 조명 처리, 그림자 효과 등

 

Fragment VS Pixel
Fragment는 화면의 특정 위치에 렌더링 할 수 있는 픽셀 후보.
Pixel은 화면의 특정 위치에 렌더링 되는 최종 색상 값


- DX : Pixel Shader

- OpenGL : Fragment Shader

Output Merger Stage (출력 병합 단계 : OM)

블렌딩, 깊이/스텐실 버퍼의 내용을 바탕으로 최종 픽셀값을 결정한다.


- Depth Testing : 깊이 버퍼의 깊이값을 기준으로 렌더링 여부를 결정한다.
- Stencil Testing : 스텐실 버퍼의 스텐실값 기준으로 렌더링 여부를 결정한다.
- Blending : 렌더링 대상에 기록되기 전에 두개 이상의 픽셀 값을 결합한다.
- 최종 픽셀 색상 값은 RenderTarget(예: 화면)에 기록되어, 사용자에게 보여진다.

실습 진행 (예제 프로젝트 생성)

728x90
반응형