입력 조립기(input assembler, IA) 단계는 메모리에서 기하 자료(정점들과 색인들)를 읽어서 기하학적 기본도형(삼각형, 선분 등)을 조립한다.
3D 물체는 어떻게 표현하는가? 제일 기본적인 도형인 삼각형으로 표현한다.

사진 출처
그럼 삼각형은 어떻게 만드는가? 3개의 정점과 3개의 변이 있으면 된다. 근데 왜 정점이라고 부르는가? 보통은 꼭짓점이라 부르는데 말이다. 왜냐하면 Direct3D의 정점은 본질적으로 공간적 위치 이외의 정보(예를 들어 법선 벡터 등)도 담을 수 있어서, 이를 통해 더 복잡한 렌더링 효과를 낼 수 있기 때문이다.
정점들은 정점 버퍼라고 하는 특별한 Direct3D 자료구조 안에 담겨서 렌더링 파이프라인에 묶인다. 마치 텍스처가 직접 묶이지 않고, 텍스터 자원 뷰가 묶이는 거나 마찬가지이다. 정점 버퍼 안에 있는 건 진짜 그냥 정점들의 정보들이다. 이 정점들을 어떻게 연결시키느냐, 이런 정보는 없다. 예를 들어 정점들을 선분으로 만들 수도 있고, 삼각형으로 만들 수도 있는데 말이다. 이렇게 기본도형을 형성하는 방식을 Direct3D에게 알려 주는 데 쓰이는 수단이 바로 기본도형 위상구조(primitive topology)이다. 다음은 기본도형 위상구조를 지정하는 메서드와, 그 열거형들이다.
void ID3D11DeviceContext::IASetPrimitiveTopology(
D3D11_PRIMITIVE_TOPOLOGY Topology);
enum D3D11_PRIMITIVE_TOPOLOGY
{
D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED = 0,
D3D11_PRIMITIVE_TOPOLOGY_POINTLIST = 1,
D3D11_PRIMITIVE_TOPOLOGY_LINELIST = 2,
D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP = 3,
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST = 4,
....
D3D11_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST = 64,
}
이 메서드를 호출해서 한 번 기본도형 위상구조를 설정하면, 다음 호출이 있을 때까지 모든 그리기 호출에서 그 위상구조가 적용된다. 다음은 그 예제이다.
md3dImmediateContext->IASetPrimitiveTopology(
D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
// 앞으로 선 목록을 적용해서 물체를 그린다.
...
md3dImmediateContext->IASetPrimitiveTopology(
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// 앞으로 삼각형 목록을 적용해서 물체를 그린다.
게임에서는 거의 삼각형 목록만 쓰이므로, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST만 알고 있으면 된다.
삼각형을 만들 때 다음과 같은 정점 배열들을 사용한다고 하자.
Vertex quad[6] = {
v0, v1, v2, // 삼각형 0
v0, v2, v3, // 삼각형 1
};
Vertex octagon[24] = {
v0, v1, v2, // 삼각형 0
v0, v2, v3, // 삼각형 1
v0, v3, v4, // 삼각형 2
v0, v4, v5, // 삼각형 3
v0, v5, v6, // 삼각형 4
v0, v6, v7, // 삼각형 5
v0, v7, v8, // 삼각형 6
v0, v8, v1, // 삼각형 7
};
이 삼각형들은, 다수의 정점들을 공유한다. 예를 들어, octagon 배열의 v0은 모든 삼각형에 들어있다. 이건 문제점을 유발한다. 어떤 문제?
이 문제를 해결하는 것이 바로 색인(index)이다. 즉, 고유한 정점들의 목록을 만들어 두고, 어떤 순서를 사용해서 삼각형을 형성할지 그 순서들을 따로 만드는 것이다. 그러면 위에서 정의한 정점 배열들은 이렇게 간략화 될 것이다.
Vertex quad[4] = {v0, v1, v2, v4};
Vertex octagon[9] = {v0, v1, v2, v3, v4, v5, v6, v7, v8};
이 고유한 정점들로 아까같은 삼각형을 만드려면, 다음과 같은 색인을 사용하면 된다.
UINT indexList[6] = {
v0, v1, v2, // 삼각형 0
v0, v2, v3, // 삼각형 1
};
UINT indexList[24] = {
v0, v1, v2, // 삼각형 0
v0, v2, v3, // 삼각형 1
v0, v3, v4, // 삼각형 2
v0, v4, v5, // 삼각형 3
v0, v5, v6, // 삼각형 4
v0, v6, v7, // 삼각형 5
v0, v7, v8, // 삼각형 6
v0, v8, v1, // 삼각형 7
};
어라, 그런데 이런 UINT 배열이 오히려 더 메모리를 잡아먹는 것이 아닌가? 당연히 아니다. 색인은 그냥 정수이므로, 정점 구조체보다 더 적은 양의 메모리를 차지한다. 정점이 많은 데이터를 가질수록 이 차이는 더욱 더 커진다.