posted by REDFORCE 2017. 3. 13. 09:30

[Engine Graphics.h]


본 글에서는 DirectX를 통한 Graphics.header 를 다뤄보겠습니다.

[코드 전체는 최하단에 있습니다]


.cpp에 대한 내용은 다음 글을 참고하세요~


먼저 Header 에서 선언한 내용들을 살펴보도록 하겠습니다.


1. 이름 더럽게 긴것들 #define으로 선언

- 주로 사용하는 변수들의 이름이 너무 길기 때문에 

TEXTURE / DEVICE / VERTEXBUFFER / SPRITE / FONT / LINE


에 해당하는 것들만 #define 으로 편하게 바꿨습니다.


2. 자주 사용하는 컬러 값 묶기

- 자주 사용하는 컬러 값들에 대해 미리 namespace로 묶어서 열거되있습니다.

- 열거형으로 DISPLAY_MODE 가 있습니다(전체화면/창모드 구분 시 사용)



3. VertexC 구조체 선언

 - 앞으로 사용할 Vertex구조체 입니다.

 - x,y,z 좌표 값과 rhw 값(기본 1.0f)

 - color 값이 들어있습니다.



4. SpriteData 구조체

 - 앞으로 꾸준히 미친듯이 사용하는 SpriteData 구조체 입니다.

 - Engine에서 Graphic Device를 통해 그림을 출력 할 때 사용하는 SpriteData 정보.


 - x, y, width, height

 - scale (크기 값)

 - angle (그림 회전 각)

 - rect ( 텍스쳐에서의 출력할 RECT )

 - LP_TEXTURE ( 텍스쳐 파일 )

 - flipHorizontal ( 좌우 반전 여부 )

 - flipVertical (상하 반전 여부 )


에 대한 값들이 들어있습니다.




5. Graphics Class

 - 마지막으로 핵심부분인 Graphics 클래스 입니다.

 - 미리 선언해두었던 device부터 sprite와 texture에 대한 포인터 변수들

 - device 생성시 사용할 각 모드 값들이 들어있습니다.

 - 각 값들이 어떤 것인지까지는 설명하진 않겠습니다( 이거 다 설명하려면 너무 글이 길어져요

   ㅠㅠ DirectX CreateDevice 에 대해서 찾아보세요!)

 - 그 외에 초기화 결과 값을 반환 할 때 사용할 HRESULT 값과 그래픽스가 사용 될 핸들 값(HWND)가 있습니다.

 - 기타 변수들에 대한건 변수명 자체가 직관적이라 생략합니다.



6. 기타

- 그 외 public: 안에 담겨있는 각종 함수들이 엄청 많습니다만 일일이 다 설명하기엔 너무 길어지므로

필요할 때마다 설명을 추가하도록 하겠습니다.



그래서 ?? 결론은??


우리가 여기서 확인할 중요한 요지는 DirectX를 생성하고 초기화 하는데 필요한 얘들을 지금 Graphics 클래스로 따로 빼놓았다는 점입니다.


실제 DirectX에서 device를 생성하고 초기화하는데 코드를 작성해보면 약 100~200 줄 정도의 코드가 나옵니다. 

이거를 메인에서 같이 막 수행했다간....[ O _ o];;;;


따라서 DirectX초기화와 관련 된 얘들을 따로 클래스로 빼서 관리한다는 점이 중요합니다.


너무 내용이 많은지라 이글에서 한번에 모든것을 다루기는 어렵습니다만


간단히 엔진을 제작하기 위해 혹시나 참조하시는 분들 또는 DirectX를 공부하시는 분들께서는

아 Graphics를 따로 빼서 이렇게 만들 수도 있구나 하는 감을 잡는데에 도움이 되지 않을까 생각됩니다.


주 함수들의 내용이나 Graphics가 하는 일에 대해서는 cpp 글에서 다루도록 하겠습니다.



실제 헤더파일에 대한 전체 코드는 아래와 같습니다.


[GitHub - June_Engine Project : Graphics.h]

