DirectX12에서 사용하는, 엄밀히는 Windows SDK의 일부인 DirectXMath의 벡터에 대해 알아보겠습니다.
먼저, 이 라이브러리는 SSE2(Streaming SIMD Extensions 2) 명령집합을 사용합니다.
SIMD 명령들은 128비트 너비의 SIMD(Single Instruction Multiple Data) 레지스터들을 이용해 32비트 float 또는 int 네 개를 하나의 명령에서 처리할 수 있습니다.
즉, 벡터 연산에 아주 유용합니다.
SMID : 병렬컴퓨팅의 한 종류로 하나의 명령으로 여러 값을 동시에 계산하는 방식
다음과 같은 벡터 연산을 스칼라 명령 4개가 아니라 SIMD 명령 하나로 처리할 수 있습니다.
x86 플랫폼에서는 SSE2를 활성화해야 하지만 x64 CPU는 모두 SSE2를 지원해 따로 활성화할 필요 없습니다.
SIMD 하드웨어 레지스터에 대응되는 XMVECTOR가 핵심 벡터 형식입니다.
XMVECTOR는 32비트의 부동소수점 값 4개로 구성되어있고
x64, SSE 활성화 x86 플랫폼에서 아래와 같이 정의됩니다
typedef __m128 XMVECTOR;
__m128 SIMD 형식을 사용해야만 벡터 연산 시 SIMD의 장점이 발휘됩니다.
2차원 3차원 벡터에서는 사용하지 않는 성분을 0으로 설정해서 무시하면 됩니다.
로컬 변수는 스택에, 전역 변수는 데이터 섹션에 자동으로 정렬하고 배치하지만, 힙에서 할당하는 것은 주의해야 한다. x64에서는 모든 힙이 16바이트로 할당되지만, x86은 8바이트입니다.
지역변수와 전역변수는 정렬이 자동으로 일어나 상관없지만, 클래스 멤버변수에는 이 형식 대신 XMFLOAT2, XMFLOAT3, XMFLOAT4를 사용하는 것이 권장됩니다.
그러나 이 형식들(XMFLOAT2, 3, 4)을 사용하면 SIMD의 장점을 가져갈 수 없으므로 이 형식들을 XMVECTOR로 변환해야 합니다,
이러한 FLOATn 형식을 XMVECTOR로 바꿔주는 적재함수와 XMVECTOR 형식을 FLOATn으로 바꿔주는 저장함수를 DirectXMath에서 제공합니다.
XMVECTOR 인스턴스를 인수로 함수를 호출할 때 효율성을 위해 값이 스택이 아니라 SSE/SSE2 레지스터를 통해 함수에 전달되게 해야 합니다.
전달할 수 있는 인수의 개수가 플랫폼과 컴파일러에 따라 달라 의존성을 없애기 위해 FXMVECTOR, GXMVECTOR, HXMVECTOR, CXMVECTOR 형식을 사용해야 합니다.
컴파일러에 대한 제약을 없애기 위해 XM_CALLCONV라는 호출규약 지시자를 함수 이름 앞에 붙여야 합니다.
입력 매개변수들에게 적용되는 규칙이며, 출력에는 SSE/SSE2 레지스터를 사용하지 않습니다.
상수 XMVECTOR 인스턴스에는 반드시 XMVECTORF32 형식을 사용해야 합니다.
static const XMVECTORF32 s_vecEye = { 100.0f, 5.0f, 5.0f, 0.f };
정수 자료를 담은 상수 XMVECTOR를 생성하려면 XMVECTORU32를 사용하면 됩니다.
XMVECTOR 객체의 내용을 설정하는 용도로 사용합니다.
XMVectorZero() → 0벡터 반환
XMVectorSplatOne() → 벡터 (1,1,1,1)를 돌려준다
XMVectorSet(float x, float y, float z, float w) → 벡터 (x,y,z,w)를 돌려준다
등등..
계산이 덜 정확하지만 속도가 더 빠른 함수들을 지원합니다.
XMVector3LengthEst(FXMVECTOR v) → 추정된 를 반환한다
Est가 붙은 함수들은 보통 추정 함수입니다.
부동소수점 수들을 비교할 때 부동소수점의 부정확함을 고려해야 합니다.
예를 들어, 정규화된 벡터의 길이는 수학적으로 1이여야 하지만, 부동소수점 연산에서 오차가 발생합니다.
이러한 이유 때문에 부동소수점 수의 상등을 판정할 때에는 두 수가 근사적으로 동일한지 봐야 하비다.
const float Epsilon = 0.001f;
bool Equals(float lhs, float rhs)
{
// lhs와 rhs간의 차지아 Epsilon보다 작은가?
return fabs(lhs - rhs) < Epsilon ? true : false;
}
DirectXMath.h 함수 레퍼런스