• 이전 글: ❎ Direct3D 11 Graphics Pipeline - 3. Vertex Shader 스테이지

  • VS까지의 결과는 정점 단위의 수학적 도형과 연속적인 공간 개념을 가진 수학적 모델이지만 GPU가 실제로 화면에 그릴 수 있는 최소 단위는 물리적 픽셀 단위이기 때문에 이 사이의 계산을 해주는 것이 바로 Rasterizer

  • Rasterizer는 Shader와 달리 프로그램이 아니라 하드웨어(GPU) 기능으로, HLSL로 조정 가능한 프로그래밍 대상이 아님

    • 설정(State)에 따라 동작만 변경 가능
  • Vertex Shader는 수학적 연산을 담당, Rasterizer는 기하 정보에서 실제 픽셀로의 변환을 담당

1. 입력과 출력

  • 입력

    • VS로부터 받은 Primitive(점 / 선 / 삼각형)

    • 각 Primitive의 Clip 공간 좌표

    • VS에서 출력하는 기타 속성들

  • 출력

    • 픽셀의 후보가 될 fragment들

    • 보간된 정점의 속성들

    • 픽셀의 위치(Screen 공간 좌표)

2. Rasterizer 수행 단계 흐름

  • Rasterizer의 작업 흐름은 하드웨어에서 자동으로 수행

1. Clipping

  • VS에서 넘어온 Clip 공간 기준으로 화면 밖에 있는 기하를 잘라냄

    • VS에서 온 SV_POSITION(Clip 공간 좌표) 기준으로 수행
  • 삼각형이 화면 밖에 걸쳐 있으면 경계선에서 삼각형이 잘리면서 새로운 정점들이 생성됨

  • 삼각형이 화면에 완전히 밖이면 Primitive 자체가 제거됨

2. Perspective Division

  • Clip 공간 좌표((x, y, z, w))를 입력으로 받아 NDC(Normalized Device Coordinates) 좌표((x / w, y / w, z / w))를 출력

3. Viewport 변환

  • NDC 좌표를 실제 화면 픽셀 좌표로 변환

  • Viewport: 화면의 어디에서 얼마나 큰 영역에 렌더링 결과를 그릴 것인가를 정의

  • Viewport를 설정하지 않으면 Rasterizer는 정상 동작하지 않기 때문에 렌더링 초기화 시 반드시 설정해주어야 함

    • 예시

      D3D11_VIEWPORT vp;
      vp.TopLeftX = 0;
      vp.TopLeftY = 0;
      vp.Width    = screenWidth;
      vp.Height   = screenHeight;
      vp.MinDepth = 0.0f;
      vp.MaxDepth = 1.0f;
      
      context->RSSetViewports(1, &vp);
      

4. 후면 제거(back-face culling)

  • 카메라에 등지고 있는(카메라가 후면을 바라보고 있는) 삼각형 제거

  • 성능 최적화와 중복 렌더 방지

  • Rasterizer State에서 정점의 권선 방향(winding order) 기준으로 판단 기준 설정

5. fragment 생성 및 속성 보간(scan conversion)

  • 삼각형 내부를 덮는 모든 픽셀 위치를 계산. 이 결과물이 Pixel(Fragment) Shader의 입력 단위가 됨

  • Rasterizer는 픽셀 자체를 만들지는 않고, 이후 PS가 판단해서 화면에 픽셀을 그릴지 말지 결정하는 픽셀 후보(fragment)들을 생성함

  • fragment에는 화면 좌표, 깊이 값, 보간된 정점 속성 등이 포함됨

3. Rasterizer State

  • Rasterizer는 프로그래머블하지 않고, 모든 동작은 State 객체로 제어

  • D3D11에서 Rasterizer State 생성 흐름

    D3D11_RASTERIZER_DESC desc = {};
    desc.FillMode = D3D11_FILL_SOLID;
    desc.CullMode = D3D11_CULL_BACK;
    desc.FrontCounterClockwise = FALSE;
    
    ID3D11RasterizerState* rs = nullptr;
    device->CreateRasterizerState(&desc, &rs);
    context->RSSetState(rs);
    

Rasterizer State 핵심 항목들

  • FillMode: 면을 어떻게 그릴 것인가

    • D3D11_FILL_SOLID: 삼각형 내부를 채움

    • D3D11_FILL_WIREFRAME: 삼각형의 변만 그림

  • CullMode: 어떤 면을 버릴 것인가

    • D3D11_CULL_BACK: 후면 제거(가장 일반적)

    • D3D11_CULL_FRONT: 앞면 제거

    • D3D11_CULL_NONE: 모두 그림

      • 메시가 통째로 안보일 때는 대부분 컬링의 문제이므로 D3D11_CULL_NULL로 찍어보는 디버깅을 많이 함
  • FrontCounterClockwise: 앞면의 정의

    • 기본값은 FALSE. 정점의 순서가 시계 방향인 경우 앞면으로 계산

    • 이 설정과 Mesh 인덱스 순서가 맞지 않으면 삼각형이 모두 사라짐

  • DepthBias: 깊이 값을 인위적으로 살짝 밀어낼 수 있는 기능

    • Shadow Map의 Z-fighting 방지

    • 일반 렌더링에서는 잘 안쓰지만, 그림자 구현 시에는 반드시 필요한 설정

  • MultisampleEnable

  • ScissorEnable

Multisample / Antialias?

  • Rasterizer는 멀티샘플링(MSAA)에도 관여함

  • 지금은 ‘Rasterizer가 안티앨리어싱에도 관여하는구나~’ 정도만 짚고 가면 될 듯

Scissor

  • 이미 만들어진 fragment 중에서 특정 사각형 영역만 통과시키는 마스크

  • 화면 크기와는 독립적으로, 개발자가 지정한 사각형 영역 안에 들어오는 픽셀만 통과시키는 픽셀 단위 마스킹

    • UI 클리핑 등에 활용
  • Clipping은 Rasterizer 초입에서 일어나는 기하 단위 절단, Scissor는 fragments가 생성된 뒤 일어나는 픽셀 단위 마스킹

4. Rasterization Rules

Rasterization Rules

  • 문서로 정리할 정도로 중요한 내용은 아니고, D3D 11을 지원하는 하드웨어가 보장하는 규칙과 한계를 명시한 것

  • Rasterizer는 수학적인 연속 공간을 이산적인 픽셀 격자로 바꾸는 단계이기 때문에 지켜야 하는 규칙과 제약이 존재

    • 하드웨어(GPU)마다 Resterization 결과가 달라지지 않도록 하기 위한 목적(같은 입력이면 하드웨어가 달라도 항상 같은 픽셀 결과)
  • 다음 글: ❎ Direct3D 11 Graphics Pipeline - 5. Pixel Shader 스테이지