본문 바로가기
Lib/DirectX

Direct3D 초기화를 위한 예제 준비 (구현)

by KingCat 2011. 11. 9.
#include "d3dUtility.h"

// Direct3D 초기화 메서드
bool d3d::InitD3D(
	HINSTANCE hInstance,
	int width, int height,
	bool windowed,
	D3DDEVTYPE deviceType,
	IDirect3DDevice9** device)
{
	// 메인 애플리케이션 생성

	WNDCLASS wc;

	wc.style         = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc   = (WNDPROC)d3d::WndProc; 
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = hInstance;
	wc.hIcon         = LoadIcon(0, IDI_APPLICATION);
	wc.hCursor       = LoadCursor(0, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName  = 0;
	wc.lpszClassName = "Direct3D9App";

	if( !RegisterClass(&wc) ) 
	{
		::MessageBox(0, "RegisterClass() - FAILED", 0, 0);
		return false;
	}
		
	HWND hwnd = 0;
	hwnd = ::CreateWindow("Direct3D9App", "Direct3D9App", 
		WS_EX_TOPMOST,
		0, 0, width, height,
		0 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/); 

	if( !hwnd )
	{
		::MessageBox(0, "CreateWindow() - FAILED", 0, 0);
		return false;
	}

	::ShowWindow(hwnd, SW_SHOW);
	::UpdateWindow(hwnd);

	//
	// Direct3D 초기화하기 
	//

	HRESULT hr = 0;

	// 1. IDirect3D9 인터페이스를 얻는다.
	// Direct3DCreate9의 단일인자에는 항상 D3D_SDK_VERSION을 전달해야 한다.
	// 애플리케이션이 올바른 헤더 파일로 만들어졌음을 확인하기 위한 것으로 함수 실패시 null 포인터 리턴.
	// IDirect3D9 객체는 장치 검증과 IDirect3DDevice9 객체 생성의 두 가지 용도로 이용됨.
	// 장치 검증이란 기능, 디스플레이 모드, 포맷 등과 같은 시스템의 그래픽 장치가 제공하는 특성 정보를 얻는 과정
	
	IDirect3D9* d3d9 = 0;
    d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

    if( !d3d9 )
	{
		::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
		return false;
	}

	// 2. 하드웨어 버텍스 프로세싱 확인하기
	// 기본 디스플레이 어댑터와 대응되는 IDirect3DDevice9 객체를 생성할 때는 반드시 원하는 버텍스 프로세싱
	// 모드를 지정해야 한다. 이때, 모든 카드가 하드웨어 버텍스 프로세싱을 이용하는지 보장할 수 없으므로 
	// 지원 여부를 확인해야 한다.

	// 어댑터의 특성에 따라 D3DCAPS9 인스턴스를 초기화한다.
	D3DCAPS9 caps;
	// 첫번째 인자 : 특성을 얻고자 하는 물리 디스플레이 어댑터 지정.
	// 두번째 인자 : 이용할 장치 타입을 지정 (하드웨어 장치(D3DDEVTYPE_HAL), 소프트웨어 장치(D3DDEVTYPE_REF))
	// 세번째 인자 : 초기화된 특성 구조체를 리턴.
	d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, &caps);

	// 이후에 IDirect3DDevice9 객체를 만들 때 버텍스 프로세싱의 타입을 지정하기 위해 저장할 곳 : vp
	int vp = 0;
	// 하드웨어 버텍스 프로세싱을 이용할 수 있는지 확인
	if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
		// 지원될 경우 vp에 하드웨어 버텍스 프로세싱을 저장
		vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
	else
		// 지원 안 될 경우 vp에 소프트웨어 버텍스 프로세싱을 저장
		vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

	// 3. D3DPRESENT_PARAMETERS 구조체 채우기
	// D3DPRESENT_PARAMETERS 구조체를 만들고자 하는 IDirect3DDevice9 객체의 성격을 결정하는데 사용
 
	D3DPRESENT_PARAMETERS d3dpp;
	// 픽셀 단위의 후면 버퍼 너비
	d3dpp.BackBufferWidth            = width;
	// 픽셀 단위의 후면 버퍼 높이
	d3dpp.BackBufferHeight           = height;
	// 후면 버퍼의 픽셀 포맷 (D3DFMT_A8R8G8B8은 32-비트 픽셀 포맷)
	d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
	// 이용할 후면 버퍼의 수. 보통 1을 지정하고 한개의 후면 버퍼를 이용한다.
	d3dpp.BackBufferCount            = 1;
	// 후면 버퍼에 이용할 멀티 샘플링의 타입 (SDK 참조)
	d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
	// 멀티 샘플링의 레빌 (SDK 참조)
	d3dpp.MultiSampleQuality         = 0;
	// 플리핑 체인의 버퍼가 교환되는 방법을 지정하는 D3DSWAPEFFECT 열거형 멤버.
	// D3DSWAPEFFECT_DISCARD가 가장 효과적이다.
	d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; 
	// 서비스와 연결된 윈도우 핸들. 드로잉 대상이 될 애플리케이션 윈도우를 지정한다.
	d3dpp.hDeviceWindow              = hwnd;
	// 윈도우 모드로 실행중일 때는 true, 전체화면 모드로 실행중일 때는 false를 지정
	d3dpp.Windowed                   = false;
	// Direct3D가 자동으로 깊이/스텐실 버퍼를 만들고 관리하길 원한다면 true
	d3dpp.EnableAutoDepthStencil     = true; 
	// 깊이/스텐실 버퍼의 포맷 (24버티 깊이 버퍼와 스텐실 버퍼로 8 비트 예약 : D3DFMT_D24S8)
	d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
	// 몇 가지 부가적인 특성들. 0(플래그 없음), SDK 참조
	d3dpp.Flags                      = 0;
	// 재생율을 지정 (디폴트 : D3DPRESENT_RATE_DEFAULT)
	d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
	// D3DPRESENT 집합의 멤버. 전체 간격 리스트는 SDK 참조
	// 즉시 시연 (D3DPRESENT_INTERVAL_IMMEDIATE)
	// 적절한 시연 간격을 Direct3D가 결정 (D3DPRESENT_INTERVAL_DEFAULT)
	d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;

	// 4. IDirect3DDevice9 인터페이스 만들기

	// 첫번째 인자 : 만들어질 IDirect3DDevice9 객체와 대응될 물리 디스플레이 어댑터 지정
	// 두번째 인자 : 이용할 장치 타입 (D3DDEVTYPE_HAL or D3DDEVTYPE_REF)
	// 세번째 인자 : 장치와 연결될 윈도우 핸들
	// 네번째 인자 : 지원하는 버텍스 프로세싱
	// 다섯번째 인자 : 장치 특성의 일부를 정의하는 초기화된 D3DPRESENT_PARAMETERS 인스턴스를 지정
	// 여섯번째 인자 : 생성된 장치를 리턴
	hr = d3d9->CreateDevice(
		D3DADAPTER_DEFAULT, // primary adapter
		deviceType,         // device type
		hwnd,               // window associated with device
		vp,                 // vertex processing
	    &d3dpp,             // present parameters
	    device);            // return created device

	if( FAILED(hr) )
	{
		// try again using a 16-bit depth buffer
		d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
		
		hr = d3d9->CreateDevice(
			D3DADAPTER_DEFAULT,
			deviceType,
			hwnd,
			vp,
			&d3dpp,
			device);

		if( FAILED(hr) )
		{
			d3d9->Release(); // done with d3d9 object
			::MessageBox(0, "CreateDevice() - FAILED", 0, 0);
			return false;
		}
	}

	d3d9->Release(); // done with d3d9 object
	
	return true;
}

// Display 함수가 될 함수의 포인터를 받아서, 메시지 루프 함수가 유휴 상태에서 디스플레이 함수를 호출.
int d3d::EnterMsgLoop(bool (*ptr_display)(float timeDelta))
{
	MSG msg;
	::ZeroMemory(&msg, sizeof(MSG));
	static float lastTime = (float)timeGetTime();

	while(msg.message != WM_QUIT)
	{
		if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
		{
			::TranslateMessage(&msg);
			::DispatchMessageA(&msg);
		}
		else
		{
			float currTime=(float)timeGetTime();
			float timeDelta = (currTime-lastTime)*0.001f;
			ptr_display(timeDelta);
			lastTime = currTime;
		}
	}
	return msg.wParam;
}

'Lib > DirectX' 카테고리의 다른 글

DirectX 내부에서의 텍스쳐 합성  (0) 2013.12.11
회전하는 입방체 만들기  (0) 2011.11.09
Triangle 그리기  (0) 2011.11.09
DirectX 기본 코드 구조.  (0) 2011.11.09
Direct3D 초기화를 위한 예제 준비 (헤더)  (0) 2011.11.09