- MicroSoft는 마이크로스프트사의 등록상표입니다.

- Direct X는 마이크로스프트사의 등록상표입니다.

- 이외에 여기서 사용된 대부분의 용어는 등록된 상표임을 알려드립니다.

MicroSoft DirectX 2

Software Development Kit

Hangul Reference Guide

written by Jae Eun, Choi

Index

Chapter 1. 다이렉트 X의 세계로 들어가보자.

-> 다이렉트 X에 대한 소개와 각 구성요소에 대한 개관이 실려 있다.

Chapter 2. 다이렉트 드로우를 알면.

-> 다이렉트 X중 가장 기본이 되는 DirectDraw에 대한 각종 정보와 사용법 그리	고 함수에 대한 기본적인 정보가 들어가 있다.

Chapter 3. 윈도우즈 프로그래밍을 모르시는 분들을 위하여

-> 윈도우즈 프로그래밍을 모르시는 독자를 위하여 약간의 가이드를 마련하였	다.

.

.

# 저자는 이글을 하이텔 게오동안에서의 공개만을 전제로 이글을 공개 합니다. 이글의 상업적 이용을 금합니다. 또한 이글을 무단으로 변경하는 것은 금합니다. 기타 자세한 내용은 HITEL : SWSC2로 문의 하시면 됩니다.

# 이글에 대하여 :  이글은 순전히 개인적인 목적으로 만들어진것입니다. 따라서 연재의 성질을 가지지 않았습니다. 저는 아직 프로그래밍을 공부하는 학생이고 단지 다이렉트 X에 대해 배우고자 다이렉트 X2의 영문 매뉴얼을 읽고 다시 나름대로의 정리를 함으로써 공부를 하고 있습니다. 능력이 되는한 DirectDraw에관해서는 공부를 마치려 합니다(이는 Direct3D와 DirectPlay에 관해서는 언급이 없음을 의미합니다). 혹시 저와 같이 공부를 하시려는 분이 계시면 위의 아이디로 연락을 주십시오.

Chapter 1. 다이렉트 X 의 세계로 들어가 보자.

1. 다이렉트 X를 사용해야 할 이유?

먼저 다이렉트 X 는 마이크로 소프트사 윈도우즈에서 높은 성능을 프로그램에 부여하기 위해 만들어진 것이다. 즉 하드웨어에 대한 저수준에 가까운 제어가 가능해짐으로서 그동안 윈도우즈에서의 게임 개발을 기피하던 개발자들에게 새로운 길이 열리었다고 볼수 있다.  다이렉트 X 의 기능은 이러한 하드웨어의 저수준제어와 윈도우즈의 고수준(?)제어와의 중간 매개체 역할을 하는 정도로 알면 되겠다. 8088시절부터 지금 까지 줄곧 사용되어왔던 MS-DOS는 그리 뛰어난 성능을 가지지 않은 OS임에도 불구하고 게임개발의 플렛폼으로 사용되어져 왔다. 하지만 MS-DOS에서의 프로그래밍은 하드웨어의 직접제어가 가능했고 시스템의 독점적 사용으로 빠른 속도가 가능했다. 그렇지만 이러한 장점뒤에는, MS-DOS에서 게임 개발은 프로그래머의 많은 노력이 들어야만 했다. 하지만 요즈음 MS-DOS프로그램이 거의 최고조에 이른 시기에서 이말은 약간의 문제가 있긴하다. 이미 수많은 안정적인 라이브러리가 만들어져서 공개 또는 판매되고 있고 실제로 이들의 성능은 무시못할 만큼 뛰어나다. 앞으로 윈도우로의 게임 플렛폼 전이로 얻을수 있는 이익은 어느정도일까? 결국은 단지 사용자에게 좀더 친숙한 환경을 제공하자는 취지와 더불어 시스템의자원을 최대한 활용하자는 것인데, MS사에서 선전하는 만큼 과연 기대를 할수 있을지는 앞으로도 두고봐야 할 일인거 같다.

이글은 다이렉트 X에 대해 기본적인이해를 위해서 입니다. 하지만, 글이 아주 추상적이어서 이해에 어려움이 오신다면 그 부분은 과감히 넘어가십시오. 아직 시작도 하지 않았는데 막혀선 안될 것 같아서... 암튼

2.  다이렉트 X 의 구성요소

다이렉트 X 의 구성요소는 크게 4가지로 나뉘어진다. IDrectDraw, IDirectDrawSurface, IDirectDrawClipper, IDirectPallete로 이루어지는  다이렉트 X 는 이들을 Component Object Model(이하 COM이라 말함) 락 일컫는다. 이제 Direct X를 구성하는 오브젝트들에 대한 간단한 설명으로 마치려 한다.

