[DirectX] DirectX 초기화 하기!!

 이제 셋팅과 랜더링 파이프라인에 대하여 알았다면, 실제 코딩을 해보도록 하자.. (혹시 예전 포스팅이 궁금하다면 아래 링크로) 

다이렉트x sdk 설치
다이렉트x 랜더링 파이프라인

 기본적으로 먼저 알고 시작해야 할 것은 directx 를 초기화 하기 위해서는 D3D객체와 D3Ddevice 객체가 필요하다.

 이 객체들의 역할은 하드웨어와의 통신이라고 생각하면된다. 즉, 하드웨어에 접근할 매개체라고 보면 된다.

 그리고 D3D객체를 생성, 그 D3D 객체로 디바이스 까지 생성한 후에 랜더링을 계속 화면 화면에 우리가 원하는 화면을 그리게 된다. 그리고 이 선언된 것들을 프로그램을 종료할 때에는 꼭 해제를 해주어야한다.

 랜더링을 하려면 아래와 같은 부분이 필요하다.

 g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
  D3DCOLOR_COLORVALUE(0.0f,1.0f,0.0f,1.0f), 1.0f, 0 );

 g_pd3dDevice->BeginScene();

 // Render geometry here...

 g_pd3dDevice->EndScene();

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

모든 함수들을 보면 알수 있듯이 모두 Device를 통하여 동작을 한다. (지금은 전역으로 선언되었지만, 따로 클래스로 만들어서 쓸수도 있으므로, 그 것은 개인적으로 쓸모에 따라 쓰면된다. ) 

 그리고 랜더링을 하기 위해서는 실시간으로 루프를 돌면서 계속 저 부분을 불러줘야 하는데, 그렇게 해야 계속 화면을 갱신해 우리가 원하는 화면이 된다. 

 각 부분의 역할들을 보면 먼저 Clear 라는 함수로 초기화를 한다. 

 그리고 BeginScene을 쓰고 EndScene을 쓰는데 이 사이에 있는 것들만 그려지게 된다. 그리고 Present를 부르면 이제 실제로 화면에 찍는 것이다. 

 현재로서는 매우 간단해 보이지만, 이 곳에 다른 함수들이 들어가고 다른 효과들을 넣고 하다보면 매우 복잡해 진다. 

 그럼 실제로 프로젝트를 만들면서 확인해보자.
 지금 가져오는 소스는 튜토리얼 용으로 만들어진 프로젝트에서 필요한 부분만 가져와서 사용했다. (사진이 잘 안보여도, 사용된 소스는 다 붙여놓았기 때문에 대충 이 위치쯤 감만 잡을 수 있다면 별 상관은 없을 것이다.)


 먼저 새로운 프로젝트를 생성한다. 현재 2005 버전으로 하지만 2008이나 2010도 거의 비슷하다. Win32프로젝트를 선택하고 확인을 누른다.


그러면 이런 화면이 나오게 되는데 다음으로 넘어가고,

 윈도우즈 응용프로그램이 선택된 체로 마침을 누른다.


그러면 아래와 같이 소스가 자동으로 생성된다.

그리고 컴파일하면 위와 같은 화면이 뜬다. 이제 조금씩 수정을 해 나가면되는데..


먼저 헤더파일을 추가한다.
#include <d3d9.h>
#include <d3dx9.h>


그리고 속성에서 링커->일반->추가 종속성에..

d3dx9.lib d3d9.lib 2개를 추가한다.


그리고 이제 전역 변수를 추가한다. 전역 변수들은..
HWND              g_hWnd       = NULL;
LPDIRECT3D9       g_pD3D       = NULL;
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;

이 3가지를 추가한다.


그리고 이제 다이렉트용 함수 3개를 추가하는데 각각

void init();
void shutDown();
void render();

이 것으로 init은 초기화를 shutDown은 해제를 그리고 화면을 그리는 것은 render 함수에 작성한다.

