MoniWiki메모장_D3D
Login:
Password:
대문|찾기|바뀐글|목록|메모장|책갈피|연꽃|링크
Edit Diff Reload Search Print Info Mail Help RSS

@ 2004-06-16 @

  다이렉트 3D
1 기타
2 DirectX
2.1 월드좌표계의 프러스텀(Frustum) 좌표 구하기
2.2 VS2005, DirectX SDK 사용을 위한 설정
2.3 DirectX 버전별 dll
3 메모리 관련
3.1 AGP 메모리와 비디오 메모리
3.2 비디오 메모리 잔량을 실시간으로 측정(GPGstudy에 올려진 글 정리)
3.3 Windows 작업 관리자
4 D3DX 함수
4.1 화면 크기 구하는 법
4.1.1 시스템 정보를 출력하는 방법 ; 듀얼모니터의 모니터 사이즈
4.2 D3DX 기하물체
4.3 HRESULT D3DXSaveSurfaceToFile( ..., D3DXIMAGE_FILEFORMAT, ... );
4.4 D3DXCheckVersion - D3D 버전 확인하기
4.5 OSVERSIONINFOEX Structure (Windows)를 이용한 버전 확인
4.6 Rendering 관련 설정, Log 파일로 저장
5 Display
5.1 맵2장을 사용한 법선 맵핑
5.2 알파블렌딩
5.3 커서를 마음대로...
5.4 D3D 9.0 글자쓰기(규진에게 감사)
5.5 Depth Buffer 비교 옵션 바꾸기
5.6 Quaternion
{_r} 메모장으로 가기

1 기타 #


▷ 특정 게임에서 한글 입력의 문제
-. Windows 7 (64 비트) 설치시 설정된 'Microsoft office IME 2007'에서 문제가 발생하지 않음
-. 별도로 받아서 설치한 '한글입력시스템(MS-IME2002)'에서는 한/영 변환키가 작동하지 않고, 한글이 입력되지 않는 현상 발견

#define DEG2RAD 0.01745f
#pragma once

//-----------------------------------------------------------------------------
// Miscellaneous helper functions
//-----------------------------------------------------------------------------
#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }

//-----------------------------------------------------------------------------
// General purpose utilities
//-----------------------------------------------------------------------------
d3dx9math.h
#define D3DX_PI ((float) 3.141592654f)
#define D3DX_1BYPI ((float) 0.318309886f)

#define D3DXToRadian( degree ) ((degree) * (D3DX_PI / 180.0f))
#define D3DXToDegree( radian ) ((radian) * (180.0f / D3DX_PI))

* D3DXCreateTextureFromFileEx() 등의 함수를 사용할때
Format을 D3DFMT_UNKNOWN 으로 지정하면 로딩 속도가 느려지는 경우도 있다.

* D3D 매크로 이용
/// 단축형 매크로
#define RS m_pd3dDevice->SetRenderState
#define TSS m_pd3dDevice->SetTextureStageState
#define SAMP m_pd3dDevice->SetSamplerState

/// 렌더링 상태 설정
RS( D3DRS_DITHERENABLE, FALSE );
RS( D3DRS_SPECULARENABLE, FALSE );
RS( D3DRS_ZENABLE, TRUE );
RS( D3DRS_AMBIENT, 0x000F0F0F );

