Transcript DirectX 9

Ch1. Direct3D 초기화
목표
 Direct3D가 그래픽 하드웨어와 상호작용하는 방법
 Direct3D에서 COM의 역할 이해
 2D 이미지가 보관되는 방법, 페이지 플리핑, 깊이 버퍼
링 등과 같은 기본적인 그래픽 개념
 Direct3D를 초기화하는 방법
 이 책의 예제 애플리케이션에서 이용하고 있는 범용적
인 구조에 익숙해진다.
1.1 Direct3D 개요
 Direct3D는 3D 가속 하드웨어를 이용하여 3D를 표현
하는 저수준 그래픽 API
 Application, Direct3D, 하드웨어 간의 관계
Application
Direct3D
HAL
Graphic
device
 HAL(Hardware Abstraction Layer) : 장치로 하여금 특별
한 작업을 수행하도록 하는 장치 고유의 코드



Direct3D가 각 장치의 세부적인 부분을 제어할 필요없게 함
하드웨어 장치에 독립적인 규약 확립이 가능
HAL에서 구현하지 않은 Direct3D함수 호출시 에러 발생
1.1 Direct3D 개요
 REF 장치
 모든 Direct3D API를 소프트웨어로 애뮬레이트하는 레
퍼런스 래스터라이저를 제공
 순수한 개발 목적으로 제공
 D3DDEVTYPE
 HAL 장치는 D3DDEVTYPE 열거형 멤버인
D3DDEVTYPE_HAL로 지정
 REF 장치도 D3DDEVTYPE_REF로 지정
 장치를 만들 때 어떤 타입을 원하는지 지정해야함
1.2 COM
 COM(Component Object Model) : DirectX를 프로그래밍






언어에 독립적으로 만들어주고 하위 호환성을 갖출 수 있
게 하는 기술
COM객체 = 인터페이스,C++ 클래스와 비슷하게 이용
다른 COM 인터페이스의 메서드나 특수한 함수를 통해
COM 인터페이스의 포인터를 얻음
C++new키워드로 COM인터페이스 만드는 것이 아님
인터페이스를 이용한 작업이 모두 끝나면 인터페이스의
Release 메서드를 호출
COM객체가 자신의 메모리 관리를 스스로 수행
COM의 정의 : http://terms.co.kr/COM.htm
1.3.1 표면(surface)
 Direct3D가 주로 2D이미지 데이터를 보관하는데 이용




하는 픽셀의 행렬
실제 픽셀 데이터는 선형 배열에 보관
표면의 너비와 높이는 픽셀 단위로 계산
피치는 byte로 계산, 하드웨어에 따라 너비보다 길수
있음
피치 = 너비 x sizeof(pixelFormat)이 아닐수 있음.
1.3.1 표면(surface)
 IDirect3DSurface9 인터페이스 사용
 LockRect – 표면 메모리로의 포인터 제공. 약간의 포인터 연산을 거치면 표면 내의
각 픽셀을 읽고 쓸 수 있음
 UnlockRect – LockRect를 호출하고 표면 메모리에 대한 작업이 끝난 뒤에는 호출하
여 표면의 잠금을 해제
 GetDesc – 표면에 대한 정보를 D3DSURFACE_DESC 구조체를 통하여 얻음
// _surface가 IDirect3DSurface9 인터페이스로의 포인터라고 가정
D3DSURFACE_DESC surfaceDesc;
_surface -> GetDesc(&surfaceDesc); //표면 정보를 얻는다.
D3DLOCKED_RECT lockedRect;
// 구조체 구조 : INT Pitch 표면피치, void *pBits 표면메모리 시작
포인터
_surface -> lockRect(&lockedRect, 0, 0); //잠근데이터를 얻을 포인터, 전체 표면을 잠근다, 잠금 플래그 를 지
정하지 않는다.
DWORD* imageData = (DWORD*)lockedRect.pBits;
for(int i = 0; i < surfaceDesc.Height; i++) {
for(int j = 0; j < surfaceDesc.Width; j++) {
int index = i * lockedRect.Pitch / 4 + j; //피치는 byte 단위이며 DWORD당 4byte이므로
//피치를 4로 나누었음에 주의
imageData[index] = 0xffff0000;
//Red
}
}
_surface -> UnlockRect();
//잠금 해제
1.3.2 멀티 샘플링(Multisampling)
 픽셀 매트릭스로 이미지를 표현할 때 나타나는 거친 이미
