• 이전 글: ❎ Direct3D 11 Graphics Pipeline - 2. Input-Assembler 스테이지

  • Vertex Shader(VS)란, IA에서 넘겨준 정점 하나를 받아 GPU 공간에서 의미 있는 위치 / 속성으로 변환하여 다음 단계로 넘기는 프로그램

    • 중요한 것은 정점 하나를 받아 처리하여 넘겨주는 정점 단위 독립 실행 프로그램이라는 점!
  • 모든 렌더링에서 반드시 실행되며, 이후 단계들이 도형을 만들 수 있도록 정점의 기본 정보를 준비하는 단계

  • HLSL에서 전형적인 형태 예시

    struct VSInput {
        float3 pos: POSITION;
        float2 uv: TEXCOORD0; // 해당 Primitive에 입힐 텍스처 내 좌표
        uint iid: SV_InstanceID;
    };
    
    • 이 구조체가 정점 1개에 해당

1. 좌표 변환

  • VS의 가장 핵심적인 책임

  • 정점 데이터는 보통 Local 공간에 있으며, GPU가 화면에 그리려면 다음과 같은 변환을 거쳐야 함

    Local -> World -> View -> Projection -> Clip Space

    • 이 변환을 수행하는 것이 VS

    • 참고로 Clip 공간으로의 모든 변환을 VS에서 수행함

변환 코드 예시

  • VS는 최소한 반드시 SV_POSITION을 출력해야 함

    struct VSOutput {
        float4 pos: SV_POSITION;
    };
    
    • 이 값이 없으면 Rasterizer가 동작할 수 없고, 화면에 아무것도 출력되지 않음
cbuffer Transform: register(b0) {
    float4x4 WorldViewProj;
};

VSOutput VSMain(VSInput input) {
    VSOutput o;
    o.pos = mul(float4(input.pos, 1.0), WorldViewProj);
    return o;
}

2. 정점 속성 전달 및 생성

  • VS는 정점의 위치 외에도 공간 변환 결과, 색상, Instance ID 기반 offset 등 필요한 속성을 선택 및 (필요 시) 계산하여 다음 단계로 넘김

  • VS의 출력 대부분은 Rasterizer에서 보간됨

    • Pixel Shader는 정점 3개에서 나온 값을 픽셀 단위로 보간된 값으로 받음

    • 때문에 VS 출력을 PS를 위한 준비 단계라고도 볼 수 있음

3. VS의 실행 모델

  • VS는 정점 1개 당 1번 실행되고, 정점 간 서로 영향이 없으면서 순서 개념도 없기 때문에 수천 개의 VS가 동시에 실행됨

  • VS는 순수 함수에 가깝기 때문에 전역 상태 변경이나 다른 정점 접근, 동적 메모리 할당 등을 수행하지 않음

  • IA는 정점의 입력 형태를 만들고, VS는 정점에 의미를 부여하는 단계!

버퍼 없는 렌더링?