#1. Engine System
+ WinMain - EngineSystem
+ EngineCore
+ EngineError
+ MainNode
#2. FrameWork
+ Grahpics (현재 글)
+ Image - SpriteData
+ Layer
+ Input
+ Game
+ Manager
+ Game Interface
+ Utility
#3. Testing Module
+ 2D Image Test
+ 2D Animation Test
+ Game UI Test
-----------------------------------------------------------------------
이번 글에서는 Graphics 클래스의 cpp 파일을 확인하도록 하겠습니다.
먼저 헤더 내용을 정리하며 가리켰던 3가지 항목
A. struct VertexC
B. struct SpriteData
C. Class Graphics
를 다시 상기해볼 필요가 있습니다.
A. VertexC에 대해서 간략히 다시 설명하자면
앞으로 사용 할 모든 이미지들은 x,y 좌표가 필요한데, DirectX 상에서는 3D 좌표를 이용하므로
z 축 좌표가 하나 더 필요합니다.
그러나 여기서 다룰 2D 게임을 위한 엔진에서는 z 축은 사실 상 필요가 없습니다.
따라서 z 축 자체는 0 값으로 모두 보존됩니다.
B. SpriteData 구조체는 모든 이미지를 사용함에 있어 그 데이터를 가지고 있습니다.
출력할 스크린 상의 x, y 좌표, 텍스쳐(이미지) 정보, 텍스쳐에서 어떤 부분을 사용할 것인지 RECT 값 등.
Graphics 클래스에서는 이 SpriteData 구조체를 주소 값 형식( * 가 아닌 & 연산자)으로 받아옴으로 원하고자 하는 SpriteData 정보를 이용하여 이미지를 출력합니다.
C. Graphics Class의 .cpp 내용을 지금 부터 확인해보겠습니다.
1. 생성자 ( Constructor )와 소멸자
생성자 구역은 헤더에서 선언한 주요 Graphics 클래스의 멤버들을 초기화합니다.
별 다른 특별한 내용은 없습니다.
#include "stdafx.h" | |
#include "graphics.h" | |
//============================================================================= | |
// Constructor | |
//============================================================================= | |
Graphics::Graphics() | |
{ | |
direct3d = NULL; | |
device3d = NULL; | |
sprite = NULL; | |
fullscreen = false; | |
stencilSupport = false; | |
width = GAME_WIDTH; // width & height are replaced in initialize() | |
height = GAME_HEIGHT; | |
backColor = graphicsNS::BACK_COLOR; | |
pOcclusionQuery = NULL; | |
numberOfPixelsColliding = 0; | |
line = NULL; | |
} | |
//============================================================================= | |
// Destructor | |
//============================================================================= | |
Graphics::~Graphics() | |
{ | |
releaseAll(); | |
} |
소멸자는 releaseAll 함수를 호출하여 연결되어있던 내용들을 해지합니다.
//============================================================================= | |
// Release all | |
//============================================================================= | |
void Graphics::releaseAll() | |
{ | |
safeRelease(pOcclusionQuery); | |
safeRelease(sprite); | |
safeRelease(device3d); | |
safeRelease(direct3d); | |
safeRelease(line); | |
} |
releaseAll( ) 에서 사용한 safeRelease( ) 함수는 템플릿 형태로 미리 만들어 둔 매크로 입니다.
/============================================================================= | |
// Function templates for safely dealing with pointer referenced items. | |
// The functions defined by these templates may be called using a normal | |
// function call syntax. The compiler will create a function that replaces T | |
// with the type of the calling parameter. | |
//============================================================================= | |
// Safely release pointer referenced item | |
template <typename T> | |
inline void safeRelease(T& ptr) | |
{ | |
if (ptr) | |
{ | |
ptr->Release(); | |
ptr = NULL; | |
} | |
} | |
#define SAFE_RELEASE safeRelease // for backward compatiblility | |
// Safely delete pointer referenced item | |
template <typename T> | |
inline void safeDelete(T& ptr) | |
{ | |
if (ptr) | |
{ | |
delete ptr; | |
ptr = NULL; | |
} | |
} | |
#define SAFE_DELETE safeDelete // for backward compatiblility | |
// Safely delete pointer referenced array | |
template <typename T> | |
inline void safeDeleteArray(T& ptr) | |
{ | |
if (ptr) | |
{ | |
delete[] ptr; | |
ptr = NULL; | |
} | |
} | |
#define SAFE_DELETE_ARRAY safeDeleteArray // for backward compatiblility | |
// Safely call onLostDevice | |
template <typename T> | |
inline void safeOnLostDevice(T& ptr) | |
{ | |
if (ptr) | |
ptr->onLostDevice(); | |
} | |
#define SAFE_ON_LOST_DEVICE safeOnLostDevice // for backward compatiblility | |
// Safely call onResetDevice | |
template <typename T> | |
inline void safeOnResetDevice(T& ptr) | |
{ | |
if (ptr) | |
ptr->onResetDevice(); | |
} | |
#define SAFE_ON_RESET_DEVICE safeOnResetDevice // for backward compatiblility |
2. Initialize
이어서 Graphics Class의 시작인 initialize( )를 살펴보겠습니다.
initialize 의미 자체대로 모든 초기화에 대한 진행을 이곳에서 합니다.
//============================================================================= | |
// Initialize DirectX graphics | |
// throws GameError on error | |
//============================================================================= | |
void Graphics::initialize(HWND hw, int w, int h, bool full) | |
{ | |
hwnd = hw; | |
width = w; | |
height = h; | |
fullscreen = full; | |
//initialize Direct3D | |
direct3d = Direct3DCreate9(D3D_SDK_VERSION); | |
if (direct3d == NULL) | |
throw(GameError(gameErrorNS::FATAL_ERROR, "Error initializing Direct3D")); | |
initD3Dpp(); // init D3D presentation parameters | |
if(fullscreen) // if full-screen mode | |
{ | |
if(isAdapterCompatible()) // is the adapter compatible | |
// set the refresh rate with a compatible one | |
d3dpp.FullScreen_RefreshRateInHz = pMode.RefreshRate; | |
else | |
throw(GameError(gameErrorNS::FATAL_ERROR, | |
"The graphics device does not support the specified resolution and/or format.")); | |
} | |
// determine if graphics card supports harware texturing and lighting and vertex shaders | |
D3DCAPS9 caps; | |
DWORD behavior; | |
result = direct3d->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); | |
// If device doesn't support HW T&L or doesn't support 1.1 vertex | |
// shaders in hardware, then switch to software vertex processing. | |
if( (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 || | |
caps.VertexShaderVersion < D3DVS_VERSION(1,1) ) | |
behavior = D3DCREATE_SOFTWARE_VERTEXPROCESSING; // use software only processing | |
else | |
behavior = D3DCREATE_HARDWARE_VERTEXPROCESSING; // use hardware only processing | |
//create Direct3D device | |
result = direct3d->CreateDevice( | |
D3DADAPTER_DEFAULT, | |
D3DDEVTYPE_HAL, | |
hwnd, | |
behavior, | |
&d3dpp, | |
&device3d); | |
if (FAILED(result)) | |
throw(GameError(gameErrorNS::FATAL_ERROR, "Error creating Direct3D device")); | |
result = D3DXCreateSprite(device3d, &sprite); | |
if (FAILED(result)) | |
throw(GameError(gameErrorNS::FATAL_ERROR, "Error creating Direct3D sprite")); | |
// Configure for alpha blend of primitives | |
device3d->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); | |
device3d->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); | |
device3d->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); | |
// Check if the device supports 8-bit stencil buffering. | |
if( FAILED( direct3d->CheckDeviceFormat(caps.AdapterOrdinal, | |
caps.DeviceType, | |
d3dpp.BackBufferFormat, | |
D3DUSAGE_DEPTHSTENCIL, | |
D3DRTYPE_SURFACE, | |
D3DFMT_D24S8 ) ) ) | |
stencilSupport = false; | |
else | |
stencilSupport = true; | |
// Create query object, used for pixel perfect collision detection | |
device3d->CreateQuery(D3DQUERYTYPE_OCCLUSION, &pOcclusionQuery); | |
createLine(&line); // create a DirectX line | |
} | |
/============================================================================= | |
// Initialize D3D presentation parameters | |
//============================================================================= | |
void Graphics::initD3Dpp() | |
{ | |
try{ | |
ZeroMemory(&d3dpp, sizeof(d3dpp)); // fill the structure with 0 | |
// fill in the parameters we need | |
d3dpp.BackBufferWidth = width; | |
d3dpp.BackBufferHeight = height; | |
if(fullscreen) // if fullscreen | |
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; // 24 bit color | |
else | |
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // use desktop setting | |
d3dpp.BackBufferCount = 1; | |
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; | |
d3dpp.hDeviceWindow = hwnd; | |
d3dpp.Windowed = (!fullscreen); | |
if(VSYNC) // if vertical sync is enabled | |
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; | |
else | |
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; | |
d3dpp.EnableAutoDepthStencil = true; | |
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; // Depth 24, Stencil 8 | |
} catch(...) | |
{ | |
throw(GameError(gameErrorNS::FATAL_ERROR, | |
"Error initializing D3D presentation parameters")); | |
} | |
} |
주요 내용을 천천히 살펴보면 먼저 파라미터
(1) 생성된 윈도우 핸들 값 (HWND)
(2) width / height 값 (int)
(3) fullscreen 여부 (bool)
값들을 받습니다.
그리고 direct3d 초기화에 들어갑니다.
위에서 보여지는 DirectX 초기화 설정에 대한 내용은 여기서 다루진 않겠습니다.
(추후 DirectX 관련 글을 올리면서 어떤 내용들이었는지 언급하여 다루겠습니다)
어 일단 이거 코드를 활용 해보고 싶은데? 라는 분들은 그대로 가져가셔서 쓰시되 필요한 설정에 대한 부분만 본인에 맞게 바꾸시면 될 것 같습니다.
3. LoadTexture
LoadTexture 함수는 Graphics Class Initialize 중에 생성 한 DirectX Device에
Texture를 올리는 함수입니다.
간단히 비유하여 설명드리자면,
2. Initialize에서 Direct9Device 라는 상자를 만들었고
LoadTexture 함수는 그 상자안에 Texture라는 내용들을 담아주는 거라 보시면 됩니다.
LoadTexture 함수는 파라미터 값으로 다음의 내용들을 받습니다.
(1) fileName (const char*) - 파일 경로
(2) transColor ( COLOR_ARGB ) - 걸러 내고싶은 컬러 값
(3) width / height ( UINT [unsigned int] ) - 불러 올 텍스쳐 크기
(4) &texture ( LP_TEXTURE ) - 텍스쳐의 주소 값
아래는 LoadTexture 함수 전체입니다.
간단히 설명하자면
(1) 파라미터로 받아온 파일 경로를 통해 이미지 정보를 생성
(2) 텍스쳐 정보 생성 및 device에 입력
순으로 들어갑니다.
//============================================================================= | |
// Load the texture into default D3D memory (normal texture use) | |
// For internal engine use only. Use the TextureManager class to load game textures. | |
// Pre: filename is name of texture file. | |
// transcolor is transparent color | |
// Post: width and height = size of texture | |
// texture points to texture | |
// Returns HRESULT | |
//============================================================================= | |
HRESULT Graphics::loadTexture(const char *filename, COLOR_ARGB transcolor, | |
UINT &width, UINT &height, LP_TEXTURE &texture) | |
{ | |
// The struct for reading file info | |
D3DXIMAGE_INFO info; | |
result = E_FAIL; | |
try{ | |
if(filename == NULL) | |
{ | |
texture = NULL; | |
return D3DERR_INVALIDCALL; | |
} | |
// Get width and height from file | |
result = D3DXGetImageInfoFromFile(filename, &info); | |
if (result != D3D_OK) | |
return result; | |
width = info.Width; | |
height = info.Height; | |
// Create the new texture by loading from file | |
result = D3DXCreateTextureFromFileEx( | |
device3d, //3D device | |
filename, //image filename | |
info.Width, //texture width | |
info.Height, //texture height | |
1, //mip-map levels (1 for no chain) | |
0, //usage | |
D3DFMT_UNKNOWN, //surface format (default) | |
D3DPOOL_DEFAULT, //memory class for the texture | |
D3DX_DEFAULT, //image filter | |
D3DX_DEFAULT, //mip filter | |
transcolor, //color key for transparency | |
&info, //bitmap file info (from loaded file) | |
NULL, //color palette | |
&texture ); //destination texture | |
} catch(...) | |
{ | |
throw(GameError(gameErrorNS::FATAL_ERROR, "Error in Graphics::loadTexture")); | |
} | |
return result; | |
} |
위 함수가 기본적인 텍스쳐 정보들을 Device에 담아주는 함수입니다만
아래와 같이 만약 시스템 메모리를 사용하여 텍스쳐를 담고 싶을 경우에는
로드 텍스쳐 함수를 다음과 같이 이용합니다.
//============================================================================= | |
// Load the texture into system memory (system memory is lockable) | |
// Provides direct access to pixel data. Use the TextureManager class to load | |
// textures for display. | |
// Pre: filename is name of texture file. | |
// transcolor transparent color | |
// Post: width and height = size of texture | |
// texture points to texture | |
// Returns HRESULT and fills TextureData structure. | |
//============================================================================= | |
HRESULT Graphics::loadTextureSystemMem(const char *filename, COLOR_ARGB transcolor, | |
UINT &width, UINT &height, LP_TEXTURE &texture) | |
{ | |
// The struct for reading bitmap file info | |
D3DXIMAGE_INFO info; | |
result = E_FAIL; // Standard Windows return value | |
try{ | |
if(filename == NULL) | |
{ | |
texture = NULL; | |
return D3DERR_INVALIDCALL; | |
} | |
// Get width and height from bitmap file | |
result = D3DXGetImageInfoFromFile(filename, &info); | |
if (result != D3D_OK) | |
return result; | |
width = info.Width; | |
height = info.Height; | |
// Create the new texture by loading a bitmap image file | |
result = D3DXCreateTextureFromFileEx( | |
device3d, //3D device | |
filename, //bitmap filename | |
info.Width, //bitmap image width | |
info.Height, //bitmap image height | |
1, //mip-map levels (1 for no chain) | |
0, //usage | |
D3DFMT_UNKNOWN, //surface format (default) | |
D3DPOOL_SYSTEMMEM, //systemmem is lockable | |
D3DX_DEFAULT, //image filter | |
D3DX_DEFAULT, //mip filter | |
transcolor, //color key for transparency | |
&info, //bitmap file info (from loaded file) | |
NULL, //color palette | |
&texture ); //destination texture | |
} catch(...) | |
{ | |
throw(GameError(gameErrorNS::FATAL_ERROR, "Error in Graphics::loadTexture")); | |
} | |
return result; | |
} |
Graphics Class의 주요 핵심 내용은 이렇게 위 3가지로 좁혀집니다만.
다음 글 부터 나머지 Graphics class의 내용에 대해서 정리하도록 하겠습니다.
'MyProject > SephyEngine' 카테고리의 다른 글
June_Engine #2_Graphics.cpp (3) (0) | 2017.04.18 |
---|---|
June_Engine #2_Graphics.cpp (2) (0) | 2017.04.17 |
June_Engine #2_Graphics.h (0) | 2017.04.07 |
June_Engine #1_MainNode (0) | 2017.04.07 |
June_Engine #1_EngineError.h (0) | 2017.04.07 |