카테고리 Archives: C++

[DX9] 2.정점의 렌더링 3 – 표시의 렌더링

이것으로 정점 버퍼에 정점이 격납되었습니다. 다음은 표시를 렌더링합니다. 표시의 렌더링에서는 먼저 백 버퍼를 클리어 해 청색으로 하고 그 다음 BeginScene 을 호출합니다.

g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0L );
g_pd3dDevice->BeginScene();

정점 버퍼로부터 정점 데이터를 렌더링 하려면 몇 단계를 거칩니다. 우선 스트림 소스를 설정합니다. 이 때 스트림 0을 사용합니다. 스트림 소스는 IDirect3DDevice9::SetStreamSource 를 호출해서 지정합니다.

g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );

첫번째 파라메터는 스트림 번호, 두번째 파라메터는 정점 버퍼로의 포인터 입니다. 세번째 파라메터는 스트림의 선두로부터 정점 데이터의 선두까지의 오프셋입니다. 이 예에서는 0입니다. 마지막 파라메터는 정점 선언의 각요소의 바이트 수입니다.

다음은 IDirect3DDevice9::SetFVF 를 호출해 고정기능의 정점 쉐이더를 식별합니다. 완전한 커스텀 정점 쉐이더는 고도의 토픽입니다만 여기서의 정점 쉐이더는 간단한 플렉서블 정점 포맷(FVF) 코드에 불과합니다. 다음 샘플 코드는 FVF 코드를 설정하고있습니다.

g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );

SetFVF 의 유일한 파라메터가 정점 데이터 레이아웃을 정의하는 고정 정점 함수 코드입니다.

다음은 아래의 샘플 코드에 나오는 것처럼 IDirect3DDevice9::DrawPrimitive 를 사용해 정점 버퍼의 정점을 렌더링 합니다.

g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );

DrawPrimitive 가 받아들이는 1번째의 파라메터는 Direct3D에 드로우하는 프리머티브의 종류를 지시하는 플래그입니다. 이 샘플에서는 D3DPT_TRIANGLELIST 플래그를 사용해 삼각형의 리스트를 지정합니다. 두번째 파라메터는 처음 로드할 정점의 인덱스입니다. 세번째 파라메터는 드로우할 프리머티브의 수를 나타냅니다. 이 샘플에서는 1개의 삼각형만 드로우하므로 이 값은 1이 설정됩니다.

각종 프리머티브의 자세한 내용에 대해서는 「프리머티브」를 참조해 주십시오.

마지막으로 신을 종료한 후 백 버퍼를 프론트 버퍼에 할당합니다. 이 예를 다음 코드에 나타냈습니다.

g_pd3dDevice->EndScene();
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

백 버퍼를 프론트 버퍼에 할당하면 클라이언트 윈도우에 3개의 다른 컬러의 포인터를 가진 삼각형이 표시됩니다.

이 튜토리얼에서는 정점을 사요해서 지오메트릭 쉐이프를 렌더링하는 방법을 다뤘습니다.「튜토리얼 3: 행렬의 사용방법」에서 행렬의 컨셉과 그 사용방법을 소개합니다.

[DX9] 2.정점의 렌더링 2 – 정점 버퍼의 설정

커스텀 정점 포맷이 정의 되면 다음은 정점을 초기화 합니다. Vertices 샘플 프로젝트에서는 필요한 Direct3D 오브젝트를 작성한 후에 애플리케이션 정의 함수인 InitVB를 호출해 이것을 실행합니다. 다음 샘플 코드는 3개의 커스텀 정점의 값을 초기화 합니다.

CUSTOMVERTEX vertices[] =
{
    { 150.0f,  50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color
    { 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },
    {  50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, },
};

상기 샘플 코드에서는 3개의 정점을 3각형의 포인트로 채우고 각 정점이 방사하는 컬러를 지정합니다. 제1포인트는  (150, 50)이고 컬러는 빨강(0xffff0000)입니다. 제2포인트는(250, 250)이고 컬러는 초록(0xff00ff00)입니다. 제3포인트는 (50, 250)이고 컬러는 청록(0xff00ffff)입니다. 이들 포인트는 각각 심도치는 0.5, RHW(Reciprocal of the W coordinate from the Homogeneous point;동차 좌표 w 성분의 역수)는 1.0입니다.

다음은 아래의 샘플코드에 나타낸 것처럼 IDirect3DDevice9::CreateVertexBuffer 를 호출해 정점 버퍼를 작성합니다.

if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX),
         0 /*Usage*/, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
    return E_FAIL;

IDirect3DDevice9::CreateVertexBuffer 의 최초 두개의 파라메터는 Direct3D 에 새로운 정점 버퍼의 필요 사이즈와 용도를 지시합니다. 다음 2개의 파라메터는 새로운 버퍼의 벡터 포맷과 메모리 위치를 지정합니다. 여기서는 벡터 포맷은  D3DFVF_CUSTOMVERTEX 으로 샘플 코드가 이전에 지정한 플렉서블 정점 포맷 (FVF) 입니다. D3DPOOL_DEFAULT 플래그는 Direct3D 에 이 정점 버퍼에 최적의 메모리를 할당해 정점 버퍼를 작성하도록 지시합니다. 마지막 파라메터는 작성하는 버퍼의 어드레스입니다.

정점 버퍼의 작성 후 다음 샘플 코드에 나온 것처럼 커스텀 정점 데이터로 그것을 채웁니다.

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

memcpy( pVertices, vertices, sizeof(vertices) );

g_pVB->Unlock();

우선 IDirect3DVertexBuffer9::Lock 을 호출해 정점 버퍼를 록합니다. 첫번째 파라메터는 록할 정점 데이터의 오프셋(바이트 단위)입니다. 두번째 파라메터는 록할 정점 데이터의 사이즈(바이트 단위)입니다. 세번째 파라메터는 BYTE 포인터의 어드레스로 정점 데이터로 포인터를 격납합니다. 4번째 파라메터는 정점 버퍼에 데이터의 록 방법을 지시합니다.

그 다음 memcpy 를 사용해 정점은 정점 버퍼에 복사됩니다. 정점 버퍼에 정점이 읽어들여지면  IDirect3DVertexBuffer9::Unlock 을 호출해 정점 버퍼의 록을 해제합니다. 정점 버퍼는 디바이스 메모리 내에 존재할 가능성이 있으므로 이 록, 그리고 록 해제의 메카니즘이 필요합니다.

이것으로 정점 버퍼에 정점이 격납됩니다. 다음은「 3 – 표시의 렌더링」에서 표시를 렌더링 하는 것을 다룹니다.