Quick Flow
local point
-> local scale
-> local rotation
-> local translation
-> parent world transform
-> world point행렬 곱은 교환법칙이 성립하지 않아 순서를 바꾸면 결과가 달라집니다. Row/column vector 표기와 row/column-major 메모리 배치는 별개의 계약이므로 math library, shader mul 방향, upload transpose를 함께 확인합니다.
합성과 계층
Column vector 관례의 대표 형태는 world = parentWorld * localTRS, localTRS = T * R * S입니다. 실제 코드는 사용하는 library 관례를 따릅니다. 부모가 회전·scale되면 자식의 local axis와 world 위치도 영향을 받습니다.
역행렬은 world point를 local space로 되돌리거나 한 좌표계에서 다른 좌표계로 바꿀 때 사용합니다. Scale 축에 0이 있으면 행렬이 singular해 inverse를 만들 수 없습니다.
Matrix4x4 localToWorld = transform.localToWorldMatrix;
Vector3 worldPoint = localToWorld.MultiplyPoint3x4(localPoint);
Vector3 localAgain = transform.worldToLocalMatrix.MultiplyPoint3x4(worldPoint);부모·자식 계층은 childLocal을 부모 공간에 둔 뒤 parentLocalToWorld로 world에 보냅니다. Unity API는 이 합성을 localToWorldMatrix에 반영하며, 직접 조합할 때는 library의 vector convention을 확인합니다.
DirectXMath와 HLSL을 연결할 때는 CPU의 World * View * Projection, constant buffer memory layout, upload transpose와 shader mul 방향을 하나의 계약으로 고정합니다. Matrix 숫자만 전달하지 말고 해당 값이 local을 clip으로 옮기는지 이름과 test로 확인합니다.
XMMATRIX world = XMMatrixRotationY(angle) * XMMatrixTranslation(0.0f, 0.0f, 4.0f);
XMMATRIX view = XMMatrixLookAtLH(eye, target, XMVectorSet(0, 1, 0, 0));
XMMATRIX projection = XMMatrixPerspectiveFovLH(fovY, aspect, nearZ, farZ);
ObjectConstants constants{};
XMStoreFloat4x4(
&constants.worldViewProjection,
XMMatrixTranspose(world * view * projection)
);cbuffer ObjectConstants : register(b0)
{
float4x4 worldViewProjection;
};
float4 ToClip(float3 localPosition)
{
return mul(worldViewProjection, float4(localPosition, 1.0));
}이 쌍은 DirectXMath row-vector 계산 결과를 transpose해 HLSL의 matrix-vector 곱으로 사용하는 한 가지 완성된 계약입니다. HLSL을 row_major와 mul(vector, matrix)로 설계할 수도 있지만 두 방식을 섞지 않습니다.
Normal 변환
Position은 translation을 받지만 direction은 받지 않습니다. Normal은 tangent surface와 수직을 유지해야 하므로 비균등 scale이 있는 model matrix M에서는 보통 transpose(inverse(M))의 3x3 부분으로 변환하고 다시 normalize합니다.
Negative scale은 handedness와 triangle winding을 뒤집을 수 있습니다. Transform hierarchy에서 mirror를 사용할 때 normal, tangent handedness와 cull mode를 함께 확인합니다.
자주 틀리는 점
- 행렬 저장 배치만 보고 vector 곱 방향을 추측하지 않습니다.
- 부모 world matrix와 자식 local matrix의 순서를 바꾸지 않습니다.
- Position, direction, normal을 같은
w와 같은 행렬로 처리하지 않습니다. - Inverse를 frame마다 반복 계산하기 전에 값 변경 시점을 확인합니다.
참고 링크
2 sources