Programming/D3D12

[책공부] Geometry Shader + chap 12 연습 문제

Dorasima 2024. 1. 30. 00:04

(사실 이해했는지 모르겠다. 어렴풋이 느껴질 뿐... 그래도 그 느낌을 정리한다.)

1. Geometry Shader 

- Primitive를 GPU단에서 새로 생성하거나, 파괴하여서 다양한 효과를 낼 수 있게 해주는 기술이다.

- VS와 PS 사이에 optional 하게 존재한다. VS에서 받은 데이터를 작업한 다음에 바로 PS로 넘기 때문에, 대부분 상황에서는 Homogenous Coordinates 으로 변환한 다음에 넘겨주어야, 프로그래머가 원하는 모습이 렌더링 될 것이다.

- 함수 시그니처가 굉장히 특이하다. 아래 문서를 보고 공부하도록 하자.

- Geometry-Shader Object - Win32 apps | Microsoft Learn

 

Geometry-Shader Object - Win32 apps

A geometry-shader object processes entire primitives. Use the following syntax to declare a geometry-shader object.

learn.microsoft.com

 

2. App에서 해줘야 하는 것

- 그동안 선택 사항이였던 GS(Geometry Shader)를 PSO에 등록해줘야한다.

- GS 로직을 작성할 때, VS에서 넘어가는 Primitive Type과 일치해야 한다.

 

3. 언급할 만한 예제에서 사용한 방법(구조)

- 저 멀리 있는 배경이나, 모델들은 3d로 그리지 않아도 괜찮은데, 그걸 quad로 그냥 판떼기(billboard)로 표현하는 것이다.

- 그리고 quad가 가지는 Vertex 정보들을 전부 App에서 관리하는 것이 아니라, 위치와 크기 정보만 관리하고 나머지는 전부 이걸 Shader에서 작업하는 것이다.

(PassCB, ObjectCB로 넘겨준 여러 정보로 GS에서 Vertex를 생성해서 PS로 넘긴다.)

-  Alpha - To - Coverage (알파-적용 범위, 알파 포괄도) 기능이 있는데, clip을 사용하는 것보다 더 부드럽게 alpha masking을 하는 방법이다. mutil sampling을 이용한, alpha masking 느낌이다.

- Configuring Blending Functionality - Win32 apps | Microsoft Learn

 

Configuring Blending Functionality - Win32 apps

Blending operations are performed on every pixel shader output (RGBA value) before the output value is written to a render target. If multisampling is enabled, blending is done on each multisample; otherwise, blending is performed on each pixel.

learn.microsoft.com

 

4. 연습 문제

(클릭하면 커집니다.)

 

연습 문제 1

- Geometry Shader는 다음과 같이 입력으로 선분(line)이 차례대로  받도록 만든다. 

- 위로 점을 생성해가면서 Stream에 하나씩 쌓으면, 피자 한조각이 시카고 피자(?) 한조각이 되면서 원기둥을 생성한다.

- 그리고 App에서는 Shader 컴파일 하고, 넘겨주기로 한 circle에 맞는 geometry를 생성하고

- Render Item을 정의하고, 전용 PSO를 만들고

- 출력해준다.

 

연습 문제 2

 

- 일반적인 식을 찾기가 너무 힘들고.. 쉐이더 조건문을 안쓰기가 너무 힘들다...그리고 vertex를 낭비하지 않고 triangle adjacent를 쓰기가 너무 어렵다.

- 아직 쉐이더에 대해 배운것이 적고 + 연습이 부족하기에

- 일단은 그냥 문제에서 요구하는 모습을 구현하는데 집중했다.

- 책에서 제공하는 Subdivide 함수와 OutputSubdivision  함수는 파라미터 형식만 바꾸고 로직은 그대로 사용하였다.

 

 

- App 에서 해주는 일은 연습문제 1과 거의 똑같이 진행했고

- 다른 점은 PerObjectCB으로 Detail 수치를 넘겨주는데, 모델마다 LOD를 가지는 것이므로, App에서 흐름제어 변수를 관리해준다.

 

연습 문제 3

차이점은 오른쪽의 경우가, Vertex World Pos에 offset을 걸 때 Primitive ID도 함께 곱한 것이다.

 

- GS는 다음과 같이 작성하였다. PassCB로 넘어오는 gTotalTime을 이용하였다.

- App에서 해주는 일은 위 연습문제와 거의 같다.

 

연습문제 4

 

- GS는 다음과 같이 작성하였다.

- App에서는 예제를 일단 그대로 draw를 해주고, 예제의 Geometry를 Point로 넘기는 Render Item과 Normal을 그리는 GS를 설정한 PSO로 세팅하고 다시 한번 더 draw를 한다.

- 이미 그린 Geometry를 별다른 세팅 없이 Point만 넘겨주기 편하도록 Practice Layer에 한번 더 넣는다.

- RenderItem 마다 PrimitiveTopology가 정의되어 있는데, DrawRenderItems() 의 시그니처만 살짝만 바꿔서 사용했다.

 

연습 문제 5

- GS는 다음 처럼 작성하였다.

- App 에서 해주는 작업은 연습문제 4번과 거의 같다.

(연습 문제 4번과 5번의 차이점을 가까이서 보면)

연습문제 4번                                                                                                          연습문제 5번

연습 문제 6

(4단계씩 PrimitiveID가 나뉜 다는 걸 잘 볼 수 있게 나무의 위치를 조정하였다.)

- DrawInstanced 가 호출될 때마다 Primitive ID가 0부터 늘어나는 걸 확인할 수 있다.

- 만약 DrawInstanced 한번에 모든 Vertex를 그리면 오른쪽 사진 처럼 되는 것을 확인 할 수 있다.

 

연습 문제 7

- PS에서 Texture2DArray에서 갯수에 맞춰서 인덱싱을 하지 않는 경우가 왼쪽 사진

- DrawInstanced를 나눠서 호출한 경우가 오른쪽 사진

 

더보기

책 : DirectX 12를 이용한 3D

게임 프로그래밍 입문