- 음악과 나 -/『 짬 통 』

Vertex Beffer

noon2dy 2006. 10. 7. 02:40

//-----------------------------------------------------------------------------
// 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  // Direct3D9를 사용하기위한 헤더

 


//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
// D3D 디바이스를 생성할 D3D 객체 변수
LPDIRECT3D9             g_pD3D       = NULL; // Used to create the D3DDevice
// 랜더링에 사용될 D3D 디바이스
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // Our rendering device

LPDIRECT3DVERTEXBUFFER9 g_pVB        = NULL; // Buffer to hold vertices

// A structure for our custom vertex type
struct CUSTOMVERTEX
{
    FLOAT x, y, z, rhw;    // The transformed position for the vertex
    DWORD color;        // The vertex color
};

// Our custom FVF, which describes our custom vertex structure
// 사용자 정점 구조체에 관한 정보를 나타내는 FVF 값
// 구조체는 X, Y, Z, RHW 값과 Diffuse 색깔값으로 이루어져 있음을 알 수 있다.
#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; // 가장 효율적인 SWAP효과
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // 현재 바탕화면 모드에 맞춰서 후면 버퍼를 생성

    // Create the D3DDevice
 // 디바이스를 다음과 같은 설정으로 생성한다.
 // 1. 디폴트 비디오카드를 사용한다( 대부분은 비디오 카드가 한개)
 // 2. HAL 디바이스를 생성한다( HW 가속장치를 사용하겠다는 의미)
 // 3. 정점 처리는 모든 카드에서 지원하는 SW 처리로 생성한다( HW로 생성할경우 더 높은 성능을 냄)
    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()
// Desc: Creates a vertex buffer and fills it with our vertices. The vertex
//       buffer is basically just a chuck of memory that holds vertices. After
//       creating it, we must Lock()/Unlock() it to fill it. For indices, D3D
//       also uses index buffers. The special thing about vertex and index
//       buffers is that they can be created in device memory, allowing some
//       cards to process them in hardware, resulting in a dramatic
//       performance gain.
//-----------------------------------------------------------------------------
// 정점버퍼(기본적으로 정점 정보를 갖고있는 메모리 블럭 - 정점정보를 정점버퍼에 써넣어야 한다)를
// 생성하고 정점값을 채워넣는다.
// 또한 D3D는 인덱스 버퍼도 사용 가능하다는 것을 명심
// 정점버퍼나 인덱스 버퍼는 기본 시스템 메모리 외에 디바이스 메모리( 비디오카드 메모리)에
// 생성될 수 있는데, 대부분의 비디오카드에서는 이렇게 할 경우 엄청난 속도의 향상을 얻을 수 있다.
//-----------------------------------------------------------------------------
HRESULT InitVB()
{
    // Initialize three vertices for rendering a triangle
    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, }, // 색깔의 경우 0xAARRGGBB의 순서로 값을줌
        {  50.0f, 250.0f, 0.5f, 1.0f, 0xff0000ff, },
    };

    // Create the vertex buffer. Here we are allocating enough memory
    // (from the default pool) to hold all our 3 custom vertices. We also
    // specify the FVF, so the vertex buffer knows what data it contains.
 // 정점 버퍼를 생성한다.
 // * 정점 버퍼는 new나 malloc()등과 다르게 정점처리만을 위해 만들어진 특수한 메모리임.
 // 3개의 사용자 정점을 보관할 메모리를 할당한다.
 // FVF를 지정하여 보관할 데이터 형식을 지정한다.
 // FVF : 사용자가 정점의 구조를 직접 정의하여 사용할 수 있는 방식인
 // 사용자 정의 정점형식( Flexible Vertex Format )
    if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3 * sizeof(CUSTOMVERTEX),
                                                  0, D3DFVF_CUSTOMVERTEX,
                                                  D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
    {
        return E_FAIL;
    }

    // Now we fill the vertex buffer. To do this, we need to Lock() the VB to
    // gain access to the vertices. This mechanism is required becuase vertex
    // buffers may be in device memory.
 // 정점 버퍼를 값으로 채운다.
 // 정점 버퍼의 Lock() 함수를 호출하여 포인터를 얻어온다.
    VOID* pVertices;
 // 일단 생성한 정점 버퍼는 쓰레기 값으로 차있기 때문에 값을 넣어줘야한다.
 // 그러기 위해서 Lock()을 사용하여 - 실제 정점을 읽고 쓸 수 있도록 "메모리 포인터"를 얻어내야한다.
    if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
        return E_FAIL;
    memcpy( pVertices, vertices, sizeof(vertices) );
    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는 D3D인터페이스보다 나중에 생성되었다
        g_pd3dDevice->Release(); // 해제할때는 반드시 생성순서의 역순으로 해제해줘야한다.

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

 


