※ 본 게시물은 DirectX11을 기준으로 작성한다.
또한 순수하게 학습용이므로 절대적으로는 믿지 말 것.
삼각형그리기전에 코드를 분석할겸, 거의 소설 쓰듯 셰이더부분을 연결하는 코드를 이해하려고 이 게시물을 써본다.
따라서 그림으로 간단히라도 표현해보려는데, 개념적으로 정확한 그림이라 할 수 없다.
다만, 글쓴이 본인이 이해하는데 도움이 될거라 생각하여 기록을 남기는것이므로 너무 이상하게 생각하지 않았으면 좋겠다.
※ 주의) 일단 아래의 그림은 파이프라인의 구조로 봐서는 엉망인 그림이다. 이해하기 위해 참고만할것.
위 그림은 셰이더부분과 연결시키는 DX코드의 일부만을 순수하게 이해만을 위해 그림으로 표현해본것이다.
번호가 파이프라인의 순서와 일치한다는것이 아님에 주의바란다. 공부할때 코드를 작성한대로 넘버링을 했을뿐이다. 정점데이터들을 생성하기도전에 픽셀셰이더를 생성하는식으로 코드를 짰었는데 (위그림에는 픽셀셰이더에대한내용을 생략) 코드를 저런순서로 짜도 잘 작동하는거보면, 파이프라인에서 알맞은 위치에 바인딩이되어 순서에 영향을 크게 안주는듯하다. 물론 넣어줄곳을 만들고 알맞은 데이터를 바인딩 시켜야할 거라고는 생각한다.
먼저 정점셰이더(VertexShader)의 개념을 잠깐 얘기해보자. 정점셰이더는 정점 하나를 받아서정점하나를 출력하는 함수의 개념으로 생각하면 편하다. 이러한 정점셰이더에 넘어 오는값들은 먼저 입력조립기 단계(input assembler)에서 정점정보를 정리해서 넘겨 주게되는데, 그러한 정리된 정점을 읽어서 알맞은 형태의 정점정보로 만들어 레스터라이저(Rasterizer)에 넘겨주는게 정점셰이더의 일이다. (정점 셰이더의 주목적은 공간변환이다고 볼 수 있다.) 화면에 그려질 모든 정점들은 이 정점 셰이더를 거쳐서 온다고 보면된다.이 정점셰이더의 구체적내용들은 프로그래머가 구현해서 GPU에 알려주게된다. 그리하여 정점셰이더(하나의 기능을하는 함수라 생각)에 알맞은 작업을 각 정점에대해 GPU가 하게되는것이다. 정점셰이더에서는 입력정점자료 뿐만아니라, 텍스처UV, 변환행렬, 장면광원정보등 GPU 메모리에 담긴 다른 자료에도 접근할 수 있다. 이러한 정점셰이더를 통해 정점들이 어떠한 변환을 거치게 되는지, 또 어떠한 정점의 형태로 정보가 전달되는지 앞으로 차근차근 알아볼 예정이다. (기본구조에서는 테셀레이터를 거치지않는 단계에서 생각한다. 테셀레이터는 정점데이터를 변형시키는 기법으로 기본단계에서 공부하기에는 혼란을 줄 수 있으므로 나중에 공부해보자.)
본론으로 와서 위의 그림을 간단히 설명하자면,
1. 프로그래머가 작성한 VertexShader File을 D3DX11CompileFromFile()함수를 통하여 이진코드로만들어 네이티브명령들로 컴파일한다. 그것을 VertexShader Buffer에 담는과정이다.
2. Device에 CreateVertexShader()함수와 앞에서 만든 VertexShader Buffer의 주소,크기를 이용해VertexShader를 만들어준다.
cf.) VertexShader가 생기는곳은 GPU위의 메모리인지, 정확히 모르겠다. 하지만 GPU가 VertexShader의 기능을 수행하게 되는것이고, 결국 VertexShader는 밑 3번에서 DX의 파이프라인에 바인딩 되므로, 너무 골치아프게 생각하지말자.
cf.)GPU에대한 이해 참고.
http://blog.appkr.kr/learn-n-think/3d-graphics/
3. 앞에서만든 VertexShader를 DeviceContext의 알맞은 함수를 통하여 파이프라인에 바인딩시켜준다.
cf.) PixelShader도 VertexShader와 비슷한 과정을거쳐 만들어주게 된다.
4. Device의 CreateBuffer()함수와 정해준 속성인 D3D11_BUFFER_DESC,정점 데이터를 담은 D3D11_SUBRESOURCE_DATA를이용하여 VertexBuffer를 만들어주었다.
5. 앞에서 만든 VertexBuffer를 알맞은 DeviceContext의 함수를 통하여 파이프라인에 바인딩.
6. Device의 CreateInputLayout()함수와 세팅해둔D3D11_INPUT_ELEMENT_DESC의 정보, 그리고VertexShader Buffer의 주소,크기를 이용해 VertexShader에 넣어줄 InputLayout을 만든다.
cf.) 이것을 VertexShader Buffer와 연관지어 만드는이유는 솔직히 와닿지는 않는데, 아무래도 셰이더 코드에서의 시멘틱과 연결지어서 INPUT_ELEMET_DESC를 만들어주었기에, 저런식으로 CreateInputLayout()함수에 쓰인것이 아닐까..
7. 앞에서만든 InputLayout을 DeviceContext의 알맞은 함수를 사용하여 파이프라인에 바인딩.
자, 앞에서의 내용을 조금은 이해했다면이제 구글에서 쉽게구할수있는, 복잡한 파이프라인이미지를준비했다. 앞의 내용을 이해하고, DirectX11의 파이프라인을보면 어느시점에, 어떠한 정보들이 파이프라인 어디쯤에 바인딩되는지조금더 자세히 알 수 있으리라 생각한다. 아마 알맞은 위치를 찾아 바인딩되는 것은 그에 알맞은 함수를써서 찾아갈 수 있지않나 생각된다.
위의 파이프라인은 현재 이해안가는것이정상적일것이라 생각되지만, (이해하시면 저좀 알려주세요)하나하나 코드를작성하다 어떠한 것을 쓰는지 보다보면 부분부분 이해가기 시작할것이라기대한다.
'ComputerScience > DirectX11' 카테고리의 다른 글
DirectX11 3D를 보여주기 위한 윈도우 -(4) Main.cpp (0) | 2018.10.11 |
---|---|
DirectX11 3D를 보여주기 위한 윈도우 -(3) Engine.h, Engine.cpp (0) | 2018.10.10 |
DirectX11 3D를 보여주기 위한 윈도우 - (2) DXApp.cpp -5 (InitDirect3D함수) (0) | 2018.10.10 |
DirectX11 3D를 보여주기 위한 윈도우 - (2) DXApp.cpp -4 (콜백함수 WinProc, MsgProc) (0) | 2018.10.08 |
DirectX11 3D를 보여주기 위한 윈도우 - (2) DXApp.cpp -3 (Init함수, InitWindow함수) (0) | 2018.10.08 |