/// 텍스처에 관한 설정
TSS( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
TSS( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
TSS( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );

* BOOL 정의
// Standard constants
#define FALSE 0
#define TRUE 1
#define NULL 0
// Success codes
#define S_OK ((HRESULT)0x00000000L)
#define S_FALSE ((HRESULT)0x00000001L)

* 렌더링 상태값 조정
Device->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD );
Device->SetRenderState( D3DRS_SPECULARENABLE, true ); // 디폴트는 꺼져있음
Device->SetRenderState( D3DRS_NORMALIZENORMALS, true ); // 노말값이 왜곡되는 현상을 방지하기 위해, Direct3D가 모든 노말값을 다시 정리하도록 한다.

* 함수...
#.D3DXPlaneFromPoints(D3DXPLANE * pOut, CONST D3DXVECTOR3 *pV1, CONST D3DXVECTOR3 *pV2, CONST D3DXVECTOR3 *pV3);
세 점으로부터 평면의 방정식을 구하는 함수
#.D3DXVec3TransformCoord 함수; 지정된 행렬에 의해 3D 벡터를 변환 해, 그 결과를 w = 1 에 투영 한다.
pOut - 연산 결과인 D3DXVECTOR3 구조체의 포인터.
pV - 처리의 기본으로 되는 D3DXVECTOR3 구조체의 포인터.
#.D3DXVec3Transform 함수; 지정된 행렬에 의해 벡터 (x, y, z, 1)를 변환 한다.
pOut - 연산 결과인 D3DXVECTOR4 구조체의 포인터.
pV - 처리의 기본으로 되는 D3DXVECTOR3 구조체의 포인터.
#.D3DXVec4Transform 함수; 지정된 행렬에 의해 4D 벡터를 변환 한다.
pOut - 연산 결과인 D3DXVECTOR4 구조체의 포인터.
pV - 처리의 기본으로 되는 D3DXVECTOR4 구조체의 포인터.

2 DirectX #

D3DXMatrixRotationYawPitchRoll 함수는 회전으로 행렬을 만들 때,
Roll (Z) * Pitch(X) * Yaw(Y) 순서로 계산

▷ 오른손 좌표계에서는
Yaw는 Z축에 대한 반시계방향 회전
Pitch는 Y축에 대한 반시계방향 회전
Roll은 X축에 대한 반시계방향 회전
고로, Z * Y * X 순으로 곱하여 회전 행렬식을 만든다.

SetRenderState( D3DRS_DEPTHBIAS , value );
DEPTHBIAS(z-bias)는 같은 깊이에 있는 두 폴리곤 사이에서 일어나는 Z-fighting을 막기위해
인위적으로 DEPTH(z)값을 조정해주는 수치로,
지형그릴때 0값을 셋팅하고 데칼 그릴때 1로 셋팅해서 인위적으로 겹치는 부분이 지저분해 지는 것을 방지한다.


2.1 월드좌표계의 프러스텀(Frustum) 좌표 구하기 #

1.렌더링 파이프라인을 통과하는 최종 버텍스의 변환은
Vertex_end = Vertex_local * Matrix_world * Matrix_view * Matrix_Proj 이다.
∵ Vertex_world = Vertex_local * Matrix_world
Vertex_end = Vertex_world * Matrix_view * Matrix_Proj
∵ Matrix_ViewProj = Matrix_view * Matrix_Proj
Vertex_end = Vertex_world * Matrix_ViewProj
2.구하고자 하는 최종결과가 Vertex_world 이므로
Vertex_world = Vertex_end * Matrix_ViewProj^-1(Matrix_view * Matrix_Proj의 역행렬)
3.절두체(Frustum)의 Vertex_end값은 (-1,-1,0) ~ (1,1,1)사이의 값임으로
D3DXMATRIXA16 MatrixViewProj = Matrix_view * Matrix_Proj;
D3DXMATRIXA16 MatrixViewProj_Inv = D3DXMatrixInverse(&MatrixViewProj_Inv, NULL, MatrixViewProj);
절두체의 Vertex_world = D3DXVec3TransformCoord( &Vertex_world, &Vertex_end, &MatrixViewProj_Inv);

2.2 VS2005, DirectX SDK 사용을 위한 설정 #

Microsoft DirectX SDK (February 2007)을 설치하면 환경변수에 다음 항목이 추가된다.
DXSDK_DIR=C:\Program Files\Microsoft DirectX SDK (February 2007)\

(방법 1) Visual Studeo 2005의 VC++에 대해서 설정하기
1. Tools | Options 다이얼로그 창을 연다.
2. Projects and Solutions | VC++ Directories | Win32, Include files에 다음 항목을 추가한다.
$(DXSDK_DIR)include
3. Projects and Solutions | VC++ Directories | Win32, Library files에 다음 항목을 추가한다.
$(DXSDK_DIR)lib\x86 or $(DXSDK_DIR)lib\x64

(방법 2) Project별로 설정하기
1. Project를 선택하고 우측 마우스 버튼을 클릭한 후 Properties 다이얼로그 창을 연다.
2. C/C++ | General | Additional Include Directories에 다음 항목을 추가한다.
$(DXSDK_DIR)include
3. Linker | General | Additional Library Directories에 다음 항목을 추가한다.
$(DXSDK_DIR)lib\x86 or $(DXSDK_DIR)lib\x64

(주의) release와 debug에 대해 모두 해 주어야 한다.

2.3 DirectX 버전별 dll #

DirectX SDK Version Release Build Debug Build
Direct3D 10.1 (March 2008) d3dx9_37.dll d3dx9d_37.dll
Direct3D 10 (November 2007) d3dx9_36.dll d3dx9d_36.dll
Direct3D 10 (August 2007) d3dx9_35.dll d3dx9d_35.dll
Direct3D 10 (June 2007) d3dx9_34.dll d3dx9d_34.dll
Direct3D 10 (April 2007) d3dx9_33.dll d3dx9d_33.dll
Direct3D 10 (February 2007) d3dx9_32.dll d3dx9d_32.dll
Direct3D 10 (December 2006)
Direct3D 10 (October 2006) d3dx9_31.dll d3dx9d_31.dll
Direct3D 10 (August 2006) d3dx9_30.dll d3dx9d_30.dll
Direct3D 10 (June 2006)
Direct3D 10 (April 2006)
Direct3D 10 (February 2006) d3dx9_29.dll d3dx9d_29.dll
Direct3D 10 (December 2005) d3dx9_28.dll d3dx9d_28.dll
DirectX 9.0 Update (October 2005) d3dx9_27.dll d3dx9d_27.dll
DirectX 9.0 Update (August 2005)
DirectX 9.0 Update (June 2005) d3dx9_26.dll d3dx9d_26.dll
DirectX 9.0 Update (April 2005) d3dx9_25.dll d3dx9d_25.dll
DirectX 9.0 Update (February 2005) d3dx9_24.dll d3dx9d_24.dll
DirectX 9.0 Update (December 2004) 이전 StaticLinkLibrary이므로 외부 의존 없음 d3dx9d.dll


3 메모리 관련 #

3.1 AGP 메모리와 비디오 메모리 #

1.AGP(Accelerated Graphics Port)
1-1.사용자는 CMOS에서 AGP Apecture 사이즈를 직접 지정할 수가 있는데, 만약 자신의 전체 램이 512MB라면 128MB~256MB 정도로 설정하고 256MB라면 64~128MB로 설정해서 사용하길 바란다(AGP 사이즈를 크게 할수록 많은 리소스를 사용하는 3D 게임들이 원활하게 돌아간다). 이처럼 AGP 메모리라고 해서 따로 있는 것이 아니라 그냥 일반 램인데 특별히 영역을 지정해주는 것이다.
1-2. 단지 OS가 AGP 메모리를 특별하게 처리하는데 속도를 위해서 특별히 잘 관여하지 않는다고 보면 된다. OS는 안정성이 우선이기 때문에 일반 메모리의 경우 페이징 처리부터 가상메모리 처리 및 OS 통제가 심하지만 AGP는 3D 카드가 직접 읽을 수 있도록 CPU가 빨리 쓸 수 있도록 설계되어 있다.
1-3. AGP의 특성
• CPU가 읽는(Read) 속도는 매우 느리고 쓰는 것은 빠르다.
• 3D 카드에서 시스템 메모리를 읽는 것은 매우 느리고 AGP 메모리를 읽는 것이 훨씬 빠르다.
• 사실상 물리적(Physical) 메모리에 잡힌다. 물리적 메모리에 잡힌다는 것은 속도상 많은 이득이 있다.
• AGP 메모리는 OS가 관리해 주기 때문에 많은 양의 메모리를 사용하더라도 그 이상의 메모리를 수용할 수가 있다. 다만 용량의 한계에 도달했을 때 시스템 메모리와 AGP 메모리간의 전송이 일어나 화면의 끊김 현상이 생기게 된다.

이와 같은 특성으로 인해 충돌검사를 한다고 버텍스 버퍼에 락(Lock)을 걸어서 읽는다거나 하는 경우가 없어야 할 것이다(버텍스 정보를 시스템 메모리에 같이 가지고 있든가 해야 된다).

2. 비디오 메모리 = AGP 메모리 + 3D 카드 메모리(예전에 텍스처 메모리라 불림)
2-1. 여기서 3D 카드 메모리는 일반적으로 3D 카드 스펙 중 128MB 또는 64MB라고 이야기하는 용량을 말한다. 비디오 메모리에는 텍스처, Z-버퍼, 셰도우 버퍼, 프레임 버퍼, 버텍스 버퍼, 스텐실 버퍼 등 모든 3D 카드가 처리하는 것들이 올라가게 된다.
2-2. 결국 중요한 것은 AGP 메모리나 3D 카드의 메모리나 비디오 메모리라고 해도 3D 하드웨어에서는 같이 처리된다는 점이다. D3D8 인터페이스 중 다음과 같은 API로 현재 사용할 수 있는 비디오 메모리 양을 알아낼 수 있다.

pd3dDevice->GetAvailableTextureMem();

이와 같은 API로 응용 프로그램의 리소스를 적절하게 비디오 메모리에 올릴 수 있는 디텍트(Detect) 기능을 넣어주면 좋다.


3.2 비디오 메모리 잔량을 실시간으로 측정(GPGstudy에 올려진 글 정리) #

#.UINT IDirect3DDevice9::GetAvailableTextureMem(VOID);

-. Return Values ; 사용 가능한 텍스처 메모리양의 추정값을 돌려준다.
-. 주의 ;
돌려받는 값은, 가장 가까운 MB 값으로, 특정의 리소스에 의한 비디오 메모리의 소비에 영향을 주는 alignment나 다른 문제에 의해, 비디오 메모리의 추정값을 정확하게 요구할 수가 없기 때문이다. 애플리케이션에서는, 이 값을 사용해, 이용할 수 있는 메모리의 대량적인 양을 추정해, 할당하려고 하는 밉맵의 레벨수와 같은 리소스에 관한 거시적인 결정을 내릴 수 있지만, 다른 리소스를 할당하는데 충분한 메모리가 남아 있는지 등 작은 스케일의 결정에는 사용할 수 없다.
-. 필요 ; Header: Declared in D3D9.h.(출처; MSDN)


(루광)
Windows 게임은 반드시 VRAM의 크기를 추정해야 한다. DirectX 4에서 DirectX 7까지는 IDirectDraw의 GetAvailableVidMem을 통해서 VRAM 크기를 직접 얻을 수 있었다.
...(중략)....
DirectX 9에서는 이 함수가 사라졌다. DirectX 9 도움말 상에는 사용할 수 있는 비디오 RAM의 양을 구하는 가장 좋은 방법이 IDirect3DDevice9 인터페이스의 GetAvailableTextureMem을 사용하는 것이라고 나와 있다.
...(중략)....
그러나 도움말을 자세히 보면, 사실 함수 이름에서도 짐작할 수 있지만, 이 함수는 사용 가능한 텍스처 메모리의 용량을 돌려줄 뿐인데, 그 값은 VRAM의 용량과 다르다. 그래서 나는 DX9 게임이라도 이 부분만큼은 DX7 API를 사용한다. DX9용 게임에서도 꼭 필요하다면 DX7, DX6 등을 사용할 수 있다는 점은 이미 이야기했었다.

더 자세히는 안 나와 있지만 그 뒤 문장들로 유추해보면 QueryInterface를 이용해서 DX7 IDirectDraw 인터페이스를 얻어서 어떻게 할 수 있나 봅니다...

대충 이렇네요..
코드:
#include <ddraw.h>
...

m_MaxAllocMem = m_pDevice->GetAvailableTextureMem();

/////
LPDIRECTDRAW7 lpDD = NULL;
DDSCAPS2 ddsCaps2;
DWORD dwTotal;
DWORD dwFree;
HRESULT hr;

hr = DirectDrawCreateEx(NULL, (VOID**)&lpDD, IID_IDirectDraw7, NULL );
if (FAILED(hr))
return FALSE;

// Initialize the structure.
ZeroMemory(&ddsCaps2, sizeof(ddsCaps2));

ddsCaps2.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
hr = lpDD->GetAvailableVidMem(&ddsCaps2, &dwTotal, &dwFree);
if (FAILED(hr))
return FALSE;

if(lpDD)
lpDD->Release();


참고로 이건 시스템 메모리에 관한거..
코드:
MEMORYSTATUS MemStatus;
MemStatus.dwLength=sizeof(MemStatus);
GlobalMemoryStatus(&MemStatus);

// get video memory
long nStartVideoMemory = g_pDirect3DDevice->GetAvailableTextureMem();

if( nStartVideoMemory <= 50000000 ) // tiny Video Memory => 16(Video) + 32(AGP)
g_byVideoMemoryType = eVIDEOMEM_TINY;
else
if( nStartVideoMemory <= 97000000 ) // Small Video Memory => 32(Video) + 64(AGP)
g_byVideoMemoryType = eVIDEOMEM_SMALL;

3.3 Windows 작업 관리자 #

#.작업관리자에서 주위 깊게 봐야할 항목 중에 메모리 사용과 VM크기라는 것이 있다.
메모리 사용량은 해당 프로세스가 현재 사용중인 물리적 메모리의 양이다.
VM 크기는 해당 프로세스에 할당된 총 가상 메모리이다.


4 D3DX 함수 #

4.1 화면 크기 구하는 법 #

1. GetDesktopWindow(), GetWindowRect()
- Desktop도 하나의 윈도우이므로, Desktop의 윈도우 핸들을 얻어 창크기를 구하는 방식

CRect rcDesktop;
::GetWindowRect(GetDesktopWindow()->m_hWnd, &rcDesktop);

int width = rcDesktop.right - rcDesktop.left;
int height = rcDesktop.bottom - rcDesktop.top;

2. GetSystemMetrics()
- 깔끔하고 간단함

int width = GetSystemMetrics(SM_CXSCREEN);
int height = GetSystemMetrics(SM_CYSCREEN);

3. GetDeviceCaps()
- HDC를 어떻게 구하냐에 따라서 듀얼 모니터 사용시 각각의 모니터에서 해상도를 구해올 수 있다는게 장점

HDC hDC = GetDC();
int width = GetDeviceCaps(hDC, HORZRES);
int height = GetDeviceCaps(hDC, VERTRES);
cf.
GetDesktopWindow(); 데스크톱 윈도우(루트 윈도우) 핸들을 반환
GetActiveWindow(); 현재 활성화 된 윈도우의 핸들을 반환 (창모드)
GetForegroundWindow(); 활성화 여부와 관계없이 최상위 위도우 핸들을 반환

4.1.1 시스템 정보를 출력하는 방법 ; 듀얼모니터의 모니터 사이즈 #

#. GetSystemMetrics function
참고함수 SystemParametersInfo

-. Syntax
int WINAPI GetSystemMetrics(
_In_ int nIndex
);
nIndex : 조사하고자 하는 설정 정보. 보통 SM_CX, SM_CY로 시작하는데 각각 X축 설정값과 Y축 설정값으로 구성

-. Parameters
SM_CLEANBOOT - 시스템이 어떻게 부팅되었는지를 조사
0이면 보통 모드로 부팅, 1이면 세이프 모드로 부팅, 2이면 네트웍 지원이 있는 세이프 모드로 부팅
SM_CMONITORS - 98, 2000 이상 : 데스크탑의 모니터 개수
SM_CMOUSEBUTTONS - 마우스의 버튼 개수.
0이면 마우스가 설치되어 있지 않음

SM_CXSCREEN, SM_CYSCREEN - 프라이머리 디스플레이의 화면 크기
이 값은 데스크탑 DC로 GetDeviceCaps 함수를 호출하여 HORZRES, VERTRES를 호출한 결과와 동일
...

SM_CXVIRTUALSCREEN, SM_CYVIRTUALSCREEN - 98/ME, 2000이상 : 가상 스크린의 폭과 높이
이 크기는 모든 디스플레이 모니터 영역을 둘러싸는 크기

SM_XVIRTUALSCREEN, SM_YVIRTUALSCREEN - 98/ME이상, 2000이상 : 가상 스크린의 왼쪽 위의 좌표


-. Return value
GetSystemMetrics( SM_ARRANGE );의 리턴 값
; 최소화된 윈도우를 어떤 식으로 정렬할 것인가를 지정한다. 정렬 시작 위치와 방향을 리턴하는데 시작 위치는 다음 중 하나
Value (시작 위치) Meaning
ARW_BOTTOMLEFT Start at the lower-left corner of the screen. The default position.
ARW_BOTTOMRIGHT Start at the lower-right corner of the screen. Equivalent to ARW_STARTRIGHT.
ARW_TOPLEFT Start at the upper-left corner of the screen. Equivalent to ARW_STARTTOP.
ARW_TOPRIGHT Start at the upper-right corner of the screen. Equivalent to ARW_STARTTOP | SRW_STARTRIGHT.

/ 정렬 방향 ARW_DOWN, ARW_LEFT, ARW_RIGHT, ARW_UP 중 하나가 된다.

GetSystemMetrics( SM_DIGITIZER );의 리턴 값 - Windows 7 or Windows Server 2008 R2 이후 버전에서 지원
NID_INTEGRATED_TOUCH, NID_EXTERNAL_TOUCH, NID_INTEGRATED_PEN, NID_EXTERNAL_PEN, NID_MULTI_INPUT, NID_READY

-. 싱글 모니터의 경우
left = 0;
top = 0;
right = GetSystemMetrics( SM_CXSCREEN );
bottom = GetSystemMetrics( SM_CYSCREEN );

-. 듀얼모니터의 경우 각각의 모니터 좌표가 아닌 전체 두개 이상의 모니터를 합친 전체 모니터 사이즈
left = GetSystemMetrics( SM_XVIRTUALSCREEN );
top = GetSystemMetrics( SM_YVIRTUALSCREEN );
right = GetSystemMetrics( SM_CXVIRTUALSCREEN );
bottom = GetSystemMetrics( SM_CYVIRTUALSCREEN );

모니터의 배치와 기본 위치에 따라 left, top이 음수 값이 될 수 있기 때문에 주의


4.2 D3DX 기하물체 #

* D3DX 라이브러리는 다음의 6가지 메쉬 생성 함수를 제공한다.
D3DXCreatBox/ Sphere/ Cylinder/ Teapot/ Polygon/ Torus
* <선언> --> <렌더링>; 필요없을 때는 리소스를 해제한다.
* 사용예
LPD3DXMESH g_sphere = NULL;
// 생성
D3DXCreateSphere(g_pd3dDevice, 1.f, 3, 3, &g_sphere, NULL );
D3DXComputeNormals( g_sphere, NULL );
// 변환
D3DXMatrixTranslation(&testMat->g_matWorld, x, y, z);
// 월드매트릭스 적용
g_pd3dDevice->SetTransform( D3DTS_WORLD, &testMat->g_matWorld );
g_sphere->DrawSubset(0); // 렌더링
// 소거
if( g_sphere != NULL ) g_sphere->Release();
g_sphere = 0;


HEL(Hardware Emulation Layer, RGB 장치라고도 함) ; 소프트웨어적으로 특정한 기능을 에뮬레이션
-. DirectX 8.0 이후로 제공되지 않음

플러그블 소프트웨어(pluggable software device) ; DirectX 9에서 소프트웨어 개발자가 작성한
HEL을 사용하기 위한 인터페이스


Win32 어플리케이션 ↔ Direct3D API ↔ HAL 디바이스 ↔디바이스 드라이버 인터페이스(DDI)↔그래픽하드웨어
Win32 어플리케이션 ↔ GDI ↔디바이스 드라이버 인터페이스(DDI)↔그래픽하드웨어

위에서 보는 것처럼, Direct3D는 DDI(Device Driver Interface)를 통하여 그래픽 하드웨어에 접근하는
수단으로 HAL을 사용한다.

HAL(Hardware Abstraction Layer); 주 디바이스 타입이고 하드웨어 가속 래스터화 및 하드웨어와 소프트웨어
버텍스 프로세싱 두 가지 모두를 지원한다.
디스플레이 어댑터가 Direct3D를 지원한다면, HAL이 컴퓨터에 존재한다.
DirectX 9.0 어플리케이션은 그래픽 카드 드라이버가 DirectX 7 DDI 이상을 지원해야 실행한다.
완전히 소프트웨어적으로 또는 부분적으로 버텍스 프로세싱을 에뮬레이션 할 수 있다.
-. D3DCREATE_SOFTWARE_VERTEXPROCESSING
-. D3DCREATE_HARDWARE_VERTEXPROCESSING
-. D3DCREATE_MIXED_VERTEXPROCESSING
_. D3DCREATE_PUREDEVICE ; Direct3D가 상태 블록에 저장될 수 있는 Get~ 형태의 어떠한 호출도
지원하지 않음을 설정하고자 할 때 사용
레퍼런스 래스터라이저는 Direct3D 9.0 전체 기능을 지원하는 반면에, 플러그블 소프트웨어 장치는 심지어
테스처링도 지원하지 않는다.
사용하는 컴퓨터에 하드웨어 가속 기능이 없다면 HAL 장치 생성 시도는 실패하게 된다.

IDirect3D9::RegisterSoftwareDevice; 플러그블 소프트웨어 장치를 등록하기 위한 함수
소프트웨어 장치들은 어플리케이션에 의해 로드되어 IDirect3D9 객체를 사용하여 등록
DirectX 9 DDK(Device Driver Kit)에 더 자세한 정보가 있음

레퍼런스 래스터라이저
레퍼런스 장치는 SDK의 설치 시에만 제공하며, Direct3D의 모든 기능들을 지원
그래픽 카드가 지원하지 않는 기능들으리 테스트하기 위해서만 레퍼런스 래스터라이저를 사용해야 하며,
이 장치는 속도를 위해서가 아니라, 정밀도를 위해 최적화
Direct3D는 기본적으로 레퍼런스 래스터라이저를 에뮬레이션하지 않는다.

COM(Component Object Model) 컴포넌트는 일관되고 정의된 방법으로 접근할 수 있는 일반적인
.DLL(Dynamic Link Library) 파일로써, COM 인터페이스들은 결코 변경할 수 없으며 언어에 독립적으로
COM 컴포넌트의 함수에만 액세스할 수 있습니다.

v-table; COM 객체에서 구현된 함수들을 참조하는 가상 함수 테이블로, COM 함수들은 직접적으로 접근못함

4.3 HRESULT D3DXSaveSurfaceToFile( ..., D3DXIMAGE_FILEFORMAT, ... ); #

Saves a surface to a file.

Syntax
HRESULT D3DXSaveSurfaceToFile(
_In_ LPCTSTR pDestFile,
_In_ D3DXIMAGE_FILEFORMAT DestFormat,
_In_ LPDIRECT3DSURFACE9 pSrcSurface,
_In_ const PALETTEENTRY *pSrcPalette,
_In_ const RECT *pSrcRect
);

//ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#. D3DXIMAGE_FILEFORMAT enumeration
Describes the supported image file formats. See Remarks for descriptions of these formats.

Syntax
typedef enum D3DXIMAGE_FILEFORMAT {
D3DXIFF_BMP = 0,
D3DXIFF_JPG = 1,
D3DXIFF_TGA = 2,
D3DXIFF_PNG = 3,
D3DXIFF_DDS = 4,
D3DXIFF_PPM = 5,
D3DXIFF_DIB = 6,
D3DXIFF_HDR = 7,
D3DXIFF_PFM = 8,
D3DXIFF_FORCE_DWORD = 0x7fffffff
} D3DXIMAGE_FILEFORMAT, *LPD3DXIMAGE_FILEFORMAT;

//ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#. PALETTEENTRY structure
Specifies the color and usage of an entry in a logical palette.

Syntax
typedef struct PALETTEENTRY {
BYTE peRed;
BYTE peGreen;
BYTE peBlue;
BYTE peFlags;
} PALETTEENTRY, *LPPALETTEENTRY;

/ BYTE peFlags; - The alpha intensity value for the palette entry. Note that as of DirectX 8, this member is treated differently than documented for Windows.

//〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
// DEFINES
//ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
#define SCREENSHOT_FORMAT                   D3DXIFF_BMP
#define SCREENSHOT_COMPRESSED_FORMAT        D3DXIFF_JPG
#define SCREENSHOT_EXTENSION                "bmp"
#define SCREENSHOT_COMPRESSED_EXTENSION     "jpg"

#define SCREENSHOT_PREFIX                   "Hellgate_"
#define SCREENSHOT_PATH                     "Screenshots\\"
#define SCREENSHOT_MIN_TIME_BETWEEN         0.1f

//ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
static HRESULT sCaptureScreenshot( ScreenShotInfo * pInfo )
{
        
        SPDIRECT3DSURFACE9 pBuffer;
...        

        D3DC_IMAGE_FILE_FORMAT tFormat = pInfo->bCompressed ? SCREENSHOT_COMPRESSED_FORMAT : SCREENSHOT_FORMAT;
        RECT * pRect = NULL;
        D3DPRESENT_PARAMETERS tPP = dxC_GetD3DPP();
        WINDOWINFO tInfo;
        if ( tPP.Windowed )
        {
                GetWindowInfo( tPP.hDeviceWindow, &tInfo );
                pRect = & tInfo.rcClient;
        }                
        
        V_RETURN( OS_PATH_FUNC(D3DXSaveSurfaceToFile)( szFilePath, tFormat, pBuffer, NULL, pRect ) );
...        
        
        return S_OK;
}

//ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

4.4 D3DXCheckVersion - D3D 버전 확인하기 #

D3D는 같은 버전대라도 분기별 업데이트로 인해 내부 함수가 변경되거나 인자가 변경되는 경우가 있어서 보통 하나의 버전을 고정시켜두고 사용하는데, 이때 프로젝트에서 버전 체크를 위해 사용하는 함수.

#include <d3dx9.h>
#include <cstdio>

#pragma comment( lib, "d3dx9.lib" )

void main() {
    #if (D3DX_SDK_VERSION != 42)
        #error 이 프로젝트에서 사용된 버전과 다른 Direct3D 버전을 사용하고 계십니다.
    #endif

    if (!D3DXCheckVersion(D3D_SDK_VERSION, /*D3DX_SDK_VERSION*/ 41)) {
        printf("버전이 달라요~ 해보리\n");
    }
} 

4.5 OSVERSIONINFOEX Structure (Windows)를 이용한 버전 확인 #

#. 버전 정보 얻기
OSVERSIONINFOEX version;
memset(&version, 0, sizeof(version));
version.dwOSVersionInfoSize = sizeof(version);
if(GetVersionEx((OSVERSIONINFO*)&version))
{
printf("Windows %d.%d.%d", version.dwMajorVersion, version.dwMinorVersion, version.dwBuildNumber);
}

#. DirectX 인터페이스 생성
IDirect3D9* d3d = Direct3DCreate9(D3D_SDK_VERSION)

#. 원하는 DirectX LoadLibrary 여부 확인
string d3dx9_dll = format("d3dx9_%d.dll", D3DX_SDK_VERSION);

if(HINSTANCE hDll = LoadLibrary(d3dx9_dll.c_str()))
{
FreeLibrary(hDll);
}
else
{
printf("Cannot find %s\n", d3dx9_dll.c_str());
}
{_n} 참고 코드(GSUtil.cpp)

4.6 Rendering 관련 설정, Log 파일로 저장 #

///////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// m_pd3dDevice->SetRenderState(...), SetSamplerState(...), SetTextureStageState(...); 설정을
// Log로 출력하기 위해 맵핑 형식으로 사용한 예

#define MAX_RENDER_STATE_NUM 256
#define MAX_TEXTURE_STAGE_NUM 8
#define MAX_TEXTURE_STAGESTATE_NUM 29
#define MAX_SAMPLER_STAGE_NUM 8
#define MAX_SAMPLER_STATE_NUM 14

//=============================================================================
//-----------------------------------------------------------------------------
class RenderDevice : public D3DDevice
{
public:
...
void SetTextureStageState(DWORD dwStage, D3DTEXTURESTAGESTATETYPE type, DWORD Value);
void SetTexture(DWORD Stage, IDirect3DBaseTexture9* pTexture );
void SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);

void LogRenderState();
void LogSamplerState();
void LogTextureStageState();

public:
LPDIRECT3DDEVICE9 m_pd3dDevice; // The D3D rendering device
DWORD m_dwRenderStateListMAX_RENDER_STATE_NUM; // Log를 출력하기 위해 맵핑 형식으로 사용
DWORD m_dwTextureStageStateListMAX_TEXTURE_STAGE_NUMMAX_TEXTURE_STAGESTATE_NUM;
DWORD m_dwSamplerStateListMAX_SAMPLER_STAGE_NUMMAX_SAMPLER_STATE_NUM;
...
};

