정점으로 폴라곤을 그리는 방법에 대해서 배우는 장이다. 용어에 대해서는 1장에서 했으니 넘기고..
정점을 뿌리기 위해서는 그래픽카드가 인지해야 하는데, 인지하기 위해서는 특정 함수로 그래픽카드 메모리(또는 시스템메모리)에 공간을 확보하는 작업을 해야 한다. 확보한 공간 정점 버퍼 또는 버텍스 버퍼 라 불리는데, 이제부터 버텍스 버퍼라 부르겠다.



버텍스 버퍼를 갖기 위해서는 정점 포맷을 결정해야 하는데, FVF(사용자 정의 정점 형식)을 이용하라고 DirectX는 권고하고 있다. 이것에 맞추지 않으면 전기적 쇼크가 뇌리에도 미치게 되니 자세히 알아야 할것이라고 책은 설명한다.


버텍스 버퍼를 만들면, 해당 버텍스 버퍼를 사용할 객체에 대한 포인터를 가져올수 있다. 이 객체는 인터페이스 객체로, 해당 버텍스 버퍼를 사용할수 있게 도와주게 된다.


버텍스 버퍼를 만들면 그 버퍼엔 쓰래기 값이 들어가 있기 때문에, 버텍스 버퍼만들때 얻어온 인터페이스 객체로 초기화해줄수가 있다.


얻어온 인터페이스 객체로 버텍스 버퍼에 알맞는 값을 셋팅해주었다면, 이제 뿌려주기만 남았다.


뿌려주는 방법은 해당 버텍스 버퍼를 사용하는 인터페이스 객체를 이용하여 후면 버퍼에 다 기록한 후에, 전면 버퍼로 플립핑 하는 방법으로 뿌려 주게 된다.


자세한 설명은 역시 코드를 보는게 더 좋을것이다.

//-----------------------------------------------------------------------------
// File: Vertices.cpp
//
// Desc: In this tutorial, we are rendering some vertices. This introduces the
//       concept of the vertex buffer, a Direct3D object used to store
//       vertices. Vertices can be defined any way we want by defining a
//       custom structure and a custom FVF (flexible vertex format). In this
//       tutorial, we are using vertices that are transformed (meaning they
//       are already in 2D window coordinates) and lit (meaning we are not
//       using Direct3D lighting, but are supplying our own colors).
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include 
#pragma warning( disable : 4996 ) // disable deprecated warning 
#include 
#pragma warning( default : 4996 )

#pragma comment(lib, "d3d9.lib")



//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9             g_pD3D = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // Our rendering device
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // 버텍스 버퍼의 인터페이스를 담을 포인터

// 사용자가 정의한 버텍스 구조체 VFV
struct CUSTOMVERTEX
{
    FLOAT x, y, z, rhw; // The transformed position for the vertex
    DWORD color;        // The vertex color
};

// 버텍스 구조체가 어떤 정보를 담을것인지 이렇게 정해 둔다.
// 자세한건 당연히 ... 도움말을 보아라.
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)




//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes Direct3D
// 내용 아까전에 한것이니 넘기고~
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
    // Create the D3D object.
    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;

    // Set up the structure used to create the D3DDevice
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof( d3dpp ) );
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

    // Create the D3DDevice
    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_pd3dDevice ) ) )
    {
        return E_FAIL;
    }

    // Device state would normally be set here

    return S_OK;
}




//-----------------------------------------------------------------------------
// Name: InitVB()
// 내용 : 전부 주석 달아 둔다.
//-----------------------------------------------------------------------------
HRESULT 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개의 크기만큼 공간을 할당하고,
	//  그 버텍스 버퍼를 사용할수 있는 인터페이스 객체의 포인터를 
	// g_pVB에 담는다.
    if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3 * sizeof( CUSTOMVERTEX ),
                                                  0, D3DFVF_CUSTOMVERTEX,
                                                  D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
    {
        return E_FAIL;
    }

	// 해당 인터페이스 객체(g_pVB)를 이용하여 Lock 하여 pVertices에 포인터를 얻어 온다.
    VOID* pVertices;
    if( FAILED( g_pVB->Lock( 0, sizeof( vertices ), ( void** )&pVertices, 0 ) ) )
        return E_FAIL;
	// 얻어온 포인터에 내가 정했던 버텍스 데이터를 밀어 넣고
    memcpy( pVertices, vertices, sizeof( vertices ) );
	// 해당 인터페이스 객체를 이용하여 Unlock 시켜 놓는다.
    g_pVB->Unlock();

    return S_OK;
}




//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
VOID Cleanup()
{
    if( g_pVB != NULL )
        g_pVB->Release();

    if( g_pd3dDevice != NULL )
        g_pd3dDevice->Release();

    if( g_pD3D != NULL )
        g_pD3D->Release();
}




//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
VOID Render()
{
    // 백버퍼를 파란색갈로 지워두고
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 );

    // 백버퍼를 사용할것이라고 디바이스에게 알린다.
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
		
		// DirectX의 출력스트림에, 아까 버텍스 버퍼로 얻어온 인터페이스 객체가 사용될것이라고 알린다.
        g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
		// 그 인터페이스 객체가 가리키는 버텍스 데이터가 어떤 형태인지 알리고
        g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
		// 후면버퍼에 기록하려고 명령 내린다. 인자값은 .. 도움말 참고 바란다.
        g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );

        // 작업이 끝났으니, 디바이스에게 끝났다고 알린다.
        g_pd3dDevice->EndScene();
    }

    // 백버퍼에 쓴것을 프론트 버퍼에 그리라고 명령 내리고
	g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
	
}	// 렌터를 종료하라고 알린다.




//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:            
            PostQuitMessage( 0 );
            return 0;
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}




//-----------------------------------------------------------------------------
// Name: wWinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
    // Register the window class
    WNDCLASSEX wc =
    {
        sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
        GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
        L"D3D Tutorial", NULL
    };
    RegisterClassEx( &wc );

    // Create the application's window
    HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 02: Vertices",
                              WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                              NULL, NULL, wc.hInstance, NULL );

    // Initialize Direct3D
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    {
        // Create the vertex buffer
        if( SUCCEEDED( InitVB() ) )
        {
            // Show the window
            ShowWindow( hWnd, SW_SHOWDEFAULT );
            UpdateWindow( hWnd );

            // Enter the message loop
            MSG msg;
            ZeroMemory( &msg, sizeof( msg ) );
            while( msg.message != WM_QUIT )
            {
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
                else
                    Render();
            }
        }
    }

	Cleanup();
    UnregisterClass( L"D3D Tutorial", wc.hInstance );
    return 0;
}



  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 라이프코리아트위터 공유하기
  • shared
  • 카카오스토리 공유하기