1. 개관

DirectX 8.1을 이용한 DirectDraw로 무언가를 만들어 보자.

11기 이선호 입니다.

극히 개인적인 문서가 될것 같네요.

DeleteMe 나도 껴줘~~~ - 인수

2. DirectX 8.1 SDK

까는데 어려움이 조금 있었다. 설정할 부분이 있기 때문에.

Visual C++ -> Tools -> Options -> Directories에서

Include Files 에는 C:\DXSDK\INCLUDE를

Library Files 에는 C:\DXSDK\LIB를 추가해야한다.

그리고 Project Setting -> Link -> Object/Library modules에는
ddraw.lib와 dxguid.lib를 추가해야한다.

그리고 소스파일의 앞부분에
#include <ddraw.h>
를 추가해야한다.

3. DirectDraw의 과정(?)

소스를 쳐보면서 느낀 점이다

DirectDraw객체의 생성 -> 표면의 생성(Front, Back, OffScreen) -> 그리고.. 표면 뒤집기..

중간중간 더 중요한 내용이 있을 것이다.

4. Source

4.1. 초기화

4.1.1. DirectDraw객체의 생성

~cpp 
HRESULT hr
LPDIRECTDRAW7 lpDD;
hr = DirectDrawCreateEx(NULL, (void **)&lpDD, IID_IDirectDraw7, NULL); // DirectDraw객체를 생성
if(hr != DD_OK) return 0;
hr = lpDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN); // 화면의 레벨을 설정
if(hr != DD_OK) return 0;
hr = lpDD->SetDisplayMode(640, 480, 8, 0, 0);
if(hr != DD_OK) return 0;
  1. SetCooperativeLevel의 인자.
    • DDSCL_ALLOWMODEX : ModeX를 사용 가능하게 해준다는데. 알수 없다.(예전에 쓰던 화면 모드라고 한다.)
    • DDSCL_ALLOWREBOOT : Ctrl+Alt+Del을 사용 가능하게
    • DDSCL_EXCLUSIVE : 독점 모드를 사용 가능하게, DDSCL_FULLSCREEN 과 함께 쓰인다.
    • DDSCL_FULLSCREEN : 풀스크린 모드
    • DDSCL_NORMAL : 보통의 윈도우 어플리케이션
    • DDSCL_NOWINDOWCHANGES : 최소화/최대화를 허용하지 않는다.
  2. SetDisplayMode의 인자.
    • 640 : 가로해상도
    • 480 : 세로해상도
    • 8 : 색생 (bit수, 8은 256컬러, 16은 High컬러)
    • 0 : Refresh Rate, 0은 디바이스 기본값 (대개 0으로 놓는다.)
    • 0 : 안써요

4.1.2. DirectDraw Front 표면의 생성

~cpp 
LPDIRECTDRAWSURFACE7 lpDDSFront;
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd); // 크기를 저장
ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT; // 구조체와 backbuffercount를 사용가능
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX; // 1차표면, 플립가능
ddsd.dwBackBufferCount = 1; // 2차표면의 개수
hr = lpDD ->CreateSurface(&ddsd, &lpDDSFront, NULL); // 생성!
if(hr != DD_OK) return 0;
  • ddsd의 변수들
    • dwSize : ddsd의 크기가 들어갑니다.
    • dwFlags : ddsd의 성격에 대해 들어가는 부분입니다.
    • ddsCaps.dwCaps : 더 자세한.. 성격..
    • 그리고 기타 변수들. : dwFlag에서 결정해준 성격들의 변수를 정해줍니다.

4.1.3. DirectDraw Back 표면의 생성

~cpp 
LPDIRECTDRAWSURFACE7 lpDDSBack;
DDSCAPS2 ddscaps;
ZeroMemory(&ddscaps, sizeof(ddscaps)); // 메모리 초가화
ddscaps.dwCaps = DDSCAPS_BACKBUFFER; // 2차표면
hr = lpDDSFront->GetAttachedSurface(&ddscaps, &lpDDSBack); // 1차표면과 접합(같은 속성의 표면을 생성)
if(hr != DD_OK) return 0;
lpDDSBack->AddRef();

4.1.4. DirectDraw OffScreen의 생성

~cpp 
LPDIRECTDRAWSURFACE7 lpDDSOff;
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH; // 높이와 넓이를 지정할 수 있음
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; // 오프스크린임을 표시
ddsd.dwHeight = 16; // 높이
ddsd.dwWidth = 16; // 넓이
hr = lpDD->CreateSurface(&ddsd, &lpDDSOff, NULL); // 표면 생성!
if(hr != DD_OK) return 0;

4.2. BMP Resource를 화면에 뿌려보자!

일단 HBITMAP형의 비트맵을 얻어와야한다.
~cpp 
HBITMAP hb;
hb = (HBITMAP) LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP), IMAGE_BITMAP, cxDesire, cyDesire, LR_CREATEDIBSECTION);
  1. 핸들을 얻어온다.
  2. 리소스의 ID를 형에 맞게 고쳐준다.
  3. BITMAP은 IMAGE_BITMAP을.
  4. 가로의 넓이
  5. 세로의 넓이
  6. ㅡ.ㅡ?
이걸로 BITMAP형을 얻는다.
~cpp 
BITMAP bmp;
GetObject(hb, sizeof(bmp), &bmp);
bmp.bmWidth 와 bmp.bmHeight로 비트맵의 크기를 얻어낼 수 있다.
~cpp 
LPDIRECTDRAWSURFACE7 lpDDS = NULL;
DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof(ddsd);
lpDDS->GetSurfaceDesc(&ddsd);
HDC hDC;
HDC hImageDC;
lpDDS->GetDC(&hDC);
hDCImage = CreateCompatibleDC(NULL);
SelectObject(hImageDC, hBMP);
StreachBlt(~~);
lpDDS->ReleaseDC(hDC);
DeleteDC(hImageDC);
이런 구조이다. imagedc에 먼저 그림을 뿌리고 그것을 hdc에 그린다.

일단 bmp파일을 찍기 위해서는
  1. bmp파일을 surface에 찍는다. (위와 같은 방법으로)
  2. Blt나 Blifast를 통해서 BackSurface에 찍는다.
  3. 그것을 Flip한다.
  4. 그러면 그것이 FrontSurface에 찍혀서 화면에 보이게 된다.
소스를 보고 내린 결론.

4.3. 결론

이론만 익혀놓고.. sdk 에 포함되어 있는..
ddutil.h ddutil.cpp dxutil.h dxutil.cpp 만 있으면.. 비트맵은 그냥 찍을 수 있군요..

ㅡ.ㅡ 뭐.. 그 소스를 뜯어 고칠만한 건덕지도 없군요.. 워낙 잘되어 있어서.

거기서 필요없어보이는것 줄이고 쓸만한거만 추려서.. 새로.. 만들어보던지만. 해야겠네요.

DirectDraw가.. 필요없다는 소리를 이제 .. 알거같아요

쿨럭. 그럼.. API에 대해서 공부해 봐야겠네요

4.3.1. Thread

영현 유용성을 위해.. 뒤에 나오는 7이나 2는 빼라.. ㅡㅡ; 하하..

선호 그래도.. 8.1 깔은 김에..ㅡㅡ;

해성 지나가다가 한마디.. ^^;; DX 초기화 과정은 이전버전과 흡사하군요.. 음.. 초기화 인터페이스를 파악했다면.. 다이렉트 엑스가 어떻게 내부적으로 작동해서 일반 윈도우 프로그래밍 보다 빠른 엑세스 메카니즘을 제공하는지 파악하시구요.. 왠만하면 DX 쓰지말구.. 추가적인 이펙트등을 구현해보는게 좋을것 같네요.. 알파블렌딩을 응용한 여러가지 기법(페이드 인아웃이나 전환.. 뭐라그러드라).. 하구.. 전 못해봤지만.. 블러링 필터 같은것두.. 서페이스에 직접 억세스 하는거 공부하면.. 해볼만 할것 같군요.. 그리구.. 음.. 매일 허접 플밍을 하구 있지만.. 그래두 지겨운 초기화 과정을 단축시키기 위해 어느정도 모듈화되게 라입을 구축하면 좋겠지요.. 전 절대 안하지만.. ㅋㅋ;; 그럼.. 잡설이었습니당~ 수거~

1002 초기화과정이 이전버전과 같은 이유는 Surface 7 을 이용해서일것 같다는. DX8로는 아직 안해봐서..~

데기) 해성이가 말한 추가적인 이펙터들의 기본적인 아이디어는 '영상처리' 시간에 배울 수 있습니다. (선호 혼자 DX 보는데도 의외로 진도가 잘 나가는듯...)

1002 Output 이 급하다면 DirectX Media SDK 를 이용할 수도 있습니다. 알파블랜딩 기본적으로 지원합니다. 그리고 Transform Libary 를 이용하면 화면 전환과 관련된 특수효과들을 이용할 수도 있죠. 하지만, 공부하시는 입장에서는 이론을 파고들어서 직접 해보는 것이 좋겠죠.

해성 가만보니 .. 99들이 감놔라 배추놔라 하구 있군.. -0-;;; ㅎㅎ;;

DeleteMe) DX8 SDK문서를 보니 Direct Draw의 전 기능이 Direct3D로 통합 됐다는군.... 고로 DDraw는 이제는 의미가 퇴색한듯.. 쿨럭;; by 봉환(비회원 참견꾼)

선호 뭐.. DirectGraphics로 통합되었다고 하지만 아직 예전의 기능들은 전부 남아있고 영원히 2D를 안하는 것은 아니기 때문에. 뭐 2D를 3D를 통해 표현하는 기법들만 요새는 소개되고 있어서 안타깝기도 하지만.^^



Retrieved from http://wiki.zeropage.org/wiki.php/DirectDraw
last modified 2021-02-07 05:23:08