//=============================================================================
//-----------------------------------------------------------------------------
void RenderDevice::SetRenderState(D3DRENDERSTATETYPE State, DWORD Value)
{
if(State<0 || State>=MAX_RENDER_STATE_NUM) return;
if(m_dwRenderStateListState != Value){
m_dwRenderStateListState = Value;
m_pd3dDevice->SetRenderState( State, Value );
}
}

void RenderDevice::SetSamplerState(DWORD dwStage, D3DSAMPLERSTATETYPE State, DWORD Value)
{
if(dwStage<0 || dwStage>=MAX_SAMPLER_STAGE_NUM) return;
if(State<0 || State>=MAX_SAMPLER_STATE_NUM ) return;

if(m_dwSamplerStateListdwStageState != Value){
m_dwSamplerStateListdwStageState = Value;
m_pd3dDevice->SetSamplerState( dwStage, State, Value );
}
}

void RenderDevice::SetTextureStageState(DWORD dwStage, D3DTEXTURESTAGESTATETYPE type, DWORD Value)
{
if(dwStage<0 || dwStage>=MAX_TEXTURE_STAGE_NUM) return;
if(type<0 || type>=MAX_TEXTURE_STAGESTATE_NUM ) return;
if(m_dwTextureStageStateListdwStagetype != Value){
m_dwTextureStageStateListdwStagetype = Value;
m_pd3dDevice->SetTextureStageState(dwStage, type, Value);
}
}