아래의 부분이 초기화 용 함수의 모든 내용이다.
void init(  )
{
    g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );

 if( g_pD3D == NULL )
 {
  // TO DO: Respond to failure of Direct3DCreate8
  return;
 }
    D3DDISPLAYMODE d3ddm;

    if( FAILED( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
 {
  // TO DO: Respond to failure of GetAdapterDisplayMode
  return;
 }

 HRESULT hr;

 if( FAILED( hr = g_pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
            d3ddm.Format, D3DUSAGE_DEPTHSTENCIL,
            D3DRTYPE_SURFACE, D3DFMT_D16 ) ) )
 {
  if( hr == D3DERR_NOTAVAILABLE )
   // POTENTIAL PROBLEM: We need at least a 16-bit z-buffer!
   return;
 }

 //
 // Do we support hardware vertex processing? if so, use it.
 // If not, downgrade to software.
 //

 D3DCAPS9 d3dCaps;

 if( FAILED( g_pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT,
                                 D3DDEVTYPE_HAL, &d3dCaps ) ) )
 {
  // TO DO: Respond to failure of GetDeviceCaps
  return;
 }

 DWORD dwBehaviorFlags = 0;

 if( d3dCaps.VertexProcessingCaps != 0 )
  dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
 else
  dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;

 //
 // Everything checks out - create a simple, windowed device.
 //

 D3DPRESENT_PARAMETERS d3dpp;
 memset(&d3dpp, 0, sizeof(d3dpp));

    d3dpp.BackBufferFormat       = d3ddm.Format;
 d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;
 d3dpp.Windowed               = TRUE;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_IMMEDIATE;

    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
                                      dwBehaviorFlags, &d3dpp, &g_pd3dDevice ) ) )
 {
  // TO DO: Respond to failure of CreateDevice
  return;
 }
}

내용을 위에서 부터 보면, d3d를 설정하고, 디스플레이 모드를 가져온 후 여러가지 셋팅을 한 후에 device를 생성한다.
 여기서 눈여겨 볼 것은 바로

g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd,
                                      dwBehaviorFlags, &d3dpp, &g_pd3dDevice )

 이 CreateDevice 부분이다. 이 곳을 보면 g_hWnd 변수를 넣어주는데 다이렉트 엑스 화면을 그려줄 윈도우 핸들값이다. 잘 생각해보면 다이렉트x를 어떤 화면에 그리고 싶다면 그 것을 설정해 주는 부분이 필요한데 이 부분이 바로 그 부분이다. 그러면 저기 핸들값을 얻으로 가보자.

 


 위의 사진은 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 부분이다. 이 함수를 찾아가보면 실제 윈도우 생성을 하고 있다. 그 곳에서..



핸들 값을 받아오면된다. 아까 init 함수 내부에 이미 처리 함수가 다 적혀있으니, 그냥 핸들 값만 받으면 설정은 끝났다. 이제 루프 부분을 수정할 차례이다.
winmain() 함수에 가보면 기본 루프가 아래와 같이 있다.


이 부분을... 아래 화면처럼..


 memset(&msg,0,sizeof(msg));
 while( msg.message != WM_QUIT )
 {
  if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
  {
   TranslateMessage( &msg );
   DispatchMessage( &msg );
  }
  else
   render();
 }

이렇게 고치면된다. 위의 memset 하는 이유는 msg 값을 초기화 하기 위해서고 WM_QUIT 메세지를 받기 전까지는 while을 계속 돌게된다. 그리고 PeekMessage로 윈도우 메세지를 받는 경우 말고는 계속 render를 돌게 된다.
그 render 함수의 내용은 아까 위에 예를 든 것처럼...

void render( )
{
 g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
  D3DCOLOR_COLORVALUE(0.0f,1.0f,0.0f,1.0f), 1.0f, 0 );

 g_pd3dDevice->BeginScene();

 // Render geometry here...

 g_pd3dDevice->EndScene();

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

 이렇게 만들면되고 저기 랜더 지오메트리 부분에 이제 앞으로 내용이 추가될 것이다.


그럼 이제 초기화 부분을 루프 이전에 추가해주고..


그 루프 아래 부분에는..

shutDown(); 함수를 추가해준다. 그 내용은 아래와 같다.

void shutDown( )
{
 if( g_pd3dDevice != NULL )
  g_pd3dDevice->Release();

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

이 모든 것들을 다 하고 난 후에 컴파일을 하면,


아까의 흰 윈도우 밖에 없던 화면이 쨘~ 녹색 화면이 나오고 있다.

위의 화면은 현재 다이렉트x가 그려지고 있는 화면이다.

화면 색이 녹색인 이유는 아까 render 함수에 Clear 부분에 바탕색이 현재 rgb중 g만 1.0f 수치가 되어있기 때문이다.

 각자 한번씩 바꿔보면 바로 적용이 되는 것을 알게 될 것이다.

 자, 이제 초기화를 했으니 간단한 도형 부터 차례대로 띄워보도록 하자.~

 [DirectX] DirectX 초기화 하기!!
Posted by 바람처럼..
|