Quick Reference
| 공간 | 의미 |
|---|---|
| Object space | 모델 자체의 로컬 좌표 |
| World space | 장면 안의 공통 좌표 |
| View space | 카메라 기준 좌표 |
| Clip space | projection 후 clipping 기준 좌표 |
| NDC | x/y는 보통 -1..1, z는 API convention에 따라 0..1 또는 -1..1 |
| Screen space | 실제 픽셀 좌표 |
object -> world -> view -> clip -> NDC -> screen공간
그래픽스에서 좌표는 숫자 세 개가 아니라 어떤 기준에서 본 위치인가까지 포함합니다. 같은 (1, 0, 0)이라도 object space에서는 모델의 오른쪽일 수 있고, world space에서는 장면의 x축 방향일 수 있습니다.
좌표 공간을 섞으면 조명, 카메라, normal, texture projection이 모두 틀어집니다. 예를 들어 light direction은 world space인데 normal은 object space라면 dot product 결과는 의미가 없습니다.
dot(normal_object, light_world) // 서로 다른 공간이라 잘못된 계산
dot(normal_world, light_world) // 같은 공간이라 의미 있음변환
변환은 좌표를 한 공간에서 다른 공간으로 옮기는 연산입니다. translation, rotation, scale은 보통 4x4 행렬로 합쳐서 다룹니다. 4x4를 쓰는 이유는 위치 이동까지 행렬 곱으로 표현하기 위해 homogeneous coordinate를 사용하기 때문입니다.
위치는 homogeneous w = 1로 변환해 translation의 영향을 받고, 방향은 w = 0으로 변환해 translation을 받지 않습니다. normal은 비균일 scale이 있으면 model 행렬을 그대로 곱하지 않고 inverse-transpose normal matrix로 방향을 보정해야 합니다. 이를 빼면 회전하지 않은 모델에서도 조명이 기울어 보일 수 있습니다.
계산 기준
| 계산 | 보통 맞춰야 하는 공간 |
|---|---|
| 물체 배치 | world space |
| 카메라 상대 위치 | view space |
| clipping | clip space |
| 조명 dot 계산 | world 또는 view space |
| normal map | tangent space |
| 후처리 | screen space |
변환 순서도 중요합니다. scale, rotation, translation을 어떤 순서로 곱하느냐에 따라 결과가 달라집니다.
translate * rotate * scale
rotate * translate * scale두 식은 같은 숫자 행렬을 쓰더라도 “먼저 회전한 뒤 옮기는가”, “옮긴 뒤 원점 기준으로 회전하는가”가 달라집니다.
Unity에서는 local position을 world position으로 바꿀 때 TransformPoint, 반대 방향은 InverseTransformPoint를 사용합니다. 방향에는 translation을 적용하지 않으므로 TransformDirection, scale까지 반영하는 벡터에는 TransformVector를 구분합니다.
Vector3 worldPoint = transform.TransformPoint(localPoint);
Vector3 localPointAgain = transform.InverseTransformPoint(worldPoint);
Vector3 worldDirection = transform.TransformDirection(localDirection);주의할 점
행렬 표기와 곱셈 순서는 API와 수학 관례에 따라 달라질 수 있습니다. row-major/column-major, row vector/column vector, 왼손/오른손 좌표계를 함께 확인해야 합니다.
중요한 것은 특정 표기를 외우는 것이 아니라, 지금 값이 어느 좌표 공간에 있고 다음 단계가 어떤 공간을 요구하는지 추적하는 것입니다.
shader debug에서는 position, normal, light direction을 같은 공간 기준으로 color 또는 buffer에 출력해 확인합니다. 세 값을 한 행렬로 “맞춰 보이게” 변환하기보다, 각 값의 생성 공간과 필요한 소비 공간을 먼저 적어 두는 편이 좌표계 버그를 더 빨리 찾습니다.
참고 링크
2 sources