ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [21] - My First Triangle - 2
    Graphics 2021. 7. 22. 21:30

    Pixel Shader를 만듭니다. 이전에 다음과 같은 오류를 얻고 슬퍼했기 때문입니다.

    Pixel Shader가 당장 문제는 아닌 것 같습니다.

    PixelShader.hlsl를 Property에서 PixelShader로 명시를 해주고 Output 위치를 Project로 잡아주는 것은 Vertex Shader와 거의 같습니다. 이 PixelShader의 Output은 Pixel의 색을 설정해 주기 때문에 어떤 Colour value일 것입니다. RGBA값이니 float4입니다.

    Rasterizer가 pixel의 위치를 결정하기 때문에 Pixel Shader에서는 Pixel의 위치가 필요하지 않습니다.

    거의 완벽하게 Vertex Shader 와 같은 수순입니다. Blob은 따로 만들지 않고 그대로 사용하게 되는데 이걸 ComPtr로 설정했으니 overload된 &연산자의 성질 덕분에 기존의 Resource는 Free되고 새롭게 Resource를 붙잡고 있을 겁니다. 이제 오류 없이 잘 될까요?

    쉽지 않습니다. Pixel Shader를 Bind 했으니 더 많은 것들을 요구합니다

    Exception의 Message를 잘 읽어보면 Render Target View가 필요한 것 같습니다. 이 파이프 라인을 보면 다음과 같은 흐름인데 Pixel Shader를 Bind 했으면 Rasterizer를 거쳐 Output Merger에서 Render Target View로 가는 것을 확인할 수 있습니다. 

    Render Target View는 보이지 않지만 부연 설명을 읽어보면 관련이 있습니다

    Output Merger가 the contents of the render targets을 만든다고 합니다. 그 외에도 잔뜩 만든다고 합니다. 다른 문서를 확인해보면 만든다고 하기 보다는 Bind해야 한다고 보는 게 맞습니다. Error Message를 보면 Pixel Shader가 Render Target view가 Slot 0에 박혀 있길 원한다고 되어 있기도 합니다. 솔직히 잘 이해는 안 됩니다. 한 가지 확실한 건 Output Render Target을 명확히 설정하지 않으면 D3D는 다 만들어 낸 Pixel Shader의 Output를 어디에 출력해야 할 지 모른다는 겁니다.

    ID3D11DeviceContext::OMSetRenderTargets (d3d11.h) - Win32 apps Microsoft Docs

    여기에 모든 정보가 있습니다!! 몇 개의 Render Target를 넣을 것인가? 하나 입니다. 두 번째 Parameter는 Render Target view의 포인터인데 우연인지 아닌지 저번에 Bacl Buffer를 비운다고 만들어 두었던 Object가 있었습니다.

    여기에 있었습니다.

    세 번째 값은 Depth stencil이지만 잘 모를 땐 nullptr

    될까요?

    안 됩니다

    사실 명확하게 실수하고 있는 부분이 있었습니다. pTarget도 ComPtr로 만들었기 때문에 Overload된 &연산자로 넘겨주면 기존의 갖고 있던 Resource를 해제해버리고 새로운 Resource를 채울 준비를 합니다. 여기서 필요한 건 Array의 Pointer를 넘겨주는 것이지 Pointer의 Pointer에 새로운 Resource를 채우는 일이 아닙니다.

    잘 보면 Target View가 Bind 되지 않았다는 에러가 사라졌음을 확인할 수 있습니다. 안 되는 건 매 한 가지이긴 합니다.
    같은 이유로 IASet 도 Vertex Array의 포인터가 필요하기 때문에 &를 없애고 다음과 같이 넘겨줍니다.

    어차피 이걸 고쳐도 안 됩니다. 그렇다면 Viewports가 뭔지 알아보는 게 나을 것 같습니다. 그런데, 이걸 여기서 다루기에는 좀 양이 방대해서 따로 빼서 하겠습니다. 일단은 얼른 Viewport object를 만들어서 Bind 해줍니다.

    에러가 더 줄었습니다. 행복하다 그죠

    아까부터 계속 나오는 Primitive Topology는 무엇일까요? Graphics Pipeline이 모든 형상을 만들 수 있는 건 아닙니다. 기본적으로 삼각형만 그립니다. D3D는 몇 가지 삼각형을 제외하고 그릴 수 있는 옵션들이 있습니다.

    몇 가지가 이렇게 있습니다
    같은 MSDN 문서에 어떤 식으로 이 Array를 해석하는지 나와있습니다

    우리는 삼각형의 Vertices를 순서대로 이어가며 하나의 삼각형을 그릴 수 있도록 유도했습니다. 그러면 누가 봐도 TriangleList라고 Configure 해주는 것이 맞을 겁니다.

    그래서 이것도 해줬습니다. 그럼 에러가 하나 사라질 것입니다
    실제로 그 Topology Error가 사라졌습니다. 거의 다 왔습니다.

    이 에러를 상세하게 읽어보면 분명 우리는 Vertices를 정의하고 IAStage에 Bind도 해줬는데도 불구하고 IAStage에 Input이 없다고 합니다. Stride에 Vertex의 크기에 대한 정보도 줬고 bytewidth에 실제 Vertices의 크기까지 줬으며 이 buffer가 어디에 쓰일 것인지도 명시했습니다. 그런데 각 Vertex의 Layout에 대한 설명이 없습니다. Vertex에 몇 개의 Elements가 있는지, 각 Elements의 의미는 무엇인지, 목적이 뭔지, 뭘 할 것인지 설명이 없다는 겁니다. 여기서 솔직히 화가 안 날 수가 없긴 한데 이게 낭만입니다.

    그래서 D3D에게 직접 더 각 Elements의 의미, 목적, 행동 등의 정보를 알려줘야 합니다. 다음과 같이 합니다.

    여기서 끝이 아닙니다

    CreateInputLayout을 보면 pBlob이 사용된 것을 확인할 수 있습니다. 약간 잡기술인 것 같은데 만약 pixel shader를 vertex shader보다 먼저 만들었다면 두 개의 shader를 pipeline에 bind하고 난 다음엔 Vertex에 대한 정보가 이 blob에 있을 겁니다. 그래서 그걸 그대로 Layout을 구성하는데 쓰면 추가적인 노동 없이 쓸 수 있을 겁니다. 마침내! 빌드를 하고 디버그 하면 삼각형을 하나 볼 수 있습니다!

    삼각형 하나 만들기 참 힘듭니다!

     

    'Graphics' 카테고리의 다른 글

    [23] - Pipeline experiments  (0) 2021.07.30
    [22] - Viewport and clip space  (0) 2021.07.23
    [20] - My First Triangle - 1  (0) 2021.07.22
    [19] - ComPtr and Smart Pointer  (0) 2021.07.21
    [18] - Debug Layer Diagnostics  (0) 2021.07.21
Designed by Tistory.