1. DirectDraw

다이렉트 X 에서 가장 기본적인 요소임과 동시에 가장 중요한 요소를 꼽으라 하면 이 DirectDraw를 꼽아야 할 것이다. 이러한 것은 아마도 도스에서 가장 기본적이고 중요한 요소를 꼽으라 하면 점찍기와 같은 것을 꼽는것과 마찬가지이다.

DirectDraw의 오브젝트는 DirectDrawCreate에 의해 생성된다. 또 IDirectDraw::CreateSurface가 있는데 이는 가상페이지를 생성하는것이라 보면된다. 이러한 방법은 가상 페이지를 생성해놓고 실제 화면이 보여지는 동안 가상페이지에서 작업을해놓고 다시 이를 실제화면에 보여주기 위해 사용된다. 이러한 사용법 역시 기존의 게임 개발자에게는 익숙하리라 본다. 만약 이에 대한 좀더 자세한 이해가 필요하다면 죄송하지만 다른글을 읽어 보는게 좋으리라 생각된다. 이글은 적어도 게임을 한 번쯤 개발한 사람들에게 맞게끔 쓸 작정이기 때문이다. 가상페이지와 함께 중요한 것은 바로 페이지 플리핑이다. 이는 IDirectDrawSurface::Flip이라는 함수가 존재함으로써 해결된다. Flip함수는 화면의 수직 복원때 작동한다. 따라서 이함수는 실행이 되더라도 즉시 그 효력을 나타내지 않는다. 스노우 현상 때문에 골치 아픈적이 있는 분에게는 좋은 소식이 될듯하다.

앞에서 말한적이 있는 DirectDraw의 구성 요소를 살펴보면 DirectDrawPallete라는 것이 있다. 이 것은 일반적으로 윈도우즈 어플리케이션이 가상으로 만들어진 펠릿을 사용하는 반면에 하드웨어의 펠릿을 직접 제어하게 해주는 요소이다. DirectDraw중 마지막으로 DirectDrawClipper라는 요소가 있는데 이는 클리핑 처리를 도맡아 하는 오브젝트라 보면된다.

Direct X는 직간접적으로 많은 처리를 한다. 이중 필자에게 가장 돋보이는 기능중 하나가 바로 하드웨어적인 지원이다. 만약 여러분들이 가진 비디오카드나 이외의 여러 가지 지원카드중 좀더 빠른 처리를 위한 장치가 있다면 DIrect X는 소프트웨어적인 처리보다는 이를 사용함으로써 좀더 빠른 속도를 보장한다. DirectDraw에서는 비트멥의 투영처리를 예를들 수 있겠는데 도스에서는 스프라이트처리와 같다고 보면 된다.

2. DirectSound

여러분들은 혹시 둠이나 헤레틱, 디센트, 퀘이크를 해본적이 있는가? 이들 게임은 필자가 해본게임중 사운드 효과가 가장 뛰어나다고 생각되는 게임이다. 다른 게임들도 해보았지만 이같이 현장감있는 사운드는 들을수 가 없었다. 그렇다. 좋은 게임이 되기 위해서 필요한 요건중하나가 바로 사운드이다. 윈도우즈에서는 사운드을 위해서 기본적으로 많은 함수들을 지원한다. Direct X에서도 사운드를 위한 오브젝트를 지원하는데 바로 DirectSound이다. 미디출력에 관해서는 DirectX가 지원하는 사항이 아니고 윈도우즈의 멀티미디어 시스템이다. 이에 대해서는 다른 윈도우즈 강좌를 살펴보도록 한다. 다른 다이렉트 X의 구성요소와 마찬가지로 DirectSound는 하드웨어적인 지원과 그것이 불가능할시에는 소프트웨어적인 예뮬레이션을 지원한다.

DirectSound는 서로다른 두가지의 셈플사운드를 믹싱또는 출력이 가능하게 해준다. 또한 사운드 오브젝트의 설정시에 사운드카드에 대한 자세한 정보를 얻을수 있음으로서 좀더 효과적인 프로그래밍을 가능케 할수 있울것이다.

