posted by REDFORCE 2017. 4. 15. 01:51

#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();
}
view raw Graphics.cpp hosted with ❤ by GitHub



소멸자는 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
view raw safeRelease.cpp hosted with ❤ by GitHub




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"));
}
}
view raw initialize.cpp hosted with ❤ by GitHub


주요 내용을 천천히 살펴보면 먼저 파라미터


 (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;
}
view raw LoadTexture.cpp hosted with ❤ by GitHub

위 함수가 기본적인 텍스쳐 정보들을 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;
}
view raw LoadTexture.cpp hosted with ❤ by GitHub



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