HLSL에서는 변수 선언 시 "형(Type)"을 수정하거나 명확하게 해 주기 위해 Type Modifier(형 지정자)를 사용할 수 있다.
대표적으로 const, row_major, column_major가 있다. 이는 HLSL의 Type Modifier는 변수의 불변성(const)과, 행렬의 메모리 저장 순서(row_major, column_major)를 명시적으로 지정하여, 성능 최적화와 데이터 일관성을 높이는 데 사용됩니다.
Type Modifier 형 지정자
const : 상수 선언. 초기값이 설정된 후 수정할 수 없는 변수를 정의. 코드 안정성을 높이고, 컴파일러 최적화를 가능하게 한다. 전역변수의 경우 HLSL에서는 모든 전역 변수(Global Variable)가 사실상 const 속성을 기본적으로 가진다. 따라서 전역변수는 선언과 동시에 초기화하거나, 외부 애플리케이션(예: DirectX 코드)에서 값을 전달받아 초기화되어야 한다.(이후 애플리케이션에서 수정 불가)
const float MyValue = 0.5f; // 초기화 이후에는 hlsl에서 변경 불가 |
row_major : 행 우선 저장(row-major layout). 행(Row) 단위로 행렬 데이터를 메모리에 저장. 하나의 행(Row)에 해당하는 데이터가 한 레지스터에 연속적으로 저장. 일부 애플리케이션(CPU 코드)이 행 우선(Rows-first) 방식으로 메모리를 다루는 경우, 데이터 매칭을 쉽게 하기 위해 필요. HLSL 기본값은 column_major이므로, CPU와 GPU 간 데이터 호환을 위해 명시적으로 row_major를 써야 할 수 있다.
row_major float3x3 myMatrix; |
3x3의 행렬이 아래와 같이 있는경우
m00, _m01, _m02
_m10, _m11, _m12
_m20, _m21, _m22
레지스터에 저장되는 값은 아래와 같다.
레지스터1 → _m00, _m01, _m02
레지스터2 → _m10, _m11, _m12
레지스터3 → _m20, _m21, _m22
즉 하나의 행에 위치한 _m00, _m01, _m02를 하나의 상수 레지스터에 저장하게 하게 된다.
column_major : 열 우선 저장(column-major layout). 열 단위 행렬 데이터를 메모리에 저장. 특별히 명시하지 않았을 때 hlsl에서는 column_major가 디폴트 값이다. 일반적인 3D 그래픽스 수학에서는 열 우선 방식(Matrix × Vector) 계산을 선호
column_major float3x3 myMatrix; |
레지스터1 → _m00, _m10, _m20
레지스터2 → _m01, _m11, _m21
레지스터3 → _m02, _m12, _m22
계산방식의 차이는 아래와 같다.
| row_major | 행 중심으로 저장 및 곱셈 (Vector × Matrix) |
| column_major | 열 중심으로 저장 및 곱셈 (Matrix × Vector) |
- row_major를 사용할 경우: 벡터 × 행렬 (v × M) 스타일
- column_major를 사용할 경우: 행렬 × 벡터 (M × v) 스타일
HLSL은 기본적으로 column_major 기준이므로, 디폴트는 Matrix × Vector 계산 방식이다.
column_major 방식 (Matrix × Vector)
수식 : M × v (M : 3×3 행렬, v : 3×1 열 벡터)
계산 순서 :
| m00 m01 m02 | | v0 | | m00*v0 + m01 * v1 + m02 * v2 | | m10 m11 m12 | × | v1 | = | m10*v0 + m11 * v1 + m12 * v2 | | m20 m21 m22 | | v2 | | m20*v0 + m21 * v1 + m22 * v2 | |
- 행렬의 행과 벡터의 열을 곱해서 결과를 얻음
- 3개의 dot product(내적) 결과가 나옴
적용 예시 (HLSL 기본)
float3 result = mul(Matrix, Vector); |
→ Matrix가 column_major이면 정상 동작.
row_major 방식 (Vector × Matrix)
수식 : v × M (v: 1×3 행 벡터 / M: 3×3 행렬)
| v0 v1 v2 | × | m00 m01 m02 | | m10 m11 m12 | | m20 m21 m22 | 결과 : | v0 * m00 + v1 * m10 + v2 * m20 , v0 * m01 + v1 * m11 + v2 * m21 , v0 * m02 + v1 * m12 + v2 * m22 | |
- 벡터의 값과 행렬의 열을 곱해서 결과를 얻음
- 결과도 1×3 행 벡터 형태
적용 예시 (row_major 사용 시)
float3 result = mul(Vector, Matrix); |
→ Matrix가 row_major일 때 맞는 계산.
- 행렬의 저장 방식(row/column)은 메모리 배치에 영향을 주고,
- 곱셈 순서(Matrix × Vector vs Vector × Matrix)는 계산 방식에 영향을 준다
- HLSL은 기본적으로 column_major + Matrix × Vector를 가정한다.
그래서 만약 row_major로 저장했다면, mul(Vector, Matrix) 순서로 곱해주어야 올바른 결과가 나옴
'Technical Report > Other things' 카테고리의 다른 글
| Black Myth : Wukong Character 3D resource (2) | 2024.09.12 |
|---|---|
| sketchfab으로 3D object를 web에서 (0) | 2015.02.06 |
| Photoshop CS3 메모리 사용관련 (0) | 2013.03.04 |
| LCD 패널별 특성 (2) | 2011.10.21 |
| Windows 7 VT로 xp mode 사용 (2) | 2011.06.30 |