#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
-----------------------------------------------------------------------
이번 글에서는 앞서 다룬 DrawSprite 함수에 이어서 적도록 하겠습니다.
1. changeDisplayMode (화면 전환 함수 [창모드/전체화면모드] )
이어서 다룰 첫 번째 함수는 changeDisplayMode 입니다.
이름만봐도 알 수 있듯이 위 함수는 전체화면이나 창모드 화면으로 변경할 시에 사용 되는 함수입니다.
사용빈도 자체는 높진 않지만 일반적인 게임이라면 필수적으로 지원되야하는
기능이라 할 수 있습니다.
우리는 일상에서 많은 게임들이 Alt+Enter 키를 누르면 전체화면이나 창모드로 바뀌는 그런 경우를 볼 수 있었을 것 입니다.
단축키 자체는 별도로 작성해서 이 함수를 호출하도록 하게끔만 만들면 되므로
키 입력에 대한 내용은 추후 Input Class 에서 다루도록 하고 여기서는
어떻게 화면이 변환되는지에 대해서만 언급하겠습니다.
먼저 코드를 살펴보겠습니다.
//============================================================================= | |
// Toggle window or fullscreen mode | |
// Pre: All user created D3DPOOL_DEFAULT surfaces are freed. | |
// Post: All user surfaces are recreated. | |
//============================================================================= | |
void Graphics::changeDisplayMode(graphicsNS::DISPLAY_MODE mode) | |
{ | |
try{ | |
switch(mode) | |
{ | |
case graphicsNS::FULLSCREEN: | |
if(fullscreen) // if already in fullscreen mode | |
return; | |
fullscreen = true; break; | |
case graphicsNS::WINDOW: | |
if(fullscreen == false) // if already in window mode | |
return; | |
fullscreen = false; break; | |
default: // default to toggle window/fullscreen | |
fullscreen = !fullscreen; | |
} | |
reset(); | |
if(fullscreen) // fullscreen | |
{ | |
SetWindowLong(hwnd, GWL_STYLE, WS_EX_TOPMOST | WS_VISIBLE | WS_POPUP); | |
} | |
else // windowed | |
{ | |
SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); | |
SetWindowPos(hwnd, HWND_TOP, 0,0,GAME_WIDTH,GAME_HEIGHT, | |
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); | |
// Adjust window size so client area is GAME_WIDTH x GAME_HEIGHT | |
RECT clientRect; | |
GetClientRect(hwnd, &clientRect); // get size of client area of window | |
MoveWindow(hwnd, | |
0, // Left | |
0, // Top | |
GAME_WIDTH+(GAME_WIDTH-clientRect.right), // Right | |
GAME_HEIGHT+(GAME_HEIGHT-clientRect.bottom), // Bottom | |
TRUE); // Repaint the window | |
} | |
} catch(...) | |
{ | |
// An error occured, try windowed mode | |
SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); | |
SetWindowPos(hwnd, HWND_TOP, 0,0,GAME_WIDTH,GAME_HEIGHT, | |
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); | |
// Adjust window size so client area is GAME_WIDTH x GAME_HEIGHT | |
RECT clientRect; | |
GetClientRect(hwnd, &clientRect); // get size of client area of window | |
MoveWindow(hwnd, | |
0, // Left | |
0, // Top | |
GAME_WIDTH+(GAME_WIDTH-clientRect.right), // Right | |
GAME_HEIGHT+(GAME_HEIGHT-clientRect.bottom), // Bottom | |
TRUE); // Repaint the window | |
} | |
} |
함수 내용 전체는 try - catch 문으로 감싸져 있습니다.
이유는 미리 우리가 정의해놓은 어떤 디스플레이 모드 상에서 바뀌는 거라면
상관이 없지만 어떤 에러로 인해 제대로 동작이 안될 경우를 대비하여
안전하게 화면을 바꾸기 위함입니다.
천천히 try 문 부터 살펴보도록 하겠습니다.
switch 문으로 mode 플래그 값을 통해 구분이 되어있는데
동작 원리는 밖에 선언해두었던 fullscreen (bool) 값을 이용하여 단순히 true / false 를 교체해주는 행위를 합니다.
그리고 switch 문에서 나오면
reset() 함수를 호출하네요.
reset 함수의 내용은 아래와 같습니다.
//============================================================================= | |
// Reset the graphics device | |
//============================================================================= | |
HRESULT Graphics::reset() | |
{ | |
safeRelease(line); | |
safeRelease(pOcclusionQuery); // release query | |
initD3Dpp(); // init D3D presentation parameters | |
sprite->OnLostDevice(); // release sprite | |
result = device3d->Reset(&d3dpp); // attempt to reset graphics device | |
// Configure for alpha blend of primitives | |
device3d->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); | |
device3d->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); | |
device3d->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); | |
// recreate query | |
device3d->CreateQuery(D3DQUERYTYPE_OCCLUSION, &pOcclusionQuery); | |
sprite->OnResetDevice(); // recreate sprite | |
createLine(&line); // recreate a DirectX line | |
return result; | |
} |
그리고 fullscreen 값을 체크하여 true 라면
현재 모니터의 전체 화면으로 메인 윈도우를 늘려주고,
아니라면 현재 게임의 width / height 값으로 창화면을 만들어줍니다.
catch 구문으로 갔을 경우의 하는 역할도 마찬가지 입니다.
2. pixelCollision (픽셀 충돌 함수)
두 번째로 다룰 함수는 픽셀 충돌 함수 입니다.
pixelCollision 함수는 저도 꽤 어려운 구역이라 어떻게 설명을 드려야 할지 저도 잘 모르겠습니다. 그래도 아에 스킵하고 넘어갈순 없으므로 어떤 식으로 픽셀 충돌을 검출하는지 확인해보겠습니다.
다음이 픽셀 충돌 함수의 내용입니다.
//============================================================================= | |
// 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. | |
// Using pixel perfect collision test with multiple entities would require | |
// creating multiple occlusionQuery objects and clearing the stencil buffer | |
// between each test. | |
//============================================================================= | |
DWORD Graphics::pixelCollision(const SpriteData &sprite1, const SpriteData &sprite2) | |
{ | |
if(!stencilSupport) // if no stencil buffer support | |
return 0; | |
beginScene(); | |
// Set up stencil buffer using current entity | |
device3d->SetRenderState(D3DRS_STENCILENABLE, true); | |
device3d->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); | |
device3d->SetRenderState(D3DRS_STENCILREF, 0x1); | |
device3d->SetRenderState(D3DRS_STENCILMASK, 0xffffffff); | |
device3d->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff); | |
device3d->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); | |
device3d->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); | |
// Write a 1 into the stencil buffer for each non-transparent pixel in ent | |
spriteBegin(); | |
// Enable stencil buffer (must be after spriteBegin) | |
device3d->SetRenderState(D3DRS_STENCILENABLE, true); | |
drawSprite(sprite2); // write 1s to stencil buffer | |
spriteEnd(); | |
// Change stencil buffer to only allow writes where the stencil value is 1 | |
// (where the ent sprite is colliding with the current sprite) | |
device3d->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL); | |
device3d->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); | |
// Begin occlusion query to count pixels that are drawn | |
pOcclusionQuery->Issue(D3DISSUE_BEGIN); | |
spriteBegin(); | |
// Enable stencil buffer (must be after spriteBegin) | |
device3d->SetRenderState(D3DRS_STENCILENABLE, true); | |
drawSprite(sprite1); // draw current entity | |
spriteEnd(); | |
// End occlusion query | |
pOcclusionQuery->Issue(D3DISSUE_END); | |
// Wait until the GPU is finished. | |
while(S_FALSE == pOcclusionQuery->GetData( &numberOfPixelsColliding, | |
sizeof(DWORD), D3DGETDATA_FLUSH )) | |
{} | |
// Turn off stencil | |
device3d->SetRenderState(D3DRS_STENCILENABLE, false); | |
endScene(); | |
return numberOfPixelsColliding; | |
} |
픽셀 충돌은 먼저 두 개의 spriteData 구조체 파라미터를 받습니다.
그리고 다소 어려운 내용일 수도 있지만 깊이 버퍼 값을 이용하여 픽셀 충돌을 검사합니다.
코드를 보시면, 처음 stencilSupport 여부를 체크하는데요.
이것은 그래픽카드에서 깊이 버퍼를 이용한 기술적 지원을 해주는지 여부를 확인합니다.
(위 stencilSupport 값은 Initialize( ) 에서 true / false 여부가 판단되어 있습니다)
다음, 깊이 버퍼 기술을 이용할 수 있다면
다양한 RenderState를 설정하는 것을 볼 수 있습니다.
이 값들이 의미하는 바에 대해서는 여기서 일일이 설명드리기에 너무 많으므로
MSDN이나 구글링 하시는 것을 통해 알아가시기를 양해드립니다.
첫 번째,
중요한 요점은 D3DRS_STENCILE 이라 하는 RenderState 값들을 이용한다는 점을 숙지하는 것 입니다.
두 번째,
설정한 RenderState 값들 중에 몇가지는 spriteBegin() 이 호출된 이후에 설정되어야 하는 값들이 있습니다.
세 번째,
pOcclusionQuery (IDirect3DQuery9*)를 이용하여 두 스프라이트의 픽셀 갯수만큼 while 문을 돌고 픽셀 충돌 여부를 검출합니다.
그리고 반환 된 충돌 된 픽셀 갯수가 numberOfPixelsColliding 에 담겨서 리턴되게 됩니다.
만약 이 함수를 이용하여 픽셀 충돌을 검사한다면 numberOfPixelsColliding 값이 0보다 큰지 아닌지만 검사한다면 픽셀 충돌이 이뤄졌는가 아닌가를 알 수 있습니다.
여기까지가 주요 Graphics Class에 대한 내용들이었습니다.
의외로 세 번에 걸쳐서 글을 쓰게 될줄은 몰랐습니다.
처음에는 한번에 다 적을 수 있겠지~~ 했는데,
코드를 포함하여 적다보니 량이 적지않구나 하는걸 느낀 후로 조금 나눠서 글을 적게 되었습니다.
만약 여기까지 읽어주셨다면 정말 감사드리고, 궁금하신 점 있으시면 답글이나 이메일
redforce01@naver.com 으로 주시면 제가 아는 한에서 꼭 답변해드리겠습니다.
추신. getDeviceState() 함수가 여기서는 다뤄지지 않은 것 같습니다만,
추후에 reset() 함수를 다시 활용할 때 한번 더 정리 하여 올릴 예정입니다.
아래는 Graphics 클래스의 .h 파일과 .cpp 파일 전체 입니다.
헤더 코드입니다.
#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 | |
cpp 코드입니다.
#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(); | |
} | |
//============================================================================= | |
// 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")); | |
} | |
} | |
//============================================================================= | |
// 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; | |
} | |
//============================================================================= | |
// 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; | |
} | |
//============================================================================= | |
// Create a vertex buffer. | |
// Pre: verts[] contains vertex data. | |
// size = size of verts[] | |
// Post: &vertexBuffer points to buffer if successful. | |
//============================================================================= | |
HRESULT Graphics::createVertexBuffer(VertexC verts[], UINT size, LP_VERTEXBUFFER &vertexBuffer) | |
{ | |
// Standard Windows return value | |
HRESULT result = E_FAIL; | |
// Create a vertex buffer | |
result = device3d->CreateVertexBuffer(size, D3DUSAGE_WRITEONLY, D3DFVF_VERTEX, | |
D3DPOOL_DEFAULT, &vertexBuffer, NULL); | |
if(FAILED(result)) | |
return result; | |
void *ptr; | |
// must lock buffer before data can be transferred in | |
result = vertexBuffer->Lock(0, size, (void**)&ptr, 0); | |
if(FAILED(result)) | |
return result; | |
memcpy(ptr, verts, size); // copy vertex data into buffer | |
vertexBuffer->Unlock(); // unlock buffer | |
return result; | |
} | |
//============================================================================= | |
// Display a quad with alpha transparency using Triangle Fan | |
// Pre: createVertexBuffer was used to create vertexBuffer containing four | |
// vertices defining the quad in clockwise order. | |
// g3ddev->BeginScene was called | |
// Post: Quad is drawn | |
//============================================================================= | |
bool Graphics::drawQuad(LP_VERTEXBUFFER vertexBuffer) | |
{ | |
HRESULT result = E_FAIL; // standard Windows return value | |
if(vertexBuffer == NULL) | |
return false; | |
device3d->SetRenderState(D3DRS_ALPHABLENDENABLE, true); // enable alpha blend | |
device3d->SetStreamSource(0, vertexBuffer, 0, sizeof(VertexC)); | |
device3d->SetFVF(D3DFVF_VERTEX); | |
result = device3d->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2); | |
device3d->SetRenderState(D3DRS_ALPHABLENDENABLE, false); // alpha blend off | |
if(FAILED(result)) | |
return false; | |
return true; | |
} | |
//============================================================================= | |
// Draw DirectX line from X1,Y1 to X2,Y2. | |
// width defauts to 1. | |
// color defaults to graphicsNS::WHITE. | |
//============================================================================= | |
void Graphics::drawLine(float x1, float y1, float x2, float y2, float width, COLOR_ARGB color) | |
{ | |
VECTOR2 endpoints[] = { VECTOR2(x1, y1), VECTOR2(x2, y2) }; | |
if (width < 0.1f) | |
width = 0.1f; | |
line->SetWidth(width); // SetWidth must be called before Begin | |
line->Begin(); // begin drawing lines | |
line->Draw(endpoints, 2, color); // draw line, 2 vertices | |
line->End(); // end drawing lines | |
} | |
//============================================================================= | |
// Display the backbuffer | |
//============================================================================= | |
HRESULT Graphics::showBackbuffer() | |
{ | |
// Display backbuffer to screen | |
result = device3d->Present(NULL, NULL, NULL, NULL); | |
return result; | |
} | |
//============================================================================= | |
// 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 Graphics::isAdapterCompatible() | |
{ | |
UINT modes = direct3d->GetAdapterModeCount(D3DADAPTER_DEFAULT, | |
d3dpp.BackBufferFormat); | |
for(UINT i=0; i<modes; i++) | |
{ | |
result = direct3d->EnumAdapterModes( D3DADAPTER_DEFAULT, | |
d3dpp.BackBufferFormat, | |
i, &pMode); | |
if( pMode.Height == d3dpp.BackBufferHeight && | |
pMode.Width == d3dpp.BackBufferWidth && | |
pMode.RefreshRate >= d3dpp.FullScreen_RefreshRateInHz) | |
return true; | |
} | |
return false; | |
} | |
//============================================================================= | |
// Draw the sprite described in SpriteData structure | |
// Color is optional, it is applied like a filter, WHITE is default (no change) | |
// Pre : sprite->Begin() is called | |
// Post: sprite->End() is called | |
// 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 Graphics::drawSprite(const SpriteData &spriteData, COLOR_ARGB color) | |
{ | |
if(spriteData.texture == NULL) // if no texture | |
return; | |
// Find center of sprite | |
D3DXVECTOR2 spriteCenter=D3DXVECTOR2((float)(spriteData.width/2*spriteData.scale), | |
(float)(spriteData.height/2*spriteData.scale)); | |
// Screen position of the sprite | |
D3DXVECTOR2 translate=D3DXVECTOR2((float)spriteData.x,(float)spriteData.y); | |
// Scaling X,Y | |
D3DXVECTOR2 scaling(spriteData.scale,spriteData.scale); | |
if (spriteData.flipHorizontal) // if flip horizontal | |
{ | |
scaling.x *= -1; // negative X scale to flip | |
// Get center of flipped image. | |
spriteCenter.x -= (float)(spriteData.width*spriteData.scale); | |
// Flip occurs around left edge, translate right to put | |
// Flipped image in same location as original. | |
translate.x += (float)(spriteData.width*spriteData.scale); | |
} | |
if (spriteData.flipVertical) // if flip vertical | |
{ | |
scaling.y *= -1; // negative Y scale to flip | |
// Get center of flipped image | |
spriteCenter.y -= (float)(spriteData.height*spriteData.scale); | |
// Flip occurs around top edge, translate down to put | |
// Flipped image in same location as original. | |
translate.y += (float)(spriteData.height*spriteData.scale); | |
} | |
// Create a matrix to rotate, scale and position our sprite | |
D3DXMATRIX matrix; | |
D3DXMatrixTransformation2D( | |
&matrix, // the matrix | |
NULL, // keep origin at top left when scaling | |
0.0f, // no scaling rotation | |
&scaling, // scale amount | |
&spriteCenter, // rotation center | |
(float)(spriteData.angle), // rotation angle | |
&translate); // X,Y location | |
// Tell the sprite about the matrix "Hello Neo" | |
sprite->SetTransform(&matrix); | |
// Draw the sprite | |
sprite->Draw(spriteData.texture, &spriteData.rect,NULL,NULL,color); | |
} | |
//============================================================================= | |
// Toggle window or fullscreen mode | |
// Pre: All user created D3DPOOL_DEFAULT surfaces are freed. | |
// Post: All user surfaces are recreated. | |
//============================================================================= | |
void Graphics::changeDisplayMode(graphicsNS::DISPLAY_MODE mode) | |
{ | |
try{ | |
switch(mode) | |
{ | |
case graphicsNS::FULLSCREEN: | |
if(fullscreen) // if already in fullscreen mode | |
return; | |
fullscreen = true; break; | |
case graphicsNS::WINDOW: | |
if(fullscreen == false) // if already in window mode | |
return; | |
fullscreen = false; break; | |
default: // default to toggle window/fullscreen | |
fullscreen = !fullscreen; | |
} | |
reset(); | |
if(fullscreen) // fullscreen | |
{ | |
SetWindowLong(hwnd, GWL_STYLE, WS_EX_TOPMOST | WS_VISIBLE | WS_POPUP); | |
} | |
else // windowed | |
{ | |
SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); | |
SetWindowPos(hwnd, HWND_TOP, 0,0,GAME_WIDTH,GAME_HEIGHT, | |
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); | |
// Adjust window size so client area is GAME_WIDTH x GAME_HEIGHT | |
RECT clientRect; | |
GetClientRect(hwnd, &clientRect); // get size of client area of window | |
MoveWindow(hwnd, | |
0, // Left | |
0, // Top | |
GAME_WIDTH+(GAME_WIDTH-clientRect.right), // Right | |
GAME_HEIGHT+(GAME_HEIGHT-clientRect.bottom), // Bottom | |
TRUE); // Repaint the window | |
} | |
} catch(...) | |
{ | |
// An error occured, try windowed mode | |
SetWindowLong(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); | |
SetWindowPos(hwnd, HWND_TOP, 0,0,GAME_WIDTH,GAME_HEIGHT, | |
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); | |
// Adjust window size so client area is GAME_WIDTH x GAME_HEIGHT | |
RECT clientRect; | |
GetClientRect(hwnd, &clientRect); // get size of client area of window | |
MoveWindow(hwnd, | |
0, // Left | |
0, // Top | |
GAME_WIDTH+(GAME_WIDTH-clientRect.right), // Right | |
GAME_HEIGHT+(GAME_HEIGHT-clientRect.bottom), // Bottom | |
TRUE); // Repaint the window | |
} | |
} | |
//============================================================================= | |
// 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. | |
// Using pixel perfect collision test with multiple entities would require | |
// creating multiple occlusionQuery objects and clearing the stencil buffer | |
// between each test. | |
//============================================================================= | |
DWORD Graphics::pixelCollision(const SpriteData &sprite1, const SpriteData &sprite2) | |
{ | |
if(!stencilSupport) // if no stencil buffer support | |
return 0; | |
beginScene(); | |
// Set up stencil buffer using current entity | |
device3d->SetRenderState(D3DRS_STENCILENABLE, true); | |
device3d->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); | |
device3d->SetRenderState(D3DRS_STENCILREF, 0x1); | |
device3d->SetRenderState(D3DRS_STENCILMASK, 0xffffffff); | |
device3d->SetRenderState(D3DRS_STENCILWRITEMASK,0xffffffff); | |
device3d->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP); | |
device3d->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); | |
// Write a 1 into the stencil buffer for each non-transparent pixel in ent | |
spriteBegin(); | |
// Enable stencil buffer (must be after spriteBegin) | |
device3d->SetRenderState(D3DRS_STENCILENABLE, true); | |
drawSprite(sprite2); // write 1s to stencil buffer | |
spriteEnd(); | |
// Change stencil buffer to only allow writes where the stencil value is 1 | |
// (where the ent sprite is colliding with the current sprite) | |
device3d->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_EQUAL); | |
device3d->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_KEEP); | |
// Begin occlusion query to count pixels that are drawn | |
pOcclusionQuery->Issue(D3DISSUE_BEGIN); | |
spriteBegin(); | |
// Enable stencil buffer (must be after spriteBegin) | |
device3d->SetRenderState(D3DRS_STENCILENABLE, true); | |
drawSprite(sprite1); // draw current entity | |
spriteEnd(); | |
// End occlusion query | |
pOcclusionQuery->Issue(D3DISSUE_END); | |
// Wait until the GPU is finished. | |
while(S_FALSE == pOcclusionQuery->GetData( &numberOfPixelsColliding, | |
sizeof(DWORD), D3DGETDATA_FLUSH )) | |
{} | |
// Turn off stencil | |
device3d->SetRenderState(D3DRS_STENCILENABLE, false); | |
endScene(); | |
return numberOfPixelsColliding; | |
} | |
//============================================================================= | |
// Test for lost device | |
//============================================================================= | |
HRESULT Graphics::getDeviceState() | |
{ | |
result = E_FAIL; // default to fail, replace on success | |
if (device3d == NULL) | |
return result; | |
result = device3d->TestCooperativeLevel(); | |
return result; | |
} | |
//============================================================================= | |
// Release all | |
//============================================================================= | |
void Graphics::releaseAll() | |
{ | |
safeRelease(pOcclusionQuery); | |
safeRelease(sprite); | |
safeRelease(device3d); | |
safeRelease(direct3d); | |
safeRelease(line); | |
} | |
//============================================================================= | |
// Reset the graphics device | |
//============================================================================= | |
HRESULT Graphics::reset() | |
{ | |
safeRelease(line); | |
safeRelease(pOcclusionQuery); // release query | |
initD3Dpp(); // init D3D presentation parameters | |
sprite->OnLostDevice(); // release sprite | |
result = device3d->Reset(&d3dpp); // attempt to reset graphics device | |
// Configure for alpha blend of primitives | |
device3d->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); | |
device3d->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); | |
device3d->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); | |
// recreate query | |
device3d->CreateQuery(D3DQUERYTYPE_OCCLUSION, &pOcclusionQuery); | |
sprite->OnResetDevice(); // recreate sprite | |
createLine(&line); // recreate a DirectX line | |
return result; | |
} |
'MyProject > SephyEngine' 카테고리의 다른 글
June_Engine #3_Image Class .cpp (1) (0) | 2017.04.19 |
---|---|
June_Engine #3_Image (Class) & SpriteData (Struct) (0) | 2017.04.19 |
June_Engine #2_Graphics.cpp (2) (0) | 2017.04.17 |
June_Engine #2_Graphics.cpp (1) (0) | 2017.04.15 |
June_Engine #2_Graphics.h (0) | 2017.04.07 |