지를 부드럽게 만드는 데 이용되는 기술
 D3DMULTISAMPLE_TYPE : 표면에 적용할 멀티 샘플링 레
벨을 지정할 수 있도록 하는 값들로 구성
 D3DMULTISAMPLE_NONE – 멀티 샘플링을 지정안함
 D3DMULTISAMPLE_1_SAMPLE ···
D3DMULTISAMPLE_16_SAMPLE – 1에서 16까지의 멀티샘플
링을 지정
 멀티 샘플링 타입과 연계된 품질 레벨도 있으며, DWORD
로 지정
 IDirect3D9::CheckDeviceMultiSampleType 메서드로 그래
픽카드에서 지원하는 멀티샘플링 타입과 품질 레벨 확인
1.3.3 픽셀 포맷
 표면이나 텍스처를 만들기 위해서는 Direct3D자원의 픽셀
포맷을 지정해야함
 D3DFORMAT 열거형 멤버로 지정
 D3DFMT_R8G8B8 – 24bit 픽셀 포맷
 D3DFMT_X8R8G8B8 – 32bit픽셀 포맷. 가장 왼쪽 8bit 사용
하지 않음
 D3DFMT_A8R8G8B8 – 32bit 픽셀 포맷. 가장 왼쪽 8bit 알파
 D3DFMT_A16B16G16R16F – 64bit 부동소수점 픽셀 포맷. 가
장 왼쪽부터 16bit씩 alpha, blue, green, red
 D3DFMT_A32B32G32R32F – 128bit 부동소수점 픽셀 포맷. 가
장 왼쪽부터 32bit씩 alpha, blue, green, red
 픽셀 포맷의 전체 목록은 SDK문서에서 D3DFORMAT 참조
1.3.4 메모리 풀
 다양한 Direct3D 자원들을 여러 가지 종류의 메모리 풀에
보관가능
 메모리 풀은 D3DPOOL 열거형 멤버로 지정
 D3DPOOL_DEFAULT – 자원의 타입과 이용 방식에 가장 적
합한 자원들을 메모리에 보관하도록 Direct3D에 요청. 반드
시 IDirect3DDevice9::Reset 호출 이전에 해제되어야 하며,
reset 호출 이후에 다시 초기화
 D3DPOOL_MANAGED – Direct3D에 의해 자동관리.
 D3DPOOL_SYSTEMMEM – 시스템 메모리 내에 보관될 자원
을 지정
 D3DPOOL_SCRATCH – 앞서의 D3DPOOL_SYSTEMMEM과
는 달리 이 풀의 자원은 그래픽 장치의 제한을 따라서는 안됨.
이 풀 내의 자원에 직접 접근할 수 없지만, 자원을 두 풀 사이
에 서로 복사하는 것은 가능
1.3.5 스왑 체인과 페이지 플리핑
 스왑 체인지 – Direct3D는 보통 두 개나 세 개의 표면
을 하나의 컬렉션으로 관리
 IDirect3DSwapChain9 인터페이스를 통해 이용가능 but
대부분 Direct3D가 직접 관리
표면1
표면2
전면 버퍼
후면 버퍼
교환
표면2
표면1
전면 버퍼
후면 버퍼
표면1
전면 버퍼
교환
표면2
후면 버퍼
1.3.6 깊이 버퍼
 이미지 데이터가 아닌 특정 픽셀의 깊이 정보를 포함하는
표면
 최종 렌더링된 이미지의 각 픽셀에 해당하는 항목들을 포