//-----------------------------------------------------------------------------
void RenderDevice::LogRenderState()
{
FILE* fp = fopen("RenderStateLog.txt", "wt");
if(fp==NULL) return;
for(int i=0;i<MAX_RENDER_STATE_NUM;i++){
fprintf(fp, "Index:%d Val=%d\n", i, m_dwRenderStateList[i]);
}
fclose(fp);
}

void RenderDevice::LogSamplerState()
{
FILE* fp = fopen("SamplerStateLog.txt", "wt");
if(fp==NULL) return;
for(int i=0;i<MAX_SAMPLER_STAGE_NUM;i++){
for(int j=0;j<MAX_SAMPLER_STATE_NUM;j++){
fprintf(fp, "Stage:%d State:%d Val=%d\n", i,j, m_dwSamplerStateList[i][j]);
}
}
fclose(fp);
}

void RenderDevice::LogTextureStageState()
{
FILE* fp = fopen("TextureStageStateLog.txt", "wt");
if(fp==NULL) return;
for(int i=0;i<MAX_TEXTURE_STAGE_NUM;i++){
for(int j=0;j<MAX_TEXTURE_STAGESTATE_NUM;j++){
fprintf(fp, "Stage:%d State:%d Val=%d\n", i,j, m_dwTextureStageStateList[i][j]);
}
}
fclose(fp);
}