DirectSound는 2가지의 구성요소(COM)에 기반을 두고 있는데,IDirectSound와 IDirectSoundBuffer이다. 먼저 IDirectSound는 다양한 사운드카드의 상황과 사운드카드을 반영하고 있다. 다음 IDirectSoundBuffer는 사운드 데이터를 가지고 있는 버퍼를 가르킨다. 그럼 다이렉트 사운드의 버퍼는 어떻게 만드는지 간단하게 알아보자. 다이렉트 사운드의 버퍼의 생성은 IDirectSound::CreateSoundBufffer에 의해 생성이 된다. 또한 이에 의해 생성된 오브젝트는 여러개가 만들어질수 있으며 primary사운드 버퍼로 보내어져 두 개의 버퍼가 믹싱이 될 수도 있다. 그외에 사운드 버퍼는 다양한 형태로 존재할수 있다(원문 : can exist hardware as onboard RAM, wave table Memory, DMA, Virual buffer). 그러나 만약 다이렉트 사운드 버퍼를 위한 하드웨어가 없다면 시스템메모리에 에뮬레이트된다.

주 사운드 버퍼는 여러 가지 용도로 사용될수 있는데, 이를 살펴보면 보조 사운드버퍼의 믹싱과 그외 특정한 기능을 위한 용도로 사용됩니다. 단 주 사운드 버퍼(primary)를 사용할 경우에는 주의할점이 있는데 lock을 걸어 버리면 다른 source에서의 하드웨어 접근이 어려워지기 때문입니다.

보조 사운드 버퍼(secondry sound buffer)는 사용가능한 사운드 버퍼 메모리보다 큰 사운드를 플레이가 가능합니다. 이를 위해서는 사운드 버퍼를 큐에 올려놓고 하는 방법이 있습니다.

3. DirectPlay

다이렉트 X에서 네트워크를 지원하기 위한 구성요소입니다. 하지만 윈도우즈의 네트워크는 아직 미흡한점이 많아 보이고 많은 사용자를 끌어들이기 위한 준비가 되지 않았다고 필자는 생각한다.

이 말이 별로 안 믿긴다면 지금 당장 윈도우즈에 다이렉트 케이블 연결을 설치해보라. 필자는 설치하는데 무려 하루밤을 세웠다.

4. Direct3D

다이렉트 X에서 신개념의 기술을 위한 실시간 3차원 기술이다. 아마도 DirectX와 함께 제공되는 예제를 보면 알겠지만 상당히 뛰어난 3차원 엔진이다. 많은 개발자들이 DIrectX를 원하는 이유도 바로 이것때문이라는 말이 있을정도이다.  Direct3D는 아직은 윈도우즈 95에서만 지원이 될뿐 윈도우즈 NT에서는 지원이 되지 않는다고 한다.

5. DirectInput

조이스틱을 사용하기 위한 구성요소이다. 관련된 함수로는 joyGetPos, joyGetPosEx가 있다.

6. AutoPlay

필자는 윈도우95가 나올 때 KOEX에서 열리는 소프트웨어 전시회에 간적이 있었다. 마침 MS사의 부스에는 예쁜 나레이터걸이 퀴즈쇼를 진행하고 있었다. 필자는 잠시도 주저 않고 가서 구경을 했다. 그런데 참 우스꽝 스러운 일이 있었다. 윈도우의 장점을 이야기 하라는 문제에서 어느 사람이 32bit운영환경으로인한 안정적인 동작에 자동실행, Plug & Play를 자랑사럽게 대답하자 정답이 아니란다. 정답은 빠르다. 새롭다. 어쩌구 저쩌구, 물론 자세한 지식이 없는 나레이터걸이 무슨 잘못이겠는가마는 국내 최대의 행사에서 이런일이 있다는건 좀 우습다. 암튼 윈도우의 장점중인 하나인 AutoPlay는 DirectX와는 크게 상관은 없다. 하지만 게임을 하려는 많은 사람들중에는 게임을 어떻게 설치하는지도 모르는 사람이 없진 않을 것이다. AutoPlay를 사용하며는 CD-ROM에 꼭 윈도우95로고가 있어야 한다.

3. 다이렉트X와 그의 구성요소(Component Object Model. (COM))

다이렉트X에서의 많은 API들은 COM(Component Object Model: 이하 COM이라 칭함)에 기반을 둔 것들이다. COM은 인터페이스의 제사용이라는 것에 기반을 두고 제작되었으며 사실상 OLE 프로그래밍에 그 본질이 있다고 할수 있겠다.

DirectX에서의 많은 API들은 OLE 오브젝트와 같이 예가 들어진다. 오브젝트는 하드웨어 또는 대화를 필요로 하는 어플리케이션을 위한 인터페이스라고 보면 된다. 이건 사용자가 COM인터페이스에 명령어를 보내고 COM이 이를 대신 수행해주는 것이다.