함한다.
 깊이 버퍼의 포맷은 깊이 테스트의 정확도를 결정
 대부분 24bit 깊이 버퍼로 충분
 D3DFMT_D32 – 32bit 깊이 버퍼를 지정
 D3DFMT_D24S8 – 24bit 깊이 버퍼를 지정, 8bit 스텐실 버퍼
예약
 D3DFMT_D24X8 – 24bit 깊이 버퍼를 지정
 D3DFMT_D24X4S4 – 24bit 깊이 버퍼를 지정, 4bit 스텐실 버
퍼 예약
 D3DFMT_D16 – 16bit 깊이 버퍼를 지정
1.3.7 버텍스 프로세싱
 소프트웨어 버텍스 프로세싱
 언제나 지원되며 항상 이용 가능
 하드웨어 버텍스 프로세싱
 그래픽 카드가 버텍스 프로세싱을 지원하는 경우에만
이용 가능
 소프트웨어 방식에 비해 성능이 우수하므로 버텍스 프
로세싱을 이용하는 것이 유리
1.3.8 장치 특성
 Direct3D가 제공하는 모든 기능들은 D3DCAPS9 구조체 내의 비트와
데이터 멤버에 대응
 기본적인 방식은 특정 하드웨어의 특성에 따라 D3DCAPS9 인스턴스