//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
VOID Render()
{
    // Clear the backbuffer to a blue color
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );

    // Begin the scene
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
        // Draw the triangles in the vertex buffer. This is broken into a few
        // steps. We are passing the vertices down a "stream", so first we need
        // to specify the source of that stream, which is our vertex buffer. Then
        // we need to let D3D know what vertex shader to use. Full, custom vertex
        // shaders are an advanced topic, but in most cases the vertex shader is
        // just the FVF, so that D3D knows what type of vertices we are dealing
        // with. Finally, we call DrawPrimitive() which does the actual rendering
        // of our geometry (in this case, just one triangle).

        // 1. 정점 정보가 담겨 있는 정점 버퍼를 출력 스트림으로 할당한다.
  // SetStreamSource() 출력할 정점버퍼를 디바이스에 바인딩(결합)한다
  g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
  // 2. D3D에게 정점 셰이더 정보를 지정한다. 대부분의 경우에는 FVF만 지정한다  
  // SetVertexShader() 로 정점 포맷을 디바이스에 지정한다.
        g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
  // 3. 기하 정보를 출력하기 위한 DrawPrimitive() 함수 호출
  // DrawPrimitive()로 정점 버퍼의 폴리곤을 그린다.
        g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );

        // End the scene 랜더링 종료
        g_pd3dDevice->EndScene();
    }

    // Present the backbuffer contents to the display
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

 


//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
// 간단하다. WM_DESTROY의 처리도 필요없지만 최소한의 함수 모양새를 위해 남겨놓은것임.
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:
            Cleanup();
            PostQuitMessage( 0 );
            return 0;
    }

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

 


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

    // Create the application's window
    HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 02: Vertices",
                              WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                              GetDesktopWindow(), 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() 함수 호출
                    Render();
            }
        }
    }

 // 등록된 클래스 소거
    UnregisterClass( "D3D Tutorial", wc.hInstance );
    return 0;
}

*******************************

typedef struct _D3DPRESENT_PARAMETERS_
{
    UINT                BackBufferWidth;
    UINT                BackBufferHeight;
    D3DFORMAT           BackBufferFormat;
    UINT                BackBufferCount;

    D3DMULTISAMPLE_TYPE MultiSampleType;
    DWORD               MultiSampleQuality;

    D3DSWAPEFFECT       SwapEffect;
    HWND                hDeviceWindow;
    BOOL                Windowed;
    BOOL                EnableAutoDepthStencil;
    D3DFORMAT           AutoDepthStencilFormat;
    DWORD               Flags;

    /* FullScreen_RefreshRateInHz must be zero for Windowed mode */
    UINT                FullScreen_RefreshRateInHz;
    UINT                PresentationInterval;
} D3DPRESENT_PARAMETERS;

*******************************

IDirect3D9::CreateDevice Method

HRESULT CreateDevice(
    UINT Adapter,  // 디바이스를 생성할 화면의 순서번호, 모니터가 두대 이상일때 사용
    D3DDEVTYPE DeviceType, // 출력 디바이스의 종류 HAL , SW, REF.
    HWND hFocusWindow,  // 디바이스가 출력할 윈도우의 핸들, 전체화면일경우 최상위윈도우만 가능
    DWORD BehaviorFlags, // 정점셰이더지원때.. ??? 모르겠다. ㅎ
    D3DPRESENT_PARAMETERS *pPresentationParameters, // 앞에서 선언한 구조체의 포인터
    IDirect3DDevice9** ppReturnedDeviceInterface // IDirect3DDevice9의 인터페이스를 갖고있는 포인터가 담겨돌아온다.
);

*******************************

IDirect3DDevice9::CreateVertexBuffer Method

HRESULT CreateVertexBuffer(         
    UINT Length,    // 생성할 정점버퍼의 바이트 단위 크기
    DWORD Usage,    // 정점 버퍼의 종류 혹은 처리 방식(SW, HW)지정
    DWORD FVF,     // 정점 정보 구조체에 따라 선언된 FVF 플래그 값
    D3DPOOL Pool,    // 정점 버퍼가 저장될 메모리의 위치( 비디오카드, 시스템 메모리)와 관리방식 지정
    IDirect3DVertexBuffer9** ppVertexBuffer, // 반환될 정점 버퍼의 인터페이스
    HANDLE* pSharedHandle
);

*******************************

IDirect3DVertexBuffer9::Lock Method

HRESULT Lock(    
    UINT OffsetToLock,  // Lock을 할 버퍼의 시작점, SizeToLock과 함께 양쪽 모두 0이면 버퍼 전체
    UINT SizeToLock,  // Lock을 할 버퍼의 크기, OffsetToLock과 함게 양쪽 모두 0이면 버퍼 점체
    VOID **ppbData,  // 읽고 쓸 수 있게 된 메모리 영역의 포인터
    DWORD Flags   // Lock을 수행할 때 함께 사용하는 플래그
);

*******************************

IDirect3DDevice9::DrawPrimitive Method

HRESULT DrawPrimitive(   
    D3DPRIMITIVETYPE PrimitiveType, // 첫번째 전달인자에 따라 다양한 모양의 선을 그림
    UINT StartVertex,
    UINT PrimitiveCount
);

 

'- 음악과 나 - > 『 짬 통 』' 카테고리의 다른 글

Light  (0) 2006.10.07
Matrices  (0) 2006.10.07
windows tip  (0) 2006.09.13
UCC에 관하여  (0) 2006.09.07
알고리즘 강좌.  (0) 2006.06.11