posted by REDFORCE 2017. 3. 13. 21:24

본 글에서는 Graphics.cpp 에 대한 내용을 다루도록 하겠습니다.


Header에 대한 내용을 아직 읽고 오지 않으신 분은 먼저 .h 에 대한 내용을 참고하시기를 추천합니다.

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


1. Graphics 생성자

 - Graphics.h 에서 정의한 Graphics 클래스의 생성자 입니다.

 - direct3d / device3d 등 미리 사용 될 변수들에 대해 초기화를 이루어집니다.



2. Graphics::initialize

 - 핵심 부분인 initialize 입니다.

 - 파라미터 값으로 device를 올린 window핸들값 HWND와 width , height, fullscreen

 - direct3d = Direct3DCreate9(D3D_SDK_VERSION) 에서 볼 수 있듯이 본 엔진은 Direct9을 사용합니다.

 - Direct3DCreate9 은 directX 함수로 현재 PC의 directX sdk 버전을 체크해서 directx를 생성합니다.

 - 만약 널 값이면 알아서 에러뿜뿜..으로 처리했습니다.

 - 그리고 InitD3Dpp() 함수를 수행합니다. (d3dpp 포맷이나 모드를 결정합니다)

 - 그 외에 더럽게 많은 device나 sprite 등의 셋팅을 진행합니다.



모든 변수들과 내용을 일일이 설명하기엔 너무 글이 길어지므로

그냥 아 DirectX 함수로 디바이스 생성하고 초기화 하고 이런저런 셋팅을 하네~ 하고 보시면 됩니다.



 - 그림이 하도 커져서 두개로 나누었습니다.

  !! if(FAILED(result))

         throw(GameError(gameErrorNS::FATAL_ERROR, "Error Creating Direct3D Device));


 가 겹쳐 있습니다.


3. LoadTexture

 - 앞으로 사용할 모든 텍스쳐 파일을 로드해올 때 사용하는 함수입니다.

 - 파라미터 값으로 

/ 파일의 경로 / transcolor 값 /텍스쳐 크기 / 담아둘 텍스쳐 포인터 / 를 받습니다.

 - LoadTexture 함수는 일반적인 모든 Texture Image들을 받아옵니다.  ( bmp, jpg, png 등 )



4. LoadTextureSystemMem

 - LoadTexture 함수와 동일한 기능을 수행합니다.

 - 큰 차이는 System Memory를 사용한다는 점 입니다.

 - D3DXCreateTextureFromFileEx ( ) 를 보시면 D3DPOOL_SYSTEMMEM 값이 다른 것을 알 수 있습니다.

 - bitmap 파일만 읽을 수 있습니다.



5. CreateVertexBuffer

- 버텍스 버퍼를 이용한 렌더시 사용하는 함수입니다.

- 주로 버텍스 버퍼를 이용하여 선이나 상자를 그릴 때 사용합니다.

- 버텍스버퍼에 대한 설명은 생략하겠습니다.


6. DrawQuad & DrawLine

- 버텍스 버퍼를 이용하여 선이나 네모 상자를 그릴 때 사용합니다.



7. showBackBuffer

 - device를 이용해서 모든 그리기 작업이 끝나면 불려지는 함수 입니다.

 - device3d->present(NULL, NULL, NULL, NULL) 을 수행합니다.

 - 결과 값으로 HRESULT 값을 받은 것을 그대로 리턴~



8. DrawSprite

 - 앞으로 더럽게 많이 쓰게 될 DrawSprite 함수 입니다.

 - 2D Game에서 모든 그리기 작업은 이 함수를 통해 그리게 됩니다.

 - 다소 설명이 들어가야 할 것 같으니 파라미터부터 설명해드리도록 하겠습니다.


 (1) SpriteData 구조체 참조 값과 transcolor 값을 받습니다.

 (2) 받아온 spriteData의 값을 토대로 VECTOR2 로 center / translate / scaling 작업을 하고 상하좌우 반전 여부를 체크하고 반전 시 그림을 반대로 반전시킵니다.

 (3) D3DMatrix 로 출력할 내용을 2D 행렬로 변환 합니다.

 (4) 변환 시킨 행렬의 내용을 device의 sprite->setTransform( ) 를 통해 transform을 setup 시킵니다.

 (5) 마지막으로 Draw!! 


Draw작업 시에는 SpriteData의 텍스쳐 / 텍스쳐에서 출력할 RECT 위치 / 투명 처리 시킬 color 값이 들어갑니다.



내용이 길어서 2장의 그림으로 나누었습니다.

매트릭스 부분부터 겹쳐 있으니 코드 보시는데 참고!



9. ChangeDisplayMode

 - 혹여나 게임을 진행중에 DisplayMode가 변할 시 불려지는 함수 입니다.

 - 파라미터 값으로 헤더에 선언해두었던 DISPLAY_MODE 열거형 값을 받습니다.

 - 워낙 직관적인 내용들뿐이라 따로 설명은 안하겠습니다.

 - 심플하게 전체화면이면 전체화면으로 돌리는 작업을 하면서 Device가 잡혀있는 Window(HWND)를 전체화면으로 변경합니다.

 - 창모드는 반대로~



마찬가지로 2장의 사진이 겹쳐있습니다.



10. PixcelCollision

 - 저도 다시 정리해보면서 확인을 해서 조금 충격먹었습니다. (픽셀 충돌 처리부분이 있었군요 ㅡ ㅡa)

 - 실제 픽셀충돌에 대해서 처리를 하려면 device에서 renderstate로 설정해야 될 것들이 조금 많습니다만 일일이 설명드리기엔 역시나 너무 길어지므로 그냥 저런식으로 셋팅한다는 점만 보고 넘어가셔도 될 것 같습니다.

 - 주요 부분은 픽셀 충돌 처리를 해야하는 SpriteData 구조체 A, B에서 

 - IDirect3DQuery9* 를 이용하여 DirectX 함수를 사용한다는 점 입니다.

 - 이 함수가 알아서 두 sprite에서 픽셀충돌이 이뤄졌는지를 반환해줍니다.

 - 최종적으로 pOcclusionQuery->GetData( ) 함수를 통해 얼마나 픽셀충돌이 이뤄졌는지를 알 수 있습니다.

 - 반환 형은 DWORD 값! ( 충돌한 픽셀 사이즈 입니다 )



11. 그 외 디바이스 처리( 릴리즈 / 리셋 )

 - 아래 3개의 함수는 우리가 위에서 만든 Device가 로스트 되거나 release를 할 시

사용 되는 함수들 입니다.


 - 첫 번째 getDeviceState() 함수는 호출 시 Device가 갑자기 뒤져버렸을 때 다시 device를 reset 시킬 수 있는지 여부를 알아 낼 수 있습니다.

 - 주로 전체화면 중에 갑자기 AltTab을 하다가 버벅버벅 거리던 중 화면이 까맣게만 되고 아무것도 안나오는 게임화면을 보신 적이 있을 겁니다. 그와 같은 경우에 이 함수를 이용하여 Device를 다시 얻어 낼 수 있는지 여부를 확인 할 때 사용합니다.



 - 두 번째 releaseAll() 함수는 호출 시 Device에 담아두었던 모든 내용들을 해지 시키는 내용뿐입니다.

 - safeRelease( )는 템플릿 형태의 매크로로 만들어둔 내용입니다.



 - 세 번째 reset()

 - reset 함수는 위의 getDeviceState() 를 통해 device가 다시 reset 될 수 있는지 여부를 알아 낸 후 호출되는 함수 입니다.

 - 다시 initD3Dpp() 함수를 통해 디바이스 모드를 재설정하고

 - sprite->OnLostDevice() 함수를 통해 sprite를 release 한 뒤,

 - device3d -> reset( ) 함수를 작동시킵니다. ( 요기서 이제 우리의 DirectX Device가 리셋~)

 - 다시 재기동 된 device의 renderState 값들을 재설정 해주고 혹여나 충돌 처리에서 썼던 값 또는 sprite를 박아두었던게 있다면 reset시켜 줍니다.




간추리고 요약해보려고 해도 이건 뭐 정리할 게 너무많아서 쉽지가 않은 것 같습니다.


Graphics.cpp 에 대한 내용은 워낙 방대한지라 기본적으로 알고 와야지 이해할 수 있을 법한 내용들이 많습니다.


따라서 독자 분들이 먼저 DirectX에 대해서 선행 한 뒤에 구독하시는 게 Graphics 클래스의 구조를 이해하시는데 도움이 될 거라 생각됩니다.



귀찮으면 그냥 graphics.h graphics.cpp 파일 복붙 해서 그냥 써버리세요.

솔직히 저도 다시 정리하면서 봐도 뭐가 뭔지 모르겠습니다. ㅡ,   . ㅡ;;귀찮아서 그냥 복붙하고

 쓰고말지...


중요한 것은 우리가 이 Graphics 클래스를 통해 directX Device에 대한 설정을 하나의 객체로 빼고 쓴다는 점입니다. 이게 어떻게 돌아가는지 하나하나 다 파고들려면 암걸려요. 암.



Graphics.cpp 파일의 전체 내용은 아래와 같습니다.


[GitHub - June_Engine Project : Graphics.cpp]


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]


posted by REDFORCE 2017. 3. 12. 18:01

본 프로젝트의 개발 일지 및 프로젝트 상세 내용을 작성 함에 있어

구어체의 사용이 있음을 미리 알려드립니다.


[System Architecture]


2D Game Engine을 만들기 위해

In Game 용도의 FrameWork 자체는 필요한 부분에 한해서는 다 완성이 되어 있는 상태입니다.


예) Graphics, Game, Entity, Collision, Manager Class 등


