System.out.println("Hello, World");

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
    /// 윈도우 클래스 등록
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, 
                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                      "D3D Tutorial", NULL };
    RegisterClassEx( &wc );

    /// 윈도우 생성
    HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 01: CreateDevice", 
                              WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                              GetDesktopWindow(), NULL, wc.hInstance, NULL );

    /// Direct3D 초기화
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    { 
        /// 윈도우 출력
        ShowWindow( hWnd, SW_SHOWDEFAULT );
        UpdateWindow( hWnd );

        /// 메시지 루프
        MSG msg; 
        while( GetMessage( &msg, NULL, 0, 0 ) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
    }

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

 


1. RegisterClassEx()로 생성하고자 하는 윈도우의 클래스를 등록한다.
2. CreateWindow()로 윈도우를 생성한다.
3. InitD3D() 함수에서 Direct3D를 초기화한다.
4. ShowWindow(), UpdateWindow()로 윈도우를 화면에 표시한다.
5. GetMessage(), TranslateMessage(), DispatchMessage()로 이루어진 메시지 루프를 수행한다.
6. 메시지 루프를 빠져나올경우 초기화한 Direct3D를 메모리에서 해제한다.
7. 프로그램을 종료한다.

대부분의 DirectX인터페이스는 초기화 시점에서 윈도우의 핸들(HWND)을 필요로 한다. 그렇기 떄문에 CreateWindow()로 윈도우를 생성한 다음 InitD3D()를 호출하고 있다. 그리고 프로그램이 종료된 다음에 생성한 Direct3D 인터페이슬ㄹ 메모리에서 해제하기 위해 메시지 루프 이후에 CelanUp() 함수를 호출 하고 있다. 이 순서 역시 상당히 중요하다. WM_CLOSE나 WM_DESTORY 등의 메시지에서 Direct3D를 해제할 경우 메시지 루프에서 문제가 생길 수 있다. 


InitD3D()함수
 * Direct3D 초기화
 *------------------------------------------------------------------------------
 */
HRESULT InitD3D( HWND hWnd )
{
    /// 디바이스를 생성하기위한 D3D객체 생성
    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;

    D3DPRESENT_PARAMETERS d3dpp;                /// 디바이스 생성을 위한 구조체
    ZeroMemory( &d3dpp, sizeof(d3dpp) );        /// 반드시 ZeroMemory()함수로 미리 구조체를 깨끗이 지워야 한다.
    d3dpp.Windowed = TRUE;                      /// 창모드로 생성
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;   /// 가장 효율적인 SWAP효과
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;    /// 현재 바탕화면 모드에 맞춰서 후면버퍼를 생성

    /// 디바이스를 다음과 같은 설정으로 생성한다.
    /// 1. 디폴트 비디오카드를 사용(대부분은 비디오카드가 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;
    }

    /// 디바이스 상태정보를 처리할경우 여기에서 한다.

    return S_OK;


그리기 함수(Render() 함수)
VOID Render()
{
    if( NULL == g_pd3dDevice )
        return;

    /// 후면버퍼를 파란색(0,0,255)으로 지운다.
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
    
    /// 렌더링 시작
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
        /// 실제 렌더링 명령들이 나열될 곳
    
        /// 렌더링 종료
        g_pd3dDevice->EndScene();
    }

    /// 후면버퍼를 보이는 화면으로!
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );

Render()함수의 알고리즘
1. 먼저 화면을 깨끗이 지운다(Clear())
2. 이제부터 폴리곤을 그리겠다고 D3D에게 알린다.(BeginScene())
3. 폴리곤을 다 그렸다고 D3D에게 알린다.(EndScene())
4. 화면에 나타나게 한다.(Present())

-인터페이스를 메모리에서 해제하기
VOID Cleanup()
{
    if( g_pd3dDevice != NULL) 
        g_pd3dDevice->Release();

    if( g_pD3D != NULL)
        g_pD3D->Release();
}
디바이스(g_pd3dDevice)는 D3D 인터페이스보다 나중에 생성되었다. 해제할때는 반드시 생성 순서의 역순으로 해제해줘야 한다. 그것만 주의하면 된다.

<생성화면>
 


Posted by 김마농