본문 바로가기
프로그래밍/DirectX

DirectX - 행렬(Matrices)

by 리뷰하는 (게임)프로그래머_리프TV 2010. 6. 14.


Dx에서 3차원의 정점(Vertex)를 화면상의 모니터로 출력해 주기 위해서는

3가지의 행렬 변환이 필요 하다.

1. 월드 행렬
2. 뷰 행렬
3. 투영 행렬

월드 행렬의 경우에는 3D오브젝트의 로컬좌표를 3차원의 필드에 특정 위치에 뿌려 주기 위해서,
( 좀더 간단하게 말하면, 로컬 좌표를 월드 좌표로 변환 하는 작업 )

뷰 행렬은 카메라를 셋팅한다고 생각하면 되는데,
뷰 행렬을 만들기 위해서는 추가적인 3개의 백터가 필요 하다.
카메라의 위치, 카메라가 바라보는 방향, 카메라의 Up벡터가 필요 하다.

마지막으로 투영 행렬은,
각각의 3D좌표들을 우리의 눈으로 보게 되는 2D로 변경하는 작업을 한다.

이런 작업을 렌더링 파이프라인이라고 하는데,

3D의 좌표를 모니터 화면에 뿌려주기 위한 작업이라고 보면 된다.

VOID SetupMatrices()
{
    // 월드 좌표계를 생성하기 위한 행렬.
    D3DXMATRIXA16 matWorld;

    // 튜토리얼 예제에서는 시간이 흐를 때 마다, 월드 행렬을 Y축을 기준으로 회전을 시킨다. 
    UINT iTime = timeGetTime() % 1000;
    FLOAT fAngle = iTime * ( 2.0f * D3DX_PI ) / 1000.0f;
    D3DXMatrixRotationY( &matWorld, fAngle );
    // 월드 행렬에 대한 값을 다 수정했으면, 마지막으로 디바이스에 셋팅.
    g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

    // 뷰 행렬에 필요한 3가지 값을 벡터로 넣어주고,
    // D3DXMatrixLookAtLH 함수를 사용해 행렬 생성 후 
    // 디바이스에 셋팅한다.
    D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f );
    D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
    D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
    D3DXMATRIXA16 matView;
    D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
    g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

    // 마지막으로 투영 행렬을 설정 해야 하는데,
    // 행렬을 하나 만들고, 
    // D3DXMatrixPerspectiveFovLH 함수를 사용해 생성하게 되는데
    // 2번째 인자는 시야각(45도), 종횡비(1.0f), 근접 클리핑 평면, 원거리 클리핑 평면이다.
    // 즉, 45도의 시야각으로 1~100의 범위 안에 있는 것만을 보여주게 한다는 것이다.
    D3DXMATRIXA16 matProj;
    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f );
    g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}​


이제 이 작업을 Render할때 마다 해주어야 한다.
D3DInit나 InitVB와는 다르게,

행렬에 관한 연산은 매번 처리를 해 주어야 한다.

VOID Render()
{
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 0 ), 1.0f, 0 );

    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
        // 렌더를 시작 할 때, 이처럼 매번 행렬 셋팅을 해주어야 한다.
        SetupMatrices();

        // 버택스를 출력 한다.
        g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
        g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
        g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 1 );

        g_pd3dDevice->EndScene();
    }

    // 화면에 출력 
   g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
​


전체 소스는 생략,