Shader를 작성하다 보면 꼭 마주치는 개념이 있다.

바로 행렬(Matrix) 변환이다.

오브젝트를 화면에 그리기까지는 다양한 공간 좌표계를 거치게 되는데, 이때 행렬 변환이 핵심적인 역할을 한다.

다행히도 Unity에서는 자주 사용하는 변환 행렬을 미리 선언해두고, Shader 코드에서 바로 사용할 수 있게 지원하고 있다.

공간 좌표계 요약

Shader에서 다루는 주요 공간은 아래와 같다.

  • Object Space (모델 공간): 오브젝트 자체의 로컬 좌표계
  • World Space (월드 공간): 씬 전체에서의 위치
  • View Space (카메라 공간): 카메라를 기준으로 본 공간
  • Clip Space (클립 공간): 최종적으로 GPU가 클리핑할 좌표계

주요 행렬 매크로

이름 설명
UNITY_MATRIX_M unity_ObjectToWorld Object → World 변환. 모델 매트릭스
UNITY_MATRIX_I_M unity_WorldToObject World → Object 변환. 모델 행렬의 역행렬
UNITY_MATRIX_V World → View 변환. 뷰 매트릭스
UNITY_MATRIX_P View → Clip 변환. 투영 매트릭스
UNITY_MATRIX_MV Object → View 변환. 모델-뷰 매트릭스
UNITY_MATRIX_VP View → Clip 변환. 뷰-프로젝션 매트릭스
UNITY_MATRIX_MVP Object → Clip 변환. 가장 많이 쓰이는 MVP 매트릭스

UNITY_MATRIX_MVP는 버텍스 쉐이더에서 거의 필수적으로 사용된다.

예제 코드

아래는 버텍스 쉐이더에서 UNITY_MATRIX_MVP를 이용해 로컬 좌표를 클립 공간으로 변환하는 코드다.

float4 vert(appdata v) : SV_POSITION
{
    return mul(UNITY_MATRIX_MVP, v.vertex);
}

만약 월드 좌표가 필요하다면, 다음과 같이 모델 행렬만 따로 사용할 수도 있다.

float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

주의할 점

  • UNITY_MATRIX_I_Munity_WorldToObject는 같은 의미지만, 내장 렌더 파이프라인에서는 후자만 제공된다.
    • URP에서는 둘 다 사용 가능하다.
  • mul(A, B)A * B와 같지만, HLSL에서는 행 벡터 기준으로 작동하기 때문에 곱셈 순서에 주의해야 한다.

댓글남기기