이장에서는 카메라를 초기화 하고 3D 공간에 파란색의 평면 사각형을 띄운다.

=================================================================================
1. 카메라 
카메라를 초기화 할때 필요한 기본적인 변수의 형에 대해서 알아 보자.
카메라에 필요한 D3DXMATRIX는 4 X 4행렬을 나타내는 변수로 D3DMATRIX를 상속 받았다.

typedef struct D3DXMATRIX : public D3DMATRIX 
{
  ........
  ........
  ........
}

typedef struct _D3DMATRIX {
    union {
        struct {
            float        _11, _12, _13, _14;
            float        _21, _22, _23, _24;
            float        _31, _32, _33, _34;
            float        _41, _42, _43, _44;

        };
        float m[4][4];
    };
} D3DMATRIX;

D3DXVECTOR3는 3차원에서 공간좌표를 표시하는 변수로 D3DVECTOR를 상속 받았다.

typedef struct D3DXVECTOR3 : public D3DVECTOR 
{
  ........
  ........
  ........
}

typedef struct _D3DVECTOR {
    float x;
    float y;
    float z;
} D3DVECTOR;

void SetupCamera ()에서 카메라 뷰와 프로젝션을 설정한다.

1) 카메라 뷰 설정 
D3DXMATRIX *D3DXMatrixLookAtLH(
                   D3DXMATRIX *pOut,
                   CONST D3DXVECTOR3 *pEye,
                   CONST D3DXVECTOR3 *pAt,
                   CONST D3DXVECTOR3 *pUp)

첫번째 인자는 함수의 결과값을 받는다.
두번째 인자는 카메라의 원점을 나타낸다.
세번째 인자는 카메라의 타겟 위치를 나타낸다.
네번째 인자는 카메라의 월드 공간의 위쪽 방향을 나타내는데 일반적으로 (0, 1, 0)이다.

카메라 메트릭스를 활성화 시키기 위해서 SetTransform()함수를 사용한다.

HRESULT SetTransform(
  D3DTRANSFORMSTATETYPE State,
  CONST D3DMATRIX* pMatrix
);

첫번째 인자에는 D3DTS_VIEW를 넣어 카메라뷰를 설정한다.
두번째 인자에는 D3DXMatrixLookAtLH()함수의 결과값을 넣는다.

2)프로젝션 설정
공간이 카메라 뷰를 통해서 어떻게 보이는가를 설정하는 함수이다.
D3DXMATRIX *D3DXMatrixPerspectiveFovLH(
              D3DXMATRIX *pOut,
              FLOAT fovy,
              FLOAT Aspect,
              FLOAT zn,
              FLOAT zf);

첫번째 인자는 함수의 결과값을 리턴받는다.
두번째 인자는 카메라 뷰의 보이는 영역(fov)을 라디안으로 나타내는데 일반적으로 D3DX_PI/4를 사용한다.
세번째 인자는 가로 세로 화면 비율이다.
네번째 인자는 카메라 뷰의 NEAR 인자를 나타내는데, 더 가까이 있는 물체는 보이지 않는다.
다섯째 인자는 카메라 뷰의 FAR 인자를 나타내는데, 더 멀리 있는 인자는 보이지 않는다.

프로젝션 메트릭스를 활성화 시키기 위해 SetTransform()함수를 실행한다.
첫번째 인자에 D3DTS_PROJECTION, 두번째 인자에  D3DXMatrixPerspectiveFovLH() 함수의 결과값을 넣는다.

================================================================================= 2. 칼라 사각형 그리기 1)버텍스 버퍼의 타입과 구조체 선언 *** 지금까지는 D3DFVF_XYZRHW옵션을 사용했기 때문에 2D화면에 그리는것과 같은것였다. 이 옵션은 인터페이스나 2D 게임을 만들때, 사용 되는 옵션이다. 버텍스의 포인터와 칼라를 선언한다. struct CUSTOMVERTEX { FLOAT x, y, z; DWORD color; }; #define D3DFVF_CUSTOMVERTEX ( D3DFVF_XYZ | D3DFVF_DIFFUSE) 2) InitD3D()함수에 초기화 추가 *** g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff ); g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); 3D 공간에 그리기 위해서 몇가 렌더링 상태를 설정할 필요가 있다. 자세한 설명은 책이나 MS 문서를 보기 바란다. D3DRS_ZENABLE 옵션은 Z-버퍼를 활성화 시킨다. D3DRS_AMBIENT 옵션은 Ambient Light 칼라를 설정한다. 디폴트로 0이다. D3DRS_LIGHTING 옵션은 라이팅을 활성화 시킨다. 디폴트로 TRUE이다. FALSE 시키지 않으면 사각형이 시커멓게 나온다. 3) 버텍스 포맷 처리 *** void RenderInit() a. 버텍스 버퍼 생성 b. 버텍스 버퍼 락 c. 데이터를 버텍스 버퍼로 복사 d. 버텍스 버퍼 락 해제 a. 버텍스 버퍼 생성 버텍스 버퍼를 생성하기전에 버텍스 버퍼에 들어갈 버텍스 정보를 만들어야 한다. 그림과 코드를 보면 쉬울 겁니다. 다이렉트 X는 왼손 좌표계를 사용한다. 컬링 모드는 디폴트로 D3DCULL_CCW(반시계 방향 컬링)이기 때문에 삼각형의 두르기 순서를 시계 방향으로 그린다.