5 Display #

5.1 맵2장을 사용한 법선 맵핑 #

D3DTEXTUREOP 열거형(스테이지마다 텍스처 혼합 처리를 정의)
typedef enum _D3DTEXTUREOP {
D3DTOP_DISABLE = 1,
...
D3DTOP_MULTIPLYADD = 25,: 적화연산을 실행한다.
마지막 2 개의 인수를 취해, 이것들을 곱셈해, 나머지의 입력/소스 인수에 덧셈 해, 이것을 결과에 배치한다.
SRGBA= Arg1 + Arg2 * Arg3
...
} D3DTEXTUREOP;

  참고; 3D게임프로그래밍(김용준 저) 2부 5장 법선 맵핑에서 추출
  g_pd3dDevice->SetTexture( 0, g_pTexNormal );  // 0번 텍스쳐 스테이지에 텍스쳐 고정(법선맵)
  g_pd3dDevice->SetTexture( 1, g_pTexDiffuse ); // 1번 텍스쳐 스테이지에 텍스쳐 고정(벽면맵)
  g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 ); 
  g_pd3dDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 0 );
  DWORD dwFactor = VectortoRGBA( &g_vLight, 0.0f );	// 벡터를 RGB로
  g_pd3dDevice->SetRenderState( D3DRS_TEXTUREFACTOR, dwFactor ); 
           // RGB로 변환된 벡터를 TextureFactor값으로 등록
  g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_DOTPRODUCT3 ); 
  g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );	
  g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TFACTOR );

  g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP,   D3DTOP_MULTIPLYADD );	
           // 벽면맵 텍스처와 법선맵을 섞어서 출력
  g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  g_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_CURRENT );
  g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1 );
  g_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );

5.2 알파블렌딩 #

* D3D의 알파블렌딩은 아래와 같이 이루어진다.
WriteColor = SrcBlend * SrcColor + DstBlend * DstColor ;

WriteColor : 화면에 찍고자 하는 색상
SrcColor : 텍스쳐 블렌딩(쉐이딩,멀티텍스쳐링 따위...)처리된 텍스쳐색상
DstColor : 현재 화면에 찍혀있는 색상

SrcBlend와 DstBlend를 적당히 잘 만들어 주면 재미있는 효과를 얻을수 있습니다.

DBLEND 열거형(지원 되고 있는혼합 모드를 정의)
typedef enum _D3DBLEND {
D3DBLEND_ZERO = 1,
D3DBLEND_ONE = 2,
D3DBLEND_SRCCOLOR = 3,
D3DBLEND_INVSRCCOLOR = 4,
D3DBLEND_SRCALPHA = 5,
D3DBLEND_INVSRCALPHA = 6,
D3DBLEND_DESTALPHA = 7,
D3DBLEND_INVDESTALPHA = 8,
D3DBLEND_DESTCOLOR = 9,
D3DBLEND_INVDESTCOLOR = 10,
D3DBLEND_SRCALPHASAT = 11,
D3DBLEND_BOTHSRCALPHA = 12,
D3DBLEND_BOTHINVSRCALPHA = 13,
D3DBLEND_BLENDFACTOR = 14,
D3DBLEND_INVBLENDFACTOR = 15,
D3DBLEND_FORCE_DWORD = 0x7fffffff
} D3DBLEND;

    m_pd3dDevice->SetTexture( 0, m_pWaterTex[0] );
    m_pd3dDevice->SetTexture( 1, m_pWaterTex[1] );
		
    //알파블렌딩 투명(반투명)하게 ---------------------------------------------
    m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE); 
    m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,	D3DBLEND_ONE  );
    m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND,	D3DBLEND_SRCCOLOR );     // 투명
