일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 운영체제
- vector
- 아두이노
- 아두이노 컴파일러
- set
- C언어
- 라인트레이서
- map
- stl
- 자료구조
- c++
- 시스템프로그래밍
- Array
- 컴퓨터 그래픽스
- Arduino
- directx
- 아두이노 소스
- Algorithm
- priority_queue
- WinAPI
- LineTracer
- arduino compiler
- html
- list
- Deque
- 통계학
- Stack
- 수광 소자
- queue
- Visual Micro
- Today
- Total
Kim's Programming
[다이렉트SDK 예제]DirectX Tutorial1 - CreateDevice 본문
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | //----------------------------------------------------------------------------- // File: CreateDevice.cpp // // Desc: This is the first tutorial for using Direct3D. In this tutorial, all // we are doing is creating a Direct3D device and using it to clear the // window. // // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #include <d3d9.h> #pragma warning( disable : 4996 ) // disable deprecated warning #include <strsafe.h> #pragma warning( default : 4996 ) //----------------------------------------------------------------------------- // Global variables //----------------------------------------------------------------------------- LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device //----------------------------------------------------------------------------- // Name: InitD3D() // Desc: Initializes Direct3D //----------------------------------------------------------------------------- HRESULT InitD3D( HWND hWnd ) { // Create the D3D object, which is needed to create the D3DDevice. if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; // Set up the structure used to create the D3DDevice. Most parameters are // zeroed out. We set Windowed to TRUE, since we want to do D3D in a // window, and then set the SwapEffect to "discard", which is the most // efficient method of presenting the back buffer to the display. And // we request a back buffer format that matches the current desktop display // format. D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof( d3dpp ) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // Create the Direct3D device. Here we are using the default adapter (most // systems only have one, unless they have multiple graphics hardware cards // installed) and requesting the HAL (which is saying we want the hardware // device rather than a software one). Software vertex processing is // specified since we know it will work on all cards. On cards that support // hardware vertex processing, though, we would see a big performance gain // by specifying hardware vertex processing. 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: Cleanup() // Desc: Releases all previously initialized objects //----------------------------------------------------------------------------- VOID Cleanup() { if( g_pd3dDevice != NULL ) g_pd3dDevice->Release(); if( g_pD3D != NULL ) g_pD3D->Release(); } //----------------------------------------------------------------------------- // Name: Render() // Desc: Draws the scene //----------------------------------------------------------------------------- VOID Render() { if( NULL == g_pd3dDevice ) return; // 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() ) ) { // Rendering of scene objects can happen here // 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 //----------------------------------------------------------------------------- LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch( msg ) { case WM_DESTROY: Cleanup(); PostQuitMessage( 0 ); return 0; case WM_PAINT: Render(); ValidateRect( hWnd, NULL ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); } //----------------------------------------------------------------------------- // Name: wWinMain() // Desc: The application's entry point //----------------------------------------------------------------------------- INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT ) { UNREFERENCED_PARAMETER( hInst ); // 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 01: CreateDevice", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wc.hInstance, NULL ); // Initialize Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ) { // Show the window ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); // Enter the message loop MSG msg; while( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } } UnregisterClass( L"D3D Tutorial", wc.hInstance ); return 0; } | cs |
- 전역변수
1 2 3 4 5 | //----------------------------------------------------------------------------- // Global variables //----------------------------------------------------------------------------- LPDIRECT3D9 g_pD3D = NULL; // Used to create the D3DDevice LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // Our rendering device | cs |
다이렉트X는 그래픽 카드를 이용합니다. 그렇기 때문에 그래픽 카드에 접근할 무언가가 필요하게 되는데요. 바로 그때 이용하는 것이 LPDIRECT3DEVICE9 구조체입니다. LPDIRECT3DEVICE9의 정의를 직접 따라 들어가다 보면 앞에 LP가 붙은거 처럼 포인터를 이용한다는 것을 알 수 있게 되는데 이 이유는 그래픽카드는 컴퓨터에 하나만 존재하지 않을 수도 있기 떄문입니다. 여전히 지금도 그래픽카드는 컴퓨터 1대당 1대가 달려있는게 일반적인데(내장1개 외장 1개 라서 2개인 개념이 아닙니다. Nvidia의 SLI 나 Radeon사의 CrossFire 같은 걸 의미합니다) 꼭 1대만 들어있지는 않기 때문에 포인터를 이용하여 접근하게됩니다. 그 위에 있는 LPDIRECT3D9는 다이렉트X용 구조체를 생성하며 역시나 포인터를 이용합니다.
- InitD3D(HWND hWnd)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | //----------------------------------------------------------------------------- // Name: InitD3D() // Desc: Initializes Direct3D //----------------------------------------------------------------------------- HRESULT InitD3D( HWND hWnd ) { // Create the D3D object, which is needed to create the D3DDevice. if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; // Set up the structure used to create the D3DDevice. Most parameters are // zeroed out. We set Windowed to TRUE, since we want to do D3D in a // window, and then set the SwapEffect to "discard", which is the most // efficient method of presenting the back buffer to the display. And // we request a back buffer format that matches the current desktop display // format. D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof( d3dpp ) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // Create the Direct3D device. Here we are using the default adapter (most // systems only have one, unless they have multiple graphics hardware cards // installed) and requesting the HAL (which is saying we want the hardware // device rather than a software one). Software vertex processing is // specified since we know it will work on all cards. On cards that support // hardware vertex processing, though, we would see a big performance gain // by specifying hardware vertex processing. 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; } | cs |
다이렉트 X를 초기화 해주는 부분입니다. 다이렉트 X는 사용하기 전에 DirectX SDK중에서 몇 버전을 쓰는지 명시되어야 합니다. 첫 조건문은 다이렉트 구조체가 몇 버전인지 명시해주는 역할을 합니다. 다음의 D3DPRESENT_PARAMETERS 구조체는 위에 있었던 LPDIRECT3DEVICE9로 만든 객체에 들어갈 파라메터들이 있는 구조체입니다. 그냥 직접 대입하지 않고 이를 이용하여 대입해주기 위해 만들어져있는 존재합니다. ZeroMemoey를 통하여 초기화를 해주며 Windowed, SwapEffect, BackBufferFormat 에 대하여 조건을 주었습니다. D3DPRESENT_PARAMETERS구조체는 다음과 같이 이루어져 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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; | cs |
원하는 부분에 대해서 지정해주면 됩니다. 현재 이 예제에서는 Windowed에 TRUE를 주어 윈도우 창이 뜰 수 있도록 하고 SwapEffect를 discard(즉 포기)하겠다고 하였으며 BackBufferFormat 백 버퍼의 포멧은 현재 데스크톱에 맞추기 위해여 D3DFMT_UNKNOWN(지정 되지 않았으니 알아서 찾아라 라는 뜻)을 주었습니다.
다음은 DirectX 구조체를 생성했으니 DirectX장치(즉 그래픽 카드)를 생성할 차례입니다. CreateDevice를 이용하여 그래픽 카드를 생성해주게 됩니다. 다중 그래픽 카드가 설치 되어 있지 않는 한은 대부분 그래픽 카드를 하나를 가지고 있기 떄무넹 기본 어댑터를 이용합니다. 그리고 그런 상황을 HAL(Hardware Abstraction Layer)에 요청합니다. 이러한 것들을 하는 과정이 마지막에 있는 조건문의 내용입니다.
Init3D함수에서는 E_FAIL, S_OK, FAILED 등이 보이는데 이는 FAILED함수를 이용할 떄 E_FAILED를 리턴받으면 오류가 생겼다 이런식으로 오류를 판별하기 위해서 작성해둔 함수와 변수입니다. 직접 정의로 이동하면
1 2 3 4 5 6 7 8 | // // MessageId: E_FAIL // // MessageText: // // Unspecified error // #define E_FAIL _HRESULT_TYPEDEF_(0x80004005L) | cs |
다음과 같이 정의되어 있음을 확인 할 수 있습니다.
- Cleanup()
1 2 3 4 5 6 7 8 9 10 11 12 | //----------------------------------------------------------------------------- // Name: Cleanup() // Desc: Releases all previously initialized objects //----------------------------------------------------------------------------- VOID Cleanup() { if( g_pd3dDevice != NULL ) g_pd3dDevice->Release(); if( g_pD3D != NULL ) g_pD3D->Release(); } | cs |
Cleanup()함수는 만들었던 포인터들을 정리해주는 함수입니다. C언어에서 동적할당으로 만든변수를 끝에가서 동적해제를 해주듯이 DirectX에서도 할당한 변수들을 해제하게됩니다.
- Render()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | VOID Render() { if( NULL == g_pd3dDevice ) return; // 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() ) ) { // Rendering of scene objects can happen here // End the scene g_pd3dDevice->EndScene(); } // Present the backbuffer contents to the display g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } | cs |
Render()함수는 화면을 매 프레임마다 그려주는 함수입니다. 첫 초건문에 g_pd3dDevice가 NULL인지 확인하여 그래픽카드가 생성되었는지(여기서는 InitD3D에서 생성함) 확인을 하는 과정입니다. 그 다음중에서는 g_pd3dDevice의 Clear함수를 통해서 BackBuffer를 파란색으로 초기화 합니다. 다음 조건문부터 그 조건문 안에 있는 EndScene()까지에는 렌더링 할 내용을 넣어주면 됩니다. 마지막 중에 있는 Present를 이용하여 백 버퍼의 내용을 출력하게됩니다.
- MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | //----------------------------------------------------------------------------- // Name: MsgProc() // Desc: The window's message handler //----------------------------------------------------------------------------- LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch( msg ) { case WM_DESTROY: Cleanup(); PostQuitMessage( 0 ); return 0; case WM_PAINT: Render(); ValidateRect( hWnd, NULL ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); } | cs |
윈도우즈는 메세지 시스템으로 돌아 갑니다. 그 부분을 처리해주는 함수입니다.
- wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | //----------------------------------------------------------------------------- // Name: wWinMain() // Desc: The application's entry point //----------------------------------------------------------------------------- INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT ) { UNREFERENCED_PARAMETER( hInst ); // 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 01: CreateDevice", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wc.hInstance, NULL ); // Initialize Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ) { // Show the window ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); // Enter the message loop MSG msg; while( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } } UnregisterClass( L"D3D Tutorial", wc.hInstance ); return 0; } | cs |
wWinMain함수는 윈도우 프로그래밍에서 C언어의 main함수와 같은 역할을 하며 기본적인 윈도우를 생성하고 제목 등등을 설정합니다.
위의 긴 녀석들 전체의 결과는 황당하게도 다음과 같습니다.
지금까지의 과정은 단순히 DirectX 창 하나를 만들기 위해서 이렇게 길게 만들었지만. 다음 예제부터 본격적으로 활용하게됩니다.
'Programming > DirectX' 카테고리의 다른 글
[다이렉트SDK 예제]DirectX Tutorial4 - Lighting (0) | 2016.04.15 |
---|---|
[다이렉트SDK 예제]DirectX Tutorial3 - Matrices (0) | 2016.04.15 |
[다이렉트SDK 예제]DirectX Tutorial2 - Vertices (0) | 2016.04.15 |
다이렉트 X 예제 알아보기 - DirectX Sample Browser (0) | 2016.04.14 |
DirectX SDK(Software Development Kit)설치 (0) | 2016.03.05 |