카테고리 Archives: C++

[DX9] 4.라이트의 작성과 사용 1 – 신 지오메트리 초기화

Direct3D 라이트로 3D 오브젝트가 보다 리얼하게 보일 수 있게 되었습니다. 신의 각 지오메트리 오브젝트는 사용된 장소와 라이트의 종류를 베이스로 해서 라이트가 조사됩니다. 이 튜토리얼의 샘플 코드에서는 라이트와 매터리얼에 대해서 설명합니다.

[DX9] 4.라이트의 작성과 사용 1 – 신 지오메트리 초기화

라이트를 사용하는 요건의 하나로 각 서피스에 법선이 포함되도록 할 필요가 있습니다. Lights 샘플 프로젝트에서는 새로운 커스텀 정점 타입을 사용합니다. 새로운 커스텀 정점형식에는 3D 위치와 서피스 법선을 포함합니다. 서피스 법선은 내부에서 Direct3D가 라이트의 계산을 하는데 사용됩니다.

struct CUSTOMVERTEX
{
    D3DXVECTOR3 position; // The 3D position for the vertex.
    D3DXVECTOR3 normal;   // The surface normal for the vertex.
};
// Custom flexible vertex format (FVF).
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL)

이것으로 바른 벡터 형식이 정의 되었습니다. Light 샘플 프로젝트에서는 원기둥을 작성하는 애플리케이션 정의 함수인 InitGeometry 를 호출합니다. 처음에는 원기둥의 포인트를 격남한 정점 버퍼를 작성합니다. 다음 샘플 코드에 그것을 표시했습니다.

// Create the vertex buffer.
if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50*2*sizeof(CUSTOMVERTEX),
                                           0 /*Usage*/, D3DFVF_CUSTOMVERTEX,
                                           D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
    return E_FAIL;

다음에는 정점 버퍼를 원기둥의 포인트로 묻습니다. 다음 샘플코드에서는 각 포인트가 위치와 법선으로 정의 되어있습니다.

CUSTOMVERTEX* pVertices;
if( FAILED( g_pVB->Lock( 0, 0, (void**)&pVertices, 0 ) ) ) return E_FAIL;

for( DWORD i=0; i<50; i++ )
{
    FLOAT theta = (2*D3DX_PI*i)/(50-1);
    pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta),-1.0f, cosf(theta) );
    pVertices[2*i+0].normal   = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );
    pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf(theta) );
    pVertices[2*i+1].normal   = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );
}

http://ko.wikipedia.org/wiki/%EC%82%BC%EA%B0%81%ED%95%A8%EC%88%98

앞의 샘플코드를 사용해 정점 버퍼를 원기둥의 정점으로 묻으면 정점 버퍼는 렌더링 할 수 있게 됩니다.
다만, 이 신의 매터리얼과 라이트는 원기둥을 렌더링하기 전에 미리 설정해둘 필요가 있습니다.
이것에 대해서는「2 - 매터리얼과 라이트 설정」에서 설명합니다.

[DX9] 3.행렬의 사용방법 3 – 사영 트랜스폼 행렬 정의

사영 트랜스폼 행렬은 지오메트리를 3D 뷰 공간으로부터 2D뷰포트 공간으로 변환하는 방법을 정의하고 있습니다.

다음 코드는 사영 트랜스폼 행렬을 작성해 Direct3D 디바이스에 대해 현재의 사영 트랜스폼을 설정합니다.

D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );

첫번째로 D3DXMatrixPerspectiveFovLH 를 불러 사영 행렬을 셋업합니다. 첫번째 파라메터는 연산의 결과가 되는 D3DXMATRIX 구조체로의 포인터입니다. 두번째 파라메터는 시야를 정의하고 있습니다. 이것으로 먼곳에 있는 오브젝트일수로 작게 보이도록 됩니다. 일반적인 시야는 1/4pi 입니다. 샘플에서도 이것을 사용하고 있습니다. 세번째 파라메터는 아스펙트 비를 정의하고 있습니다. 샘플에서는 전형적인 아스펙트 비 값인 1을 사용하고 있습니다. 네번째와 다섯번째 파라메터는 전방 클립면과 후방 클립면을 정의합니다. 이것들에 의해 지오메트리가 렌더링 되지 않게 되는 거리를 정의합니다. Matrices 샘플 프로젝트에서는 전방 클립면을 1로 후방 클립면을 100으로 설정했습니다.

다음에는 IDirect3DDevice9::SetTransform 를 호출해 Direct3D 디바이스에 대한 트랜스폼을 적용합니다.IDirect3DDevice9::SetTransform 에 넘기는 첫번째 파라메터에 의해 설정된 트랜스폼을 Direct3D에 지시합니다. 이 샘플에서는 D3DTS_PROJECTION 플래그를 사용해서 설정할 필요가 있는 사영 트랜스폼을 지정합니다. 두번째 파라메터는 현재의 트랜스폼으로 설정된 행렬로의 포인터입니다.

사영 트랜스폼에 대한 자세한 것은 「사영 트랜스폼 (Direct3D 9)」을 참조해 주세요.

이 튜토리얼에서는 행렬을 사용하는 방법을 표시했습니다.「튜토리얼 4:라이트의 작성과 사용」에서는 리얼리티를 높여주기 위한 신에 라이트를 추가하는 방법을 다뤄 보겠습니다.