//  m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND,	D3DBLEND_INVDESTCOLOR);  // 반투명
    출처 : 감자닷넷 + 규진

5.3 커서를 마음대로... #


SetCursor( NULL ); // 마우스를 나타나지 않게 않다.

HCURSOR hcr;
hcr = LoadCursor(NULL,IDC_ARROW);

SetCursor( hcr ); // 마우스를 나타나게함
ShowCursor(TRUE);
ShowCursor(false);

GetCursorPos(LPPOINT lpPoint);
SetCursorPos(int x, int y);


5.4 D3D 9.0 글자쓰기(규진에게 감사) #


LPD3DXFONT m_pStatsFont;
m_pStatsFont = NULL;
// 선언
HRESULT hr;
if( FAILED( hr = D3DXCreateFont( g_pd3dDevice, 30, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET,OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"), &m_pStatsFont ) ) )
{
MessageBox(g_hwnd,"D3DXCreateFont fail","error",MB_OK);
return 0;
}
// 렌더링 시간표시 예
fFPS = myTimer.GetFPS();
sprintf(cFPS,"FPS: %4.1f",fFPS);
//TextOut(hDC,0,0,str,(int)strlen(str));
//SetWindowText(hWnd,str);
RECT rc;
SetRect( &rc, 5, 5, 0, 0 );
// DT_NOCLIP : 클리핑하지 않고 드로잉한다.
m_pStatsFont->DrawText( NULL, cFPS, -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ));


5.5 Depth Buffer 비교 옵션 바꾸기 #


렌더링 surface에서 depth testing이 일어날 때 만약 z 혹은 w값이 이전의 값보다 더 작은 경우
Direct3D은 render 타겟을 업데이트 하도록 되어있다.
그러나 필요한 경우 D3DRS_ZFUNC의 값을 세팅하여 이러한 옵션을 바꿀수 있다.
typedef enum_D3DCMPFUNC {
D3DCMP_NEVER = 1,: 항상 fail 값을 준다.
D3DCMP_LESS = 2,: 이전 값보다 작으면 accept한다
D3DCMP_EQUAL = 3,: 이전 값과 같으면 accept 한다
D3DCMP_LESSEQUAL = 4,: 이전 값보다 같거나 작으면 accept한다
D3DCMP_GREATER = 5,: 이전 값보다 크면 accept한다.
D3DCMP_NOTEQUAL = 6,: 이전 값보다 같지 않으면 accept한다.
D3DCMP_GREATEREQUAL = 7,: 이전 값보다 크거나 같으면 accept한다
D3DCMP_ALWAYS = 8,:항상 accept한다

D3DCMP_FORCE_DWORD = 0x7fffffff // D3DCMP_FORCE_DWORD 결과를 32bit 사이즈로 바꾼다. 이값은 사용되지 않는다.
} D3DCMPFUNC;

5.6 Quaternion #

* Quaternion회전
D3DXMATRIX *D3DXMatrixRotationQuaternion(
D3DXMATRIX *pOut, // [in, out] 연산 결과인 D3DXMATRIX 구조체의 포인터.
CONST D3DXQUATERNION *pQ ); // in 처리의 기본으로 되는 D3DXQUATERNION 구조체의 포인터.
반환값; 소스의 쿼터니온으로부터 구축된 D3DXMATRIX 구조체의 포인터.

* Quaternion사이의 보간
D3DXQUATERNION *D3DXQuaternionSlerp(
D3DXQUATERNION *pOut, // [in, out] 연산 결과인 D3DXQUATERNION 구조체의 포인터.
CONST D3DXQUATERNION *pQ1, // in 처리의 기본으로 되는 D3DXQUATERNION 구조체의 포인터.
CONST D3DXQUATERNION *pQ2, // in 처리의 기본으로 되는 D3DXQUATERNION 구조체의 포인터.
FLOAT t ); // in 보간 하는 쿼터니온간의 간격을 나타내는 파라미터.
반환값; 보간 결과인 D3DXQUATERNION 구조체의 포인터.

{_r} 메모장으로 가기

April, 2025
 12345
6789101112
13141516171819
20212223242526
27282930 

얕은 지식은 위험하다.

RecentChangesMacro
링크
MoniWikiIdeas
딱지_글로벌게임산업Trend_2011
last modified 2017-05-18 15:53:43
고치기|찾기|쪽 지우기|비슷한 쪽 Valid XHTML 1.0! Valid CSS! powerd by MoniWiki
0.4767 sec