#ifndef _GRAPHICS_H // Prevent multiple definitions if this
#define _GRAPHICS_H // file is included in more than one place
#define WIN32_LEAN_AND_MEAN
#ifdef _DEBUG
#define D3D_DEBUG_INFO
#endif
class Graphics;
#include <d3d9.h>
#include <d3dx9.h>
#include <D3dx9core.h>
#include "constants.h"
#include "gameError.h"
// DirectX pointer types
#define LP_TEXTURE LPDIRECT3DTEXTURE9
#define LP_SPRITE LPD3DXSPRITE
#define LP_3DDEVICE LPDIRECT3DDEVICE9
#define LP_3D LPDIRECT3D9
#define VECTOR2 D3DXVECTOR2
#define LP_VERTEXBUFFER LPDIRECT3DVERTEXBUFFER9
#define LP_DXFONT LPD3DXFONT
#define LP_VERTEXBUFFER LPDIRECT3DVERTEXBUFFER9
#define LP_DXLINE LPD3DXLINE
// Color defines
// ARGB numbers range from 0 through 255
// a = Alpha channel (transparency where 255 is opaque)
// r = Red, g = Green, b = Blue
#define COLOR_ARGB DWORD
#define SETCOLOR_ARGB(a,r,g,b) \
((COLOR_ARGB)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff)))
namespace graphicsNS
{
// Some common colors
// ARGB numbers range from 0 through 255
// A = Alpha channel (transparency where 255 is opaque)
// R = Red, G = Green, B = Blue
const COLOR_ARGB ORANGE = D3DCOLOR_ARGB(255,255,165, 0);
const COLOR_ARGB BROWN = D3DCOLOR_ARGB(255,139, 69, 19);
const COLOR_ARGB LTGRAY = D3DCOLOR_ARGB(255,192,192,192);
const COLOR_ARGB GRAY = D3DCOLOR_ARGB(255,128,128,128);
const COLOR_ARGB OLIVE = D3DCOLOR_ARGB(255,128,128, 0);
const COLOR_ARGB PURPLE = D3DCOLOR_ARGB(255,128, 0,128);
const COLOR_ARGB MAROON = D3DCOLOR_ARGB(255,128, 0, 0);
const COLOR_ARGB TEAL = D3DCOLOR_ARGB(255, 0,128,128);
const COLOR_ARGB GREEN = D3DCOLOR_ARGB(255, 0,128, 0);
const COLOR_ARGB NAVY = D3DCOLOR_ARGB(255, 0, 0,128);
const COLOR_ARGB WHITE = D3DCOLOR_ARGB(255,255,255,255);
const COLOR_ARGB YELLOW = D3DCOLOR_ARGB(255,255,255, 0);
const COLOR_ARGB MAGENTA = D3DCOLOR_ARGB(255,255, 0,255);
const COLOR_ARGB RED = D3DCOLOR_ARGB(255,255, 0, 0);
const COLOR_ARGB CYAN = D3DCOLOR_ARGB(255, 0,255,255);
const COLOR_ARGB LIME = D3DCOLOR_ARGB(255, 0,255, 0);
const COLOR_ARGB BLUE = D3DCOLOR_ARGB(255, 0, 0,255);
const COLOR_ARGB BLACK = D3DCOLOR_ARGB(255, 0, 0, 0);
const COLOR_ARGB FILTER = D3DCOLOR_ARGB(255,255,255,255); // use to specify drawing with colorFilter
const COLOR_ARGB ALPHA25 = D3DCOLOR_ARGB( 64,255,255,255); // AND with color to get 25% alpha
const COLOR_ARGB ALPHA50 = D3DCOLOR_ARGB(128,255,255,255); // AND with color to get 50% alpha
const COLOR_ARGB BACK_COLOR = NAVY; // background color of game
const COLOR_ARGB TRANSCOLOR = BLACK; // transparent color
enum DISPLAY_MODE{TOGGLE, FULLSCREEN, WINDOW};
}
struct VertexC // Vertex with Color
{
float x, y, z; // vertex location
float rhw; // reciprocal homogeneous W (set to 1)
unsigned long color; // vertex color
};
// Flexible Vertex Format Codes
// D3DFVF_XYZRHW = The verticies are transformed
// D3DFVF_DIFFUSE = The verticies contain diffuse color data
#define D3DFVF_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)
// SpriteData: The properties required by Graphics::drawSprite to draw a sprite
struct SpriteData
{
int width; // width of sprite in pixels
int height; // height of sprite in pixels
float x; // screen location (top left corner of sprite)
float y;
float scale; // <1 smaller, >1 bigger
float angle; // rotation angle in radians
RECT rect; // used to select an image from a larger texture
LP_TEXTURE texture; // pointer to texture
bool flipHorizontal; // true to flip sprite horizontally (mirror)
bool flipVertical; // true to flip sprite vertically
};
class Graphics
{
private:
// DirectX pointers and stuff
LP_3D direct3d;
LP_3DDEVICE device3d;
LP_SPRITE sprite;
LP_DXLINE line; // line pointer
D3DPRESENT_PARAMETERS d3dpp;
D3DDISPLAYMODE pMode;
IDirect3DQuery9* pOcclusionQuery; // for pixel perfect collision detection
DWORD numberOfPixelsColliding; // for pixel perfect collision detection
// other variables
HRESULT result; // standard Windows return codes
HWND hwnd;
bool fullscreen;
bool stencilSupport; // true if device supports stencil buffer
int width;
int height;
COLOR_ARGB backColor; // background color
// (For internal engine use only. No user serviceable parts inside.)
// Initialize D3D presentation parameters
void initD3Dpp();
public:
// Constructor
Graphics();
// Destructor
virtual ~Graphics();
// Releases direct3d and device3d.
void releaseAll();
// Initialize DirectX graphics
// Throws GameError on error
// Pre: hw = handle to window
// width = width in pixels
// height = height in pixels
// fullscreen = true for full screen, false for window
void initialize(HWND hw, int width, int height, bool fullscreen);
// Create a vertex buffer.
// Pre: verts[] contains vertex data.
// size = size of verts[]
// Post: &vertexBuffer points to buffer if successful.
HRESULT createVertexBuffer(VertexC verts[], UINT size, LP_VERTEXBUFFER &vertexBuffer);
// Display a quad (rectangle) with alpha transparency.
// Pre: createVertexBuffer was used to create vertexBuffer containing four
// vertices defining the quad in clockwise order.
// g3ddev->BeginScene was called
bool drawQuad(LP_VERTEXBUFFER vertexBuffer);
// 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 = name of texture file.
// transcolor = transparent color
// Post: width and height = size of texture
// texture points to texture
HRESULT loadTexture(const char * filename, COLOR_ARGB transcolor, UINT &width, UINT &height, LP_TEXTURE &texture);
// 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 = name of texture file.
// transcolor = transparent color
// Post: width and height = size of texture
// texture points to texture
HRESULT loadTextureSystemMem(const char *filename, COLOR_ARGB transcolor, UINT &width, UINT &height, LP_TEXTURE &texture);
// Display the offscreen backbuffer to the screen.
HRESULT showBackbuffer();
// Checks the adapter to see if it is compatible with the BackBuffer height,
// width and refresh rate specified in d3dpp. Fills in the pMode structure with
// the format of the compatible mode, if found.
// Pre: d3dpp is initialized.
// Post: Returns true if compatible mode found and pMode structure is filled.
// Returns false if no compatible mode found.
bool isAdapterCompatible();
// Draw the sprite described in SpriteData structure.
// color is optional, it is applied as a filter, WHITE is default (no change).
// Creates a sprite Begin/End pair.
// Pre: spriteData.rect defines the portion of spriteData.texture to draw
// spriteData.rect.right must be right edge + 1
// spriteData.rect.bottom must be bottom edge + 1
void drawSprite(const SpriteData &spriteData, // sprite to draw
COLOR_ARGB color = graphicsNS::WHITE); // default to white color filter (no change)
// Reset the graphics device.
HRESULT reset();
// Toggle, fullscreen or window display mode
// Pre: All user created D3DPOOL_DEFAULT surfaces are freed.
// Post: All user surfaces are recreated.
void changeDisplayMode(graphicsNS::DISPLAY_MODE mode = graphicsNS::TOGGLE);
// Return length of vector v.
static float Vector2Length(const VECTOR2 *v) {return D3DXVec2Length(v);}
// Return Dot product of vectors v1 and v2.
static float Vector2Dot(const VECTOR2 *v1, const VECTOR2 *v2) {return D3DXVec2Dot(v1, v2);}
// Normalize vector v.
static void Vector2Normalize(VECTOR2 *v) {D3DXVec2Normalize(v, v);}
// Transform vector v with matrix m.
static VECTOR2* Vector2Transform(VECTOR2 *v, D3DXMATRIX *m) {return D3DXVec2TransformCoord(v,v,m);}
// Return the number of pixels colliding between the two sprites.
// Pre: The device supports a stencil buffer and pOcclusionQuery points to
// a valid occlusionQuery object.
// Post: Returns the number of pixels of overlap
// This function waits for the graphics card to render the last frame and return
// the collision query pixel count. To avoid slowing down your game, use a
// simple collison test first to eliminate entities that are not colliding.
DWORD pixelCollision(const SpriteData &sprite1, const SpriteData &sprite2);
// get functions
// Return direct3d.
LP_3D get3D() { return direct3d; }
// Return device3d.
LP_3DDEVICE get3Ddevice() { return device3d; }
// Return sprite
LP_SPRITE getSprite() { return sprite; }
// Return handle to device context (window).
HDC getDC() { return GetDC(hwnd); }
// Test for lost device
HRESULT getDeviceState();
// Return fullscreen
bool getFullscreen() { return fullscreen; }
// Return pOcclusionQuery
IDirect3DQuery9* getPOcclusionQuery() { return pOcclusionQuery; }
// Returns true if the graphics card supports a stencil buffer
bool getStencilSupport() { return stencilSupport; }
// Set color used to clear screen
void setBackColor(COLOR_ARGB c) {backColor = c;}
//=============================================================================
// Create DX line, description from D3dx9core.h
// This object intends to provide an easy way to draw lines using D3D.
//
// Begin -
// Prepares device for drawing lines
// Draw -
// Draws a line strip in screen-space.
// Input is in the form of a array defining points on the line strip. of D3DXVECTOR2
// DrawTransform -
// Draws a line in screen-space with a specified input transformation matrix.
// End -
// Restores device state to how it was when Begin was called.
// SetPattern -
// Applies a stipple pattern to the line. Input is one 32-bit
// DWORD which describes the stipple pattern. 1 is opaque, 0 is
// transparent.
// SetPatternScale -
// Stretches the stipple pattern in the u direction. Input is one
// floating-point value. 0.0f is no scaling, whereas 1.0f doubles
// the length of the stipple pattern.
// SetWidth -
// Specifies the thickness of the line in the v direction. Input is
// one floating-point value.
// SetAntialias -
// Toggles line antialiasing. Input is a BOOL.
// TRUE = Antialiasing on.
// FALSE = Antialiasing off.
// SetGLLines -
// Toggles non-antialiased OpenGL line emulation. Input is a BOOL.
// TRUE = OpenGL line emulation on.
// FALSE = OpenGL line emulation off.
// OpenGL line: Regular line:
// *\ *\
// | \ / \
// | \ *\ \
// *\ \ \ \
// \ \ \ \
// \ * \ *
// \ | \ /
// \| *
// *
// OnLostDevice, OnResetDevice -
// Call OnLostDevice() on this object before calling Reset() on the
// device, so that this object can release any stateblocks and video
// memory resources. After Reset(), the call OnResetDevice().
//=============================================================================
void createLine(LP_DXLINE *line)
{
D3DXCreateLine(device3d, line);
}
//=============================================================================
// Draw DirectX line from X1,Y1 to X2,Y2.
// width defauts to 1.
// color defaults to graphicsNS::WHITE.
//=============================================================================
void drawLine(float x1, float y1, float x2, float y2, float width = 1.0f, COLOR_ARGB color = graphicsNS::WHITE);
//=============================================================================
// Clear backbuffer and BeginScene()
//=============================================================================
HRESULT beginScene()
{
result = E_FAIL;
if(device3d == NULL)
return result;
// Clear back buffer, stencil buffer and depth buffer
device3d->Clear(0, 0,
D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER,
backColor, 1.0f, 0);
result = device3d->BeginScene(); // begin scene for drawing
return result;
}
//=============================================================================
// EndScene()
//=============================================================================
HRESULT endScene()
{
result = E_FAIL;
if(device3d)
result = device3d->EndScene();
return result;
}
//=============================================================================
// Sprite Begin
//=============================================================================
void spriteBegin()
{
sprite->Begin(D3DXSPRITE_ALPHABLEND);
}
//=============================================================================
// Sprite End
//=============================================================================
void spriteEnd()
{
sprite->End();
}
};
#endif
view raw Graphics.h hosted with ❤ by GitHub