그러나 엔진으로써의 구동을 위한 핵심 코어 시스템은 섣불리 만들기가 어려운 상황입니다.

[글쓴이 저자가 너무 됻밥이라...(시무룩)]



현재 구상해본 구조는 핵심부분만 보자면


WinMain -> Engine System Initialize -> Engine Core Start 

-> Engine Window System Initialize -> Engine Graphics -> Run Loop


입니다만


Engine Window System을 설계하는 것과 


목표인 2개의 화면.

Engine Scene / Engine Game


에 Graphics를 올리고 Run을 시키는 구조를 잡는게 너무 어려운 것 같습니다.


Graphics를 2개를 잡아서 올리자니 비효율적인 것 같고


1개의 Graphics만 갖고 2개의 화면에 띄우는 작업을 하려니



Scene에서의 화면은 엔진 사용자가 이리저리 움직이며 다양한 컴포넌트들을 올리면서 에디트가 가능해야하고


Game에서의 화면은 엔진에서 빌드를 수행했을 시 인게임컨트롤을 통한 화면움직임이 이루어질텐데

([예] Unity3D Scene / Game화면)


말이지요.


이게 현재 겪고 있는 첫 번째 난관입니다만



일단 각각의 HWND 화면을 하나의 Graphics에서 정보를 가져와서 렌더링 할 수 있는 구조와 방법을 생각해 봐야겠습니다.



이 문제가 해결 된다면


수정해서 해결한 방안을 적어보도록 하겠습니다.