CUSTOMVERTEX vertex[4]; float fSizeX = 5.0f; float fSizeY = 5.0f; // Create the geometry vertex[0].x = -fSizeX/2; vertex[0].y = fSizeY/2; vertex[0].z = 0.0f; vertex[0].color = 0xff; vertex[1].x = fSizeX/2; vertex[1].y = fSizeY/2; vertex[1].z = 0.0f; vertex[1].color = 0xff; vertex[2].x = -fSizeX/2; vertex[2].y = -fSizeY/2; vertex[2].z = 0.0f; vertex[2].color = 0xff; vertex[3].x = fSizeX/2; vertex[3].y = -fSizeY/2; vertex[3].z = 0.0f; vertex[3].color = 0xff; 버텍스 버퍼를 생성하기 위해서는 CreateVertexBuffer()함수를 사용한다. HRESULT CreateVertexBuffer( UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer ); g_d3d_Device->CreateVertexBuffer(4*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_VertexBuffer) 첫번째 인자는 버텍스 버퍼의 길이로 지금은 4개의 버텍스가 필요합니다. 두번째 인자는 버퍼를 어떻게 사용할것인지 지정한다. 세번째 인자는 사용할 버텍스 포맷을 지정한다. 네번째 인자는 버퍼가 차지할 메모리 풀을 지정한다. 여기서는 디폴트 메모리 풀을 사용 하므로 D3DPOOL_DEFAULT를 사용한다. 마지막 인자는 버퍼 포인터를 지정한다. b. 버텍스 버퍼 락 HRESULT IDirect3DIndexBuffer8::Lock( UINT OffsetToLock, UINT SizeToLock, BYTE** ppbData, DWORD Flags ); g_VertexBuffer->Lock(0, sizeof(vertex), (BYTE**)&lpVertices, 0) 버퍼의 데이터를 수정하기 위해서는 버퍼에 락을 걸고 데이타 버퍼의 포인터를 얻어 온다.. 첫번째 인자는 락을 걸 인덱스 데이터의 옵셋을 지정하는데. 일반적으로 0을 지정한다. 두번째 인자는 락을 걸 버텍스 포맷의 크기를 지정한다. 세번째 인자는 락된 데이터의 포인터를 리턴받는다. 마지막 인자는 연산에 필요한 플래그를 지정한다. c. 데이터를 버텍스 버퍼로 복사 memcpy(lpVertices, vertex, sizeof(vertex)); 버텍스 데이터를 락된 데이터 버퍼로 복사한다. d. 버텍스 버퍼 락 해제 HRESULT IDirect3DIndexBuffer8::Unlock(); Lock()함수를 사용한 후에는 락을 Unlock()함수를 사용해야 한다. 4)지오메트리 출력 *** a. SetStreamSource() b. SetVertexShader() c. DrawPrimitive() a. SetStreamSource() 지오메트리를 출력하기 위해 3D시스템에게 어디서 버텍스 데이터를 가져올것인지 알려 주기위해 SetStreamSource() 함수를 사용한다. HRESULT IDirect3DDevice8::SetStreamSource( UINT StreamNumber, IDirect3DVertexBuffer8* pStreamData, UINT Stride); g_d3d_Device->SetStreamSource(0, g_VertexBuffer, sizeof(CUSTOMVERTEX)); 첫번째 인자는 사용하는 스트림이 어느것인지 지정한다. 두번째 인자는 스트림 데이터의 포인터이다. 마지막 인자는 버텍스 포맷의 크기이다. b. SetVertexShader() 스트림을 설정하고 난후에는 버텍스 타입의 포맷을 알려주기 위해 SetVertexShader()를 함수를 사용한다. 크기를 설정하고 타입을 알려주는 건가.....??? HRESULT IDirect3DDevice8::SetVertexShader(DWORD Handle); g_d3d_Device->SetVertexShader(D3DFVF_CUSTOMVERTEX); c. DrawPrimitive() 셋업한 지오메트리를 렌드링하기 위해 DrawPrimitive()함수를 사용한다. HRESULT IDirect3DDevice8::DrawPrimitive( D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount); g_d3d_Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); 첫번째 인자는 프라이머티브 타입을 지정하는것으로 타입은 아래와 같습니다. typedef enum _D3DPRIMITIVETYPE { D3DPT_POINTLIST = 1, D3DPT_LINELIST = 2, D3DPT_LINESTRIP = 3, D3DPT_TRIANGLELIST = 4, D3DPT_TRIANGLESTRIP = 5, D3DPT_TRIANGLEFAN = 6, D3DPT_FORCE_DWORD = 0x7fffffff } D3DPRIMITIVETYPE; 두번째 인자는 버퍼가 시작할 버퍼의 인덱스다. 마지막 이자는 렌드링 할 프라이머티브 수이다. 이 제 끝난건가... 휴...