오브젝트는 또한 다른 오브젝트와 실시간으로 묶여질수가 있으며 또한 다른 오브젝트의 결과를 이용할수 있다.

1. IUnknown

모든 COM 인터페이스는 바로 이 IUnknown 인터페이스에서 유도 되었다. IUnknownd인터페이스는 수많은 다른 DirectX 오브젝트의 콘트롤의 확보와 여러 인터페이스와의 통신을 위한 능력을 가지고 있다. IUnknown은 단지 3개의 접근 방법만을 가지고 있는데 그것은 다음과 같다.

AddRef  : 어느 한 인터페이스나 어플리케이션이 오브젝트와 결합시킬 때 reference count를 1씩 증가 시킨다.

Release : Addref와는 반대로 reference count를 감소 시킨다. 최종적으로 reference count가	0이 된다면 오브젝트는 해제된다.

QueryInterface	: 어느 특정 인터페이스에 대한 포인터의 지원하는 특징에 관해 알아본다.

여기서 Addref와 Release는 reference count라는 것을 가지고 있다. 예를 든다면, 여러분들이 다이렉트 서페이스 오브젝트(DirectSurfaceObject)를 생성해낸다면 바로 이 reference count가 1이 되게 되고 그와 동시에 인터페이스는 여러분들이 생성한 오브젝트의 포인터를 함수는 반환하게 되는 것이다. 또 함수는 항상 먼저 Addref를 통해 reference count를 증가시킨후에 사용되어진다.

당연하겠지만 모든 Addref와 Release는 같은수 만큼 존재해야 한다. 역시 포인터를 파괴할 경우 이를 먼저 호출해야만 한다. Release로인해 만약 reference count 가 0이 된다면 오브젝트와 불필요한 모든 인터페이스는 해제된다는 것을 알고 있어야 한다.

2. DirectX의 개발을 위한 인터페이스들

다이렉트 X의 SDK의 인터페이스는 COM프로그래밍의 계보에서 가장 기본적인 수준에서 제작되었다. IDirectDraw, IDrectSound와 같은 인터페이스 오브젝트는 OLE의 IUnknown에서 유도된 것이다. 전형적으로 COM오브젝트를 생성하기 위해서는 Win32의 CoCreateInstance함수보다는 DLL의 좀더 전문화된 함수들로 기본적인 오브젝트를 생성한다.

일반적으로 다이렉트 X를 사용하다보면 다이렉트X의 오브젝트는 한가지장치만을 가르키는 오브젝트를 가지는게 아니라 여러개의 장치의 오브젝트를 함께 가질수 있다. 이는 간단히 IDirectSurface오브젝트가 단지 비디오램의 정보만을 가져서 되는 것이 아니고 화면 펠릿에 대한 오브젝트인 IDirectPallette오브젝트 역시 포함하고 있어야함을 가르키는 것이라 보면 좋은 예가 될 수 있을 것이다. 또다른 예를 들어본다면 DIrectSound또한 포함 될 수 있다.

3. C++사용자와 COM인터페이스와의 연결

여러분들이 주지하여야 할 사항은 C++에서의 COM인터페이스는 바로 추상적인 베이스 클레스와 같다고 볼수 있다는 것이다. C++에서의 추상적인 클레스는 모든 수단이 순수한 가상함수이라는 것이고, 이는 이들 가상함수와 아무런 코드도 연관되어 있지 않다는 것을 의미한다. 필자는 아직 C++을 공부하는 중이라 여기에 대해 더  자세한 설명이 부족함을 죄송하게 생각한다. 여러분들은 개인적으로 C++가이드 책한권쯤은 보았으리라고 생각한다. 그렇지 않고서야 어떻게 감히 거대한 클레스 덩어리인 MFC와 같은 윈도우즈 프로그래밍을 배울생각을 하겠는가?

C++의 pure virtual 함수들과 COM 인터페이스는 둘다 vtable이라는 디바이스를 사용한다. 이 vtable이라는 것은 주언진 인터페이스에대한 모든 함수의 주소를 가지고 있는 것이다. 이해를 돕기 위해서, 이들 함수를 사용하기위해서는 QueryInterface를 인터페이스의 주소를 얻기위해 사용할수 있는 것이다. 참고로 프로그램이나 오브젝트가 QueryInterface를 통해 받는 것은 바로 vtable의 주소인 것이다. 이러한 구조는 오브젝트에의해 사용되는 private데이터와 client access와의 관께를 끊기 위한 것이다.

마지막으로 COM 오브젝트와 C++오브젝트의 비슷한점은 사용법에서 첫 번째 인자값이 인터페이스 또는 클레스의 이름이 올수 4있다는 것이다. 사실 C++의 클레스와 COM 오브젝트는 이진코드가 서로 호환이 되기 때문에 컴파일러는 이를 C++의 추상적인 클레스로 이해해 버리며 동시에 같은 구문으로 취급해 버린다. 이러한 취급의 결과로 복잡한 코드를 많이 줄이는데 기여를 하게 됨은 물론이다. 즉 COM 오브젝트는 C++의 클레스와같이 취급되므로 사용이 간편하다는 얘기다.

4. C를 사용한 COM오브젝트의 접근

그럼 C를 통해선 어떻게 COM오브젝트를 사용할까? 먼저 모든 COM 인터페이스의 사용은 C를 통해 사용되어질수 있다. 단지 이를 사용할때에는 다음의 두가지 사항만 기억해두면 된다.

- 첫 번째 파라미터는 항상 그와 관련된 만들어진 오브젝트(this인자) 의 리퍼런스이어야 한다.

- 각각의 인터페이스 method는 오브젝트 vtable에 의해 참조되어야 한다.

다음은 여기에 대한 예제이다. 여기서는 다이렉트 오브젝트를 CreateSurface를 통해 생성하는 과정을 C로 표현한 것이다.

ret = lpDD->lpVtbl->CreateSurface(lpDD,&ddsd,&lpDDS,NULL);

DirectDraw 오브젝트는 파라미터 lpDD를 참조해  새로운 Surface를 만들어낸다.

가끔 이러한 method는 surface에 관해 descipt된 스트럭쳐 ddsd를 채워 새로운 surface(lpDDS)를 만들어야할 필요가 있음은 물론이다. 만약 위의 함수에 대해 좀더 자세한 설명이 필요 하다면 리퍼런스를 참조하도록 한다.

IDirectDraw::CreateSurface를 호출키 위해서는 여러분은 먼저 DirectDraw 오브젝트의 vtable을 참조하도록(dereference) 해주어야 한다. 다음에 method의 vtable을 참조토록 해주면된다.

COM 오브젝트의 사용에 있어서는 C와 C++에는 미묘한 차이가 있다. 이들을 보여주기 위해서 다음예제가 있다. 위의 예제와 비교해보기 바란다.

ret = lpDD->CreatSurface(&ddsd,&lpDDS,NULL)

여기서의 차이가 나는 이유는 C++의 함축적기능에 의한 것으로 this포인터와 vtable에 관한 처리를 내부적으로 처리케 하여준다.

5. 인터페이스의 사용법과 구문

앞으로는 모든 COM오브젝트를 C++의 클레스와 같이 취급하는 것이 좋을듯하다. 또한 DirectX의 원문에도 같은 내용으로 표기한다고 하였으므로, 모든 COM오브젝트를 C++의 클레스 이름으로 사용하도록 하겠다. 또한 대부분의 개발자들이 다이렉트 X와 비쥬얼 C++을 사용한다고 가정하였으므로 C보다는 C++을 위주로 하는 것이 바람직하도 생각되기에 C++을 대상으로 하겠다.

C++에서는 바로 앞에서 보여주었듯이  this의 pointer를 포함할 필요가 없다. 다시 예를 들어 보인다면

HRESULT GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps);

또 같은 예를 C의 문법으로 보여 준다면

HRESULT GetCaps(LPDIRECTDRAW lpDD, LPDDCAPS lpDDDriverCaps, LPDDCAPS, lpDDHELCaps);

여기서 lpDD파라미터는 다이렉트 드로우 오브젝트를 가르키는 포인터이다.

6. 메크로 정의의 사용

항상 그렇듯이 DirectX의 헤더 파일도 각각의 Method에 대해 수많은 메크로정의를 가지고 있다. 이러한 메크로의 사용은 각각의 method의 사용에 편리함을 주는 것은 당연한 것이다. 다음의 예제는 IDirectDraw_CreateSurface메크로를 사용하는 과정방법을 보여준다.

ret = IDirectDraw_CreateSurface(lpDD, &ddsd, &lpDDS, NULL);

이에 대한 리스트를 얻고 싶다면 직접 헤더파일을 참조토록 한다.

7. 부동 소숫점

DIrectX의 구조는 부동 소숫점을 53까지의 정밀도를 가진다. 하지만 응용프로그래에서 이를 변경할 필요가 있을 경우에는 변경이 가능하다. 여기서 주의해야 할점은 항상 변경후에는 원래의 값으로 되돌려놓는 것을 잊어서는 안된다는 것이다.