Programming/D3D12

(공부중) #1 App 구조 예쁘게 다시 바꿔보기

Dorasima 2024. 7. 1. 14:47

유영천 프로그래머(@megayuchi )님 방송을 가끔 보는데...

 

그동안 공부했던 D3D12 책이 그다지 좋지 않다는.... 얘기를 들었다.

 

그래서

뭐라도 좀 해야겠다 싶어서 앱 구조라도 일단 예쁘게? 다시 짜보는 걸 해보도록 하겠다.

- 예쁘다의 기준은... 나중에 공부하면서 추가할 기능이... 예쁘게? 돌아가게 하는 거 ㅋㅋ

github - d3d12practice - solopractice

 

0. 일단 megayuchi 강의 샘플을 적당히 따라감

https://inf.run/WYdms

 

D3D12 프로그래밍-기초편 강의 | megayuchi - 인프런

megayuchi | 이제는 주류 그래픽 API의 자리가 D3D11에서 D3D12로 넘어간 것 같습니다. D3D12는 매력적인 기능들을 지원하지만 학습 난이도가 높은 편입니다. 하지만 차근차근 학습한다면 개인도 D3D12 API

www.inflearn.com

 

- D3D12 API와 어울리는 구조로 짜는 방법을 엿볼 수 있다.

- 완전 비동기 + 멀티스레드 특화 API를 위한 pooling을 많이 사용한다.

- DirectXAgility와 DirectXTex도 간단하게 사용한다.

(강의는 취직한 뒤 꼭 구매하겠습니다... 하핫)

 

1. D3D12 like(?) 하게 그려보기 위해, PSO caching을 해보기로 했다.

 

- 일단 지금은 ... 머 대충 박스 몇개, 사각형 몇개 출력하는게 전부니까 이렇게 문자열로 구분하는데,

- 나중가면 key가 여러개인 자료구조를 사용해야 하지 않을까...

 

2. 일단  World 느낌이 나게 Quad를 wireframe으로 그려보겠다.

-어... 이렇게 삼각형 느낌이 나면 안되는디 

- geometry 쉐이더를 이용해서 다시 해봐야겠다.

 

3. Geometry Shader로 Tile 그리기.

- Geometry Shader로 만든 LineStream이... 안보인다 (해결함)

- 짜증난다... Culling이 일어나는건 아닌 것 같다. 순서를 뒤집어도 가로선은 잘 보인다.

- 윗줄을 다시 말하면... 저 (x < 0) (z < 0)부분에서 제멋대로 Culling이 일어난다(?) 라고 표현하는 느낌이다.

- UINT로 해서 그런거다 ㅋㅋㅋㅋㅋㅋㅋ

- 이렇게 x, y 축을 1좌표 마다 점을 그려서 넘겨주었다.

 

4. 좀 더 자연스럽게 GridTile 그리기

- 간격도 좀 넒혀주고 (25 정도?), 카메라 위치에 따라 적절히 새로 그려지게 했다.

(나중에는 카메라 위치에 따라, 그리지 않는 것도 하는게 좋을 듯?)

 

5. 파일 드래그 앤 드롭

- 일단 현재 목표는 3d model viewer 이다.

- 드래그 앤 드롭으로 모델 파일을 띄워보려고 한다.

- WndProc() 에서 WM_DROPFILES 메시지 일 때, <shellapi.h>에서 제공하는 DragQueryFile()을 이용하였다.

- 그 이전에 

- 윈도우 속성에 WS_EX_ACCEPTFILES 확장 속성을 추가해준다.

 

6. Lighting을 하기 위한 Frame 별 CBV 따로 넘겨주기

- D3D12Renderer 가 App과 함께 가면서 렌더링을 하는데

- 카메라 위치나 월드의 조명 정보는 모든 object가 공유하니까 Render에서 관리하고, Object에 넘겨주는 식으로 한다.

- Object 별로 PSO와 Root Signature를 갖긴하지만... 포인터로 넘겨 받은걸 SetGraphicsRootConstantBufferView()로 걸어주기만 하는거니까.... 그다지 느린 작업은 아니라고 생각한다.

 

7. 모델 윤곽선 (outline) 그려보기

- 인접한 삼각형이 서로 카메라를 중심으로 dot값이 다르면, 그곳이 바로 윤곽선일 것이다.

- Geometry Shader에서 이를 해줄 수 있을 것이다.

- 삼각형의 인접 정보(Triangle Adjacency) 알아야하기 때문에, 원래 Mesh 정보를 나타내는 Indices의 Triangle list를 Triangle list with adjacency으로 바꿔줘야 한다.

https://learn.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-primitive-topologies

 

Primitive Topologies - Win32 apps

Direct3D 10 and higher supports several primitive types (or topologies) that are represented by the D3D\_PRIMITIVE\_TOPOLOGY enumerated type. These types define how vertices are interpreted and rendered by the pipeline.

learn.microsoft.com

 

- DirectXMesh를 쓰고싶었는데... 자꾸 heap corruption이 나서 직접 만들어주기로 했다.

- 일단은 주변 삼각형을 위치(position)으로 검색하면서 채워넣어야 하기 때문에 unordered_map을 위한 hash를 만들고

- 원하는 동작은 triangle list 를 triangle list with adjacency로 바꾸는 것이다.

- list는 index 3개씩 1개의 삼각형을 만드는 특징을 가지고 있으니까

- 사이사이와 마지막에 인접점을 하나 끼워넣어주면 되는 것이다.

- https://learn.microsoft.com/ko-kr/windows/win32/direct3dhlsl/dx-graphics-hlsl-geometry-shader

 

기하 도형 셰이더 개체 - Win32 apps

기하 셰이더 개체는 전체 기본 형식을 처리합니다. 다음 구문을 사용하여 기하 도형 셰이더 개체를 선언합니다.

learn.microsoft.com

- 요런식으로 vertex position으로 검색이 가능하고 value로 삼각형 정보를 가지고 있는 map에서 인접 정보를 찾는 함수를 따로 만든다.

- 사이사이에 끼워 넣어주면 triangle list with adjacency 가 된다.

- 윤곽선을 그리는 Shader 코드는 다음과 같다. 

- 이제 topology를 D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ 으로 설정하고

- 이것저것 다 모델 정보에 맞는 정보로 그리면?

- 근데 고쳐야 할 점이 보인다.

- 삼각형 노멀과, 삼각형에서 카메라를 향한 방향이 어느 구역에서 (현상으로는 수직 근처) 그려지지 말아야할 구간이 그려진다.

 

- 고쳤다. Camera 로 방향을, 삼각형이 아니라 각 점에 대해 계산하고, 원래 삼각형 노멀이 카메라와 dot 가 음수면 그냥 날려버렸다.

 

8. Material은 Sub-Model 단위로 넘겨주기

- 시간에 따라 업데이트 될 수 있으니, 강의에 나온 pool 구조를 이용해서 업데이트 하기

- 이렇게 서브 모델 마다 머테리얼을 가질 수 있게 만들고 
- 원래 Draw를 걸 때는 heap에 Texture 밖에 없었는데, Material 정보가 추가 되었으니,
- 서브 모델의 개수 만큼 Texture, Material 이 번갈아 가면서 bind 하게 된다.

클릭하며 커집니다.

- 이에 맞게, root signature 도 바꾸고, 쉐이더도 바꾼다.
(다른 자료형에 다른 버퍼라서 table entry를 그냥 하나 추가해주었다.)

- 그렇게 하면?

요로콤 Material 이 넘어가게 된다.

 

9. 좀 길어지는 것 같아서... 2편으로 옮긴다.

- (공부중) #2 이런저런 기능 추가(?) 해보기