의 멤버를 초기화하고 D3DCAPS9 인스턴스의 대응되는 비트나 데이
터 멤버를 확인하여 장치가 특정한 기능을 제공하는지 확인
bool supportHardwareVertexProcessing;
//만약 비트가 켜져 있다면 장치가 기능을 지원한다는 의미
if ( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
{
//비트가 켜져 있으므로 기능이 지원된다.
supportsHardwareVertexProcessing = true;
}
else
{
//비트가 꺼져 있으므로, 기능이 지원되지 않는다.
hardwareSupportsVertexProcessing = false;
}
1.4 Direct3D 초기화하기
1. IDirect3D9 인터페이스로의 포인터를 얻는다.
2. IDirect3DDevice9 인터페이스를 만들기 위해 장치특
성(D3DCAPS9)을 확인한다.
3. D3DPRESENT_PARAMETERS 구조체 인스턴스를 초
기화한다. 이 구조체는 우리가 만들고자하는
IDirect3DDevice9 인스턴스의 특성을 지정하기 위한
몇 가지 데이터 멤버들을 포함
4. 초기화된 D3DPRESENT_PARAMETERS에 따라
IDirect3DDevice9 객체를 만듬
1.4.1 IDirect3D9 인터페이스 얻기
IDirect3D9* _d3d9;
_d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
 Direct3DCreate9의 단일 인자에는 항상
D3D_SDK_VERSION을 전달해야 함
 실패하면 null 포인트 리턴
 IDirect3D9 객체는 장치 검증과 IDirect3DDevice9 객
체 생성의 두 가지 용도로 이용
1.4.2 하드웨어 버텍스 프로세싱
확인하기
 IDirect3DDevice9 객체를 생성할 때는 반드시 원하는
버텍스 프로세싱 모드를 지정해야 한다.
 하드웨어 버텍스 프로세싱을 지원하는지 여부 확인을
위해 D3DCAPS9 인스턴스를 초기화
HRESULT IDirect3D9::GetDeviceCapts(UINT Adapter, D3DDEVTYPE DeviceType, D3DCAPS9 *pCaps);
 Adapter – 특성을 얻고자 하는 물리 디스플레이 어댑터를 지정
 DevieType – 이용할 장치타입 지정. 하드웨어(D3DDEVTYPE_HAL),
소프트 웨어(D3DDEVTYPE_REF)
 pCaps – 초기화된 특성 구조체를 리턴
1.4.2 하드웨어 버텍스 프로세싱
확인하기
D3DCAPS9 caps;
D3d9->GetDeviceCaps(
D3DADAPTER_DEFAULT, // 기본 디스플레이 어댑터를 표기
deviceType,
// 장치 타입을 지정, 보통 D3DDEVTYPE_HAL
&caps);
// 기본 디스플레이 어댑터의 특성으로 채워진 D3DCAPS9 구조체를 리턴
//하드웨어 버텍스 프로세싱을 이용할 수 있는가?
int vp = 0;
if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
{ //하드웨어 버텍스 프로세싱이 지원된다는 사실을 ‘vp‘에 저장
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
}
else
{ //소프트웨어 버텍스 프로세싱을 이용해야 한다는 사실을 ‘vp‘에 저장
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
 버텍스 프로세싱의 타입을 변수 vp에 보관했음에 주의
 이후 IDirect3DDevice9 객체를 만들 때 버텍스 프로세
싱의 타입을 지정해야 하기 때문
1.4.3 D3DPRESENT_PARAMETERS
구조체 채우기
 D3DPRESENT_PARAMETERS 구조체
Typedef struct _D3DPRESENT_PARAMETERS_ {
UINT BackBufferWidth; //픽셀 단위의 후면버퍼 너비
UINT BackBufferHeight; //픽셀 단위의 후면버퍼 높이
D3DFORMAT BackBufferFormat; //후면 버퍼의 픽셀 포맷
UINT BackBufferCount; //이용할 후면 버퍼의 수. 보통 한 개의 후면버퍼 사용
D3DMULTISAMPLE_TYPE MultiSampleType; //후면 버퍼에 이용할 멀티 샘플링의 타입
DWORD MultiSampleQuality; //멀티 샘플링의 레벨
D3DSWAPEFFECT SwapEffect; //플리핑 체인의 버퍼가 교환되는 방법을 지정
HWND hDeviceWindow; //서비스와 연결된 윈도우 핸들
//드로잉의 대상이 될 애플리케이션 윈도우를 지정
BOOL Windowed; //윈도우 모드일때 true, 전체화면 모드일때 false를 지정
BOOL EnableAutoDepthStencil; //자동으로 깊이/스텐실 버퍼를 만들고 관리하길 원하면
true
D3DFORMAT Auto DepthStencilFormat; //깊이/스텐실 버퍼의 포맷
DWORD Flags; //몇 가지 부가적인 특성
UINT FullScreen_RefreshRateInHz; //재생율을 지정 D3DPRESENT_RATE_DEFAULT
UINT PresentationInterval; //D3DPRESENT 집합의 멤버
} D3DPRESENT_PARAMETERS;
1.4.4 IDirect3DDevice9 인터페이
스 만들기
 D3DPRESENT_PARAMETERS를 채운 뒤 다음 메서드
로 IDirect3dDevice9객체를 만들 수 있음.
HRESULT IDirect3D9::CreateDevice {
UINT Adapter, //만들어질 IDirect3DDevice9 객체와 대응될 디스플레이 어댑터를 지정
D3DDEVTYPE DeviceType, //이용할 장치 타입을 지정(하드웨어 or 소프트웨어)
HWND hFocusWindow; //장치와 연결될 윈도우 핸들. 보통은 장치가 드로잉을 수행할 윈도우
DWORD BehaviorFlags, //D3DCREATE_HARDWARE_VERTEXPROCESSING or
//D3DCREATE_SOFTWARE_VERTEXPROCESSING
D3DPRESENT_PARAMETERS *pPresenttationParameters, //장치 특성의 일부를 정의하는
//초기화된
//D3DPRESENT_PARAMETERS
//인스턴스를 지정
IDirect3DDevice9** ppReturnedDeviceInterface //생성된 장치를 리턴
};
1.4.4 IDirect3DDevice9 인터페이스
만들기
 호출 예
IDirect3DDevice9* device = 0;
hr = d3d9->CreateDevice (
D3DADAPTER_DEFAULT, //기본 어댑터
D3DDEVTYPE_HAL, //창치 타입
hwnd, //장치와 연결된 윈도우
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp, //시연 인자
&device); //생성된 장치
if( FAILED(hr))
{
::MessageBox(0, “CreateDevice () – FAILED”, 0, 0);
return 0;
}
//버텍스 프로세싱 타입