상세 컨텐츠

본문 제목

[DirectX11] Graphics Pipeline 3 - Rasterizer

DirectX 11

by 이나시오- 2024. 8. 26. 14:11

본문

 Vertex Shader 다음으로 Rasterizer에 대해 알아보겠다. Vertex Shader와 Rasterizer 사이에 Tessellation stage라고 Hull Shader, Tessellator, Geometry Shader의 과정도 있다. 이 단계들은 정점 정보를 이용해 더 정점들을 추가적으로 계산해서 더 디테일한 표면을 구현하기 위해 거치는 단계이다. 하지만 렌더링에서 필수적인 단계는 아니고, 구체적인 내용은 아직 공부하지 못해서 Rasterizer를 먼저 정리하기로 했다.

 

Rasterizer

 Rasterizer는 vertex 정보들로 구성한 벡터 기반의 topology를 pixel로 변환하는 과정이다. 즉, 말 그대로 vector을 raster로 만들기 때문에 Rasterizer인 것이다. 아래 이미지를 보면 vector의 경우 점을 이어서 도형을 구성한 것이므로 해상도에 관계없이 부드러운 도형을 만들 수 있다. Raster의 경우 격자형의 픽셀들에서 픽셀 값을 이용해서 도형처럼 보이도록 구성하는 것이기 때문에, 저해상도의 경우 아래 이미지처럼 픽셀이 보이는 경우가 발생할 수 있고, 고해상도여도 이미지를 확대해보면 픽셀들이 보인다. 현재 우리가 갖고 있는 정보는 vector 정보인데, 화면에 출력하기 위해서는 모니터의 각 픽셀 값을 설정해야 하므로 결국 raster 정보가 필요하다. 이러한 변환과정을 진행하는 것이 Rasterizer이다.

출처 : 위키피디아

 

 Rasterizer Stage에서 vertex들을 이용해서 도형의 영역에 해당하는 픽셀을 계산하는 과정 뿐만 아니라, vertex가 갖고 있던 값들 (예: UV, Color)을 거리에 따라 선형 보간을 통해 픽셀 마다 값을 할당해준다. 따라서 vertex에 할당된 값들이 픽셀들에 부드럽게 이어지도록 할당된다.

 

Rasterizer 생성

 Rasterizer는 따로 생성하지 않아도 기본 옵션으로 적용되지만, 원하는 옵션이 있는 경우 생성해줘야 한다. D3D11_RASTERIZER_DESC 구조체를 전달해서 생성하는데, CullMode와 FillMode를 설정해야 한다.

 

 cull은 '추려내다'라는 뜻으로, CullMode는 vertex 정보를 rasterize 할 때 픽셀을 어떻게 선택할 건지에 관한 옵션이다. CullMode가

cull_back이면, 면의 뒷면에 해당하는 픽셀은 채택하지 않고,

cull_front이면, 앞면에 해당하는 픽셀은 채택하지 않고,

cull_none이면, 앞 뒷면 모두 렌더링할 픽셀로 채택하는 것이다.

 이 때 앞/뒷면은 vertex의 순서가 시계방향/반시계방향으로 구성됨으로 구분한다. (DirectX의 경우 Front : CW(시계방향), Back : CCW(반시계) / OpenGL의 경우 Front : CCW, Back : CW) 보통 cull_back이나 cull_none을 사용하지만, 뒷면을 봐야하는 경우 cull_front를 사용한다. 예를 들면 스카이 박스라는 큰 구체 안에 게임을 만들게 되는데, 이 때 카메라가 스카이 박스 안에서 그 내면을 렌더링해야 하므로 cull_front를 사용한다고 한다.

 

 FillMode는 면을 채울 때 어떤 픽셀을 채택할 건지에 관한 옵션이다. FillMode가

fill_solid이면 면의 전체를 채우고,

fill_wireframe이면 면은 채우지 않고 면을 둘러싸는 선분들에 해당하는 픽셀만 채택하게 된다.

// m_RSState[4] : 서로 다른 4개의 rasterizer을 담아두는 배열, ComPtr<ID3D11RasterizerState>[4]
// RS_TYPE : enum class

// CULL_BACK : 뒷면, CCW, Default
m_RSState[(UINT)RS_TYPE::CULL_BACK] = nullptr;

// CULL_FRONT : 앞면, CW, 예 : Skybox의 내부를 볼 때
D3D11_RASTERIZER_DESC Desc{};
Desc.CullMode = D3D11_CULL_FRONT;
Desc.FillMode = D3D11_FILL_SOLID;
DEVICE->CreateRasterizerState(&Desc, m_RSState[(UINT)RS_TYPE::CULL_FRONT].GetAddressOf());

// CULL_NONE
Desc.CullMode = D3D11_CULL_NONE;
Desc.FillMode = D3D11_FILL_SOLID;
DEVICE->CreateRasterizerState(&Desc, m_RSState[(UINT)RS_TYPE::CULL_NONE].GetAddressOf());

// WIRE_FRAME
Desc.CullMode = D3D11_CULL_NONE;
Desc.FillMode = D3D11_FILL_WIREFRAME;
DEVICE->CreateRasterizerState(&Desc, m_RSState[(UINT)RS_TYPE::WIRE_FRAME].GetAddressOf());

 

나중에 이론적인 부분을 더 스터디해서 포스트를 보충할 예정이다.

 

관련글 더보기