반응형

//-----------------------------------------------------------------------------
// File: Meshes.cpp
//
// Desc: 보다 멋진 기하 정보를 출력하기 위해서는 전문적인 3D모델러가 만든 모델을
//       파일로 읽어들이는 것이 일반적이다. 다행스럽게도 D3DX에는 강력한 X파일
//       처리 기능이 있어서 정점 버퍼, 인덱스 버퍼 생성 등의 많은 부분을 대신해 
//       준다. 이번 예제는 D3DXMESH를 사용해 파일을 읽어서 이 파일과 연관된 제질과
//       텍스처를 함께 사용하는 것을 알아본다.
//
//       Note: 이번에 소개 되지는 않짐나 나중에 사용하게 될 강력한 기능 중 하나는
//       FVF를 지정하여 새로운 메시를 복제(clone)하는 것이다. 이 기능을 사용하여
//       텍스처 좌표나 법선벡터 등을 기존 메시에 추가한 새로운 메시를 생성할 수 있다.
//       (나중에 Cg, HLSL 등을 공부할 때 많이 사용될 것이다.
//
// Copyright (c) Microsoft Corporation. All rights reserved.

//-----------------------------------------------------------------------------

// 전역 변수
//-----------------------------------------------------------------------------
LPDIRECT3D9         g_pD3D = NULL; // D3DDevice 생성할 D3D 객체 변수
LPDIRECT3DDEVICE9   g_pd3dDevice = NULL; // 렌더링에 사용될 D3D 디바이스

LPD3DXMESH          g_pMesh = NULL; // 메시 객체
D3DMATERIAL9*       g_pMeshMaterials = NULL; // 메시에 사용될 제질
LPDIRECT3DTEXTURE9* g_pMeshTextures = NULL; // 메시에 사용될 텍스처
DWORD               g_dwNumMaterials = 0L;   // 메시에 사용중인 재질의 수

 


//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Direct3D 초기화
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
    // 디바이스를 생성하기위한 D3D 객체 생성
    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;

    // 디바이스를 생성할 구조체
    // 복잡한 오브젝트를 그리기 위해 Z버퍼를 사용한다.
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof( d3dpp ) );
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

    // 디바이스 생성
    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_pd3dDevice ) ) )
    {
        return E_FAIL;
    }

    // Z버퍼 기능을 켠다.
    g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );

    // 주변광원(ambient)값을 최대 밝기로
    g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );

    return S_OK;
}

 


//-----------------------------------------------------------------------------
// Name: InitGeometry()
// Desc: 메시 읽기, 재질과 텍스처 배열 생성
//-----------------------------------------------------------------------------
HRESULT InitGeometry()
{
 // 재질을 임시로 보관할 버퍼 선언
    LPD3DXBUFFER pD3DXMtrlBuffer;

    // 메시 파일을 읽어 들인다. 재질 정보도 함께 읽는다.
    if( FAILED( D3DXLoadMeshFromX( L"Tiger.x", D3DXMESH_SYSTEMMEM,
                                   g_pd3dDevice, NULL,
                                   &pD3DXMtrlBuffer, NULL, &g_dwNumMaterials,
                                   &g_pMesh ) ) )
    {
        // 현재 폴더에 없으면 상위 폴더 검색
        if( FAILED( D3DXLoadMeshFromX( L"..\\Tiger.x", D3DXMESH_SYSTEMMEM,
                                       g_pd3dDevice, NULL,
                                       &pD3DXMtrlBuffer, NULL, &g_dwNumMaterials,
                                       &g_pMesh ) ) )
        {
            MessageBox( NULL, L"Could not find tiger.x", L"Meshes.exe", MB_OK );
            return E_FAIL;
        }
    }

    // 재질 정보와 텍스처 정보를 따로 뽑아낸다.
    D3DXMATERIAL* d3dxMaterials = ( D3DXMATERIAL* )pD3DXMtrlBuffer->GetBufferPointer();
    g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials];
    if( g_pMeshMaterials == NULL )
        return E_OUTOFMEMORY;
    g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials];
    if( g_pMeshTextures == NULL )
        return E_OUTOFMEMORY;

    for( DWORD i = 0; i < g_dwNumMaterials; i++ )
    {
        // 재질을 복사한다.
        g_pMeshMaterials[i] = d3dxMaterials[i].MatD3D;

        // 재질 주변광원 정보를 Diffuse
        g_pMeshMaterials[i].Ambient = g_pMeshMaterials[i].Diffuse;

        g_pMeshTextures[i] = NULL;
        if( d3dxMaterials[i].pTextureFilename != NULL &
            lstrlenA( d3dxMaterials[i].pTextureFilename ) > 0 )
        {
            // 텍스처를 파일에서 로드한다.
            if( FAILED( D3DXCreateTextureFromFileA( g_pd3dDevice,
                                                    d3dxMaterials[i].pTextureFilename,
                                                    &g_pMeshTextures[i] ) ) )
            {
                // 텍스처를 로드 한다.
                const CHAR* strPrefix = "..\\";
                CHAR strTexture[MAX_PATH];
                strcpy_s( strTexture, MAX_PATH, strPrefix );
                strcat_s( strTexture, MAX_PATH, d3dxMaterials[i].pTextureFilename );
                // 텍스처가 현재 폴더에 없으면 상위 폴더 검색
                if( FAILED( D3DXCreateTextureFromFileA( g_pd3dDevice,
                                                        strTexture,
                                                        &g_pMeshTextures[i] ) ) )
                {
                    MessageBox( NULL, L"Could not find texture map", L"Meshes.exe", MB_OK );
                }
            }
        }
    }

    // 임시로 생성한 재질 버퍼 초기화
    pD3DXMtrlBuffer->Release();

    return S_OK;
}

 


//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: 초기화된 객체들 소거
//-----------------------------------------------------------------------------
VOID Cleanup()
{
    if( g_pMeshMaterials != NULL )
        delete[] g_pMeshMaterials;

    if( g_pMeshTextures )
    {
        for( DWORD i = 0; i < g_dwNumMaterials; i++ )
        {
            if( g_pMeshTextures[i] )
                g_pMeshTextures[i]->Release();
        }
        delete[] g_pMeshTextures;
    }
    if( g_pMesh != NULL )
        g_pMesh->Release();

    if( g_pd3dDevice != NULL )
        g_pd3dDevice->Release();

    if( g_pD3D != NULL )
        g_pD3D->Release();
}

 

//-----------------------------------------------------------------------------
// Name: SetupMatrices()
// Desc: 월드, 뷰, 프로젝션 메트릭스를 설정한다.
//-----------------------------------------------------------------------------
VOID SetupMatrices()
{
    // 월드 행렬 설정
    D3DXMATRIXA16 matWorld;
    D3DXMatrixRotationY( &matWorld, timeGetTime() / 1000.0f );
    g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

    // 뷰 행렬 설정
    D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f );
    D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
    D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
    D3DXMATRIXA16 matView;
    D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
    g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

    // 프로젝션 행렬 설정
    D3DXMATRIXA16 matProj;
    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f );
    g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}

 


//-----------------------------------------------------------------------------
// Name: Render()
// Desc: 화면 그리기
//-----------------------------------------------------------------------------
VOID Render()
{
    // 후면 버퍼와 Z버퍼를 지운다.
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
                         D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 );

    // 렌더링 시작
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
        // 월드, 뷰, 프로젝션 행렬 설정
        SetupMatrices();

        // 메시는 재질이 다른 메시별로 부분집합을 이루고 있다.
        // 이들을 루프를 수행하여 모두 그려준다.
        for( DWORD i = 0; i < g_dwNumMaterials; i++ )
        {
            // 부분집합 메시의 재질과 텍스처 설정
            g_pd3dDevice->SetMaterial( &g_pMeshMaterials[i] );
            g_pd3dDevice->SetTexture( 0, g_pMeshTextures[i] );

            // 부분집합 메시 출력
            g_pMesh->DrawSubset( i );
        }

        // 렌더링 종료
        g_pd3dDevice->EndScene();
    }

    // 후면 버퍼를 보이는 화면으로
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

 


//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: 윈도우 메시지 프로시저
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:
            Cleanup();
            PostQuitMessage( 0 );
            return 0;

  case WM_KEYDOWN: // 키를 눌렀을때
   if( wParam == VK_ESCAPE ) { // esc를 눌렀을때
    ::DestroyWindow(hWnd);
    return 0;
   }
 }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

 


//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: 프로그램 시작점
//-----------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
    // 윈도우 클래스 등록
 WNDCLASSEX wc =
    {
        sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
        GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
        L"D3D Tutorial", NULL
    };
    RegisterClassEx( &wc );

    // 윈도우창 생성
    HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 06: Meshes",
                              WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                              NULL, NULL, wc.hInstance, NULL );

    // Direct3D 초기화
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    {
        // 기하 정보 초기화
        if( SUCCEEDED( InitGeometry() ) )
        {
            // 윈도우 출력
            ShowWindow( hWnd, SW_SHOWDEFAULT );
            UpdateWindow( hWnd );

            // 메시지 루프
            MSG msg;
            ZeroMemory( &msg, sizeof( msg ) );
            while( msg.message != WM_QUIT )
            {
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
                else
                    Render();
            }
        }
    }
 //등록된 클래스 소거
    UnregisterClass( L"D3D Tutorial", wc.hInstance );
    return 0;
}

반응형

'DirectX > DirectX 9.0' 카테고리의 다른 글

[DirectX 9.0] Textures  (0) 2014.02.11
[DirectX 9.0] Lights  (0) 2014.02.11
[DirectX 9.0] Matrices  (0) 2014.02.11
[DirectX 9.0] Vertices  (0) 2014.02.11
CreateDevice  (0) 2011.03.02
반응형

//-----------------------------------------------------------------------------
// File: Textures.cpp
//
// Desc: 보다 좋은 광원과 제질은 3차원 오브체트는 텍스쳐와 결합될 때 더욱 현실감
//   있게 된다. 텍스처란 마치 벽지 같은 것으로, 적당하게 늘이거나 줄여서 면에
//       붙이게 된다. 일반적으로 텍스처는 이미지 파일(jpg, bmp, tga등)을 D3DX 계열
//   의 함수를 사용해서 읽어들여서 사용하게 된다. 정점ㅈ 버퍼와 마찬가지로 
//       Lock()과 Unlock() 함수를 사용해서 메모리에 직접 접근할 수도 있다. 이렇게
//   생성한 텍스처를 면에 붙이는 행위를 맵핑이라고 한다.
//
//   텍스쳐와 기하 정보와 연결되기 위해서 텍스쳐 좌표계를 갖게 되는데, 각각의
//       정점은 이러한 텍스처 좌표를 포함하고 있어야 한다. 일반적으로 (U,V)좌표계를
//       사용하고 U,V의 값은 0.0 ~ 0.1 사이의 값이다. 텍스처 좌표는 최초에 설정될 수
//       도 있지만 실시간으로 직접 계산하여 더 다양한 효과를 낼 수도 있다.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// 아래 주석을 지우면 텍스쳐가 고정된 것 처럼 보여진다.

//#define SHOW_HOW_TO_USE_TCI

//-----------------------------------------------------------------------------
// 전역 변수
//-----------------------------------------------------------------------------
LPDIRECT3D9             g_pD3D = NULL; // D3DDevice를 생성할 D3D객체 변수
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // 렌더링에 사용될 D3D 디바이스
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // 정점을 보관할 정점 버퍼
LPDIRECT3DTEXTURE9      g_pTexture = NULL; // 텍스처 정보

//정점을 정의할 구조체. 텍스처 좌표가 추가 되었다.
struct CUSTOMVERTEX
{
    D3DXVECTOR3 position; // 3차원 좌표
 D3DXVECTOR3 normal;   // 정점의 법선벡터
 D3DCOLOR color;    // 색상
#ifndef SHOW_HOW_TO_USE_TCI
    FLOAT tu, tv;   // 텍스처 좌표
#endif
};

// O사용자 정점 구조체에 관한 정보를 나타내는 FVF값
#ifdef SHOW_HOW_TO_USE_TCI
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
#else
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX1)
#endif

 

//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: IDirect3D 초기화
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
    // 디바이스를 생성하기 위한 D3D 객체 생성.
    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;

    // 디바이스를 생성할 구조체
    // 복잡한 오브젝트를 사용하기 위해, Z버퍼를 생성한다.
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof( d3dpp ) );
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

    // Create the D3DDevice
    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_pd3dDevice ) ) )
    {
        return E_FAIL;
    }

    // 컬러 기능을 끈다
    g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

    // 조명 기능을 켠다.
    g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );

    // Z버퍼 기능을 켠다.
    g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );

    return S_OK;
}

 


//-----------------------------------------------------------------------------
// Name: InitGeometry()
// Desc: 기하 정보 초기화
//-----------------------------------------------------------------------------
HRESULT InitGeometry()
{
    // D3DX 계열 함수를 사용해서 파일로 부터 텍스처 생성(babana.bmp)
    if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"banana.bmp", &g_pTexture ) ) )
    {
        // 현제 폴더에 파일이 없으면 상위 폴더 검색
        if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"..\\banana.bmp", &g_pTexture ) ) )
        {
            MessageBox( NULL, L"Could not find banana.bmp", L"Textures.exe", MB_OK );
            return E_FAIL;
        }
    }

    // 정점 버퍼 생성
    if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50 * 2 * sizeof( CUSTOMVERTEX ),
                                                  0, D3DFVF_CUSTOMVERTEX,
                                                  D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
    {
        return E_FAIL;
    }

    // 정점 버퍼를 채운다. 텍스처 U,V좌표값을 0.0~1.0 사이의 값으로 채운다.
    CUSTOMVERTEX* pVertices;
    if( FAILED( g_pVB->Lock( 0, 0, ( void** )&pVertices, 0 ) ) )
        return E_FAIL;
    for( DWORD i = 0; i < 50; i++ )
    {
        FLOAT theta = ( 2 * D3DX_PI * i ) / ( 50 - 1 );

        pVertices[2 * i + 0].position = D3DXVECTOR3( sinf( theta ), -1.0f, cosf( theta ) );
  // 실린더 아래쪽 원통의 법선 벡터
  pVertices[2 * i + 0].normal = D3DXVECTOR3( sinf( theta ), 0.0f, cosf( theta ) );
  pVertices[2 * i + 0].color = 0xffffffff;
#ifndef SHOW_HOW_TO_USE_TCI
        pVertices[2 * i + 0].tu = ( ( FLOAT )i ) / ( 50 - 1 );
        pVertices[2 * i + 0].tv = 1.0f;
#endif

        pVertices[2 * i + 1].position = D3DXVECTOR3( sinf( theta ), 1.0f, cosf( theta ) );
  // 실린더 위쪽 원통의 법선 벡터
  pVertices[2 * i + 1].normal = D3DXVECTOR3( sinf( theta ), 0.0f, cosf( theta ) );
  pVertices[2 * i + 1].color = 0xff808080;
#ifndef SHOW_HOW_TO_USE_TCI
        pVertices[2 * i + 1].tu = ( ( FLOAT )i ) / ( 50 - 1 );
        pVertices[2 * i + 1].tv = 0.0f;
#endif
    }
    g_pVB->Unlock();

    return S_OK;
}

 


//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: 초기화된 객체들 소거
//-----------------------------------------------------------------------------
VOID Cleanup()
{
    if( g_pTexture != NULL )
        g_pTexture->Release();

    if( g_pVB != NULL )
        g_pVB->Release();

    if( g_pd3dDevice != NULL )
        g_pd3dDevice->Release();

    if( g_pD3D != NULL )
        g_pD3D->Release();
}

 

//-----------------------------------------------------------------------------
// Name: SetupMatrices()
// Desc: 월드, 뷰, 프로젝션 메트릭스를 설정한다.
//-----------------------------------------------------------------------------
VOID SetupMatrices()
{
    // 월드행렬 설정
    D3DXMATRIXA16 matWorld;
    D3DXMatrixIdentity( &matWorld );
    D3DXMatrixRotationX( &matWorld, timeGetTime() / 1000.0f );
    g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

    // 뷰행렬 설정
    D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f );
    D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
    D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
    D3DXMATRIXA16 matView;
    D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
    g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

    // 프로젝션 행렬 설정
    D3DXMATRIXA16 matProj;
    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f );
    g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}


//-----------------------------------------------------------------------------
// Name: SetupLights()
// Desc: 재질과 조명을 설정한다.
//-----------------------------------------------------------------------------
VOID SetupLights()
{
 // 재질 설정. 여기서는 주변색(Ambient)과 확산색(Diffuse)을 사용 한다.
 // 색상은 노란색. 재질은 디바이스에 단 하나만 설정할수 있다.
 D3DMATERIAL9 mtrl;
 ZeroMemory( &mtrl, sizeof( D3DMATERIAL9 ) );
 mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;
 mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;
 mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f;
 mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
 g_pd3dDevice->SetMaterial( &mtrl );

 // 흰색의 방향성 광원을 설치한다.
 // 많은 조명을 사요할 경우 렌더링 시간이 오래 걸린다.
 // 하지만, 여기서는 하나의 조명만 사용한다. 그리고,
 // 우리는 D3D광원을 사용 렌더링 한다.
 D3DXVECTOR3 vecDir;
 D3DLIGHT9 light;
 ZeroMemory( &light, sizeof( D3DLIGHT9 ) );
 light.Type = D3DLIGHT_DIRECTIONAL;
 light.Diffuse.r = 1.0f;
 light.Diffuse.g = 1.0f;
 light.Diffuse.b = 1.0f;
 vecDir = D3DXVECTOR3( cosf( timeGetTime() / 350.0f ),
  1.0f,
  sinf( timeGetTime() / 350.0f ) );
 D3DXVec3Normalize( ( D3DXVECTOR3* )&light.Direction, &vecDir );// 단위벡터로 만든다
 light.Range = 1000.0f; // 광원이 갈수 있는 최대 거리
 g_pd3dDevice->SetLight( 0, &light );
 g_pd3dDevice->LightEnable( 0, TRUE );
 g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );

 // 환경광원 값 설정
 g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00202020 );
}

 

//-----------------------------------------------------------------------------
// Name: Render()
// Desc: 화면 그리기
//-----------------------------------------------------------------------------
VOID Render()
{
    // 후면 버퍼와 Z버퍼를 지운다.
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
                         D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 );

    // 렌더링 시작
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
  // 광원과 재질 설정
  SetupLights();

        // 메트릭스 설정
        SetupMatrices();

        // 생성한 텍스쳐를 0번 텍스처 스테이지에 올린다.
        // 텍스처 스제이지는 여러 장의 텍스처와 색상 정보를 섞어서 출력할 때 사용된다.
  // 여기서 텍스처의 색상과 정점의 색상 정보를 modulate 연산으로 섞어서 출력한다.
        g_pd3dDevice->SetTexture( 0, g_pTexture );
        g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
        g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
        g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
        g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );

#ifdef SHOW_HOW_TO_USE_TCI
        // Note: to use D3D texture coordinate generation, use the stage state
 // D3DTSS_TEXCOORDINDEX, as shown below. In this example, we are using
 // the position of the vertex in camera space (D3DTSS_TCI_CAMERASPACEPOSITION)
 // to generate texture coordinates. Camera space is the vertex position
 // multiplied by the World and View matrices.  The tex coord index (TCI)  
 // parameters are passed into a texture transform, which is a 4x4 matrix  
 // which transforms the x,y,z TCI coordinates into tu, tv texture coordinates.

 // In this example, the texture matrix is setup to transform the input
 // camera space coordinates (all of R^3) to projection space (-1,+1) 
 // and finally to texture space (0,1).
 //    CameraSpace.xyzw = (input vertex position) * (WorldView)
 //    ProjSpace.xyzw = CameraSpace.xyzw * Projection           //move to -1 to 1
 //    TexSpace.xyzw = ProjSpace.xyzw * ( 0.5, -0.5, 1.0, 1.0 ) //scale to -0.5 to 0.5 (flip y)
 //    TexSpace.xyzw += ( 0.5, 0.5, 0.0, 0.0 )                  //shift to 0 to 1

 // Setting D3DTSS_TEXTURETRANSFORMFLAGS to D3DTTFF_COUNT4 | D3DTTFF_PROJECTED
 // tells D3D to divide the input texture coordinates by the 4th (w) component.
 // This divide is necessary when performing a perspective projection since
 // the TexSpace.xy coordinates prior to the homogeneous divide are not actually 
 // in the 0 to 1 range.
 D3DXMATRIXA16 mTextureTransform;
 D3DXMATRIXA16 mProj;
 D3DXMATRIXA16 mTrans;
 D3DXMATRIXA16 mScale;

 g_pd3dDevice->GetTransform( D3DTS_PROJECTION, &mProj );
 D3DXMatrixTranslation( &mTrans, 0.5f, 0.5f, 0.0f );
 D3DXMatrixScaling( &mScale, 0.5f, -0.5f, 1.0f );
 mTextureTransform = mProj * mScale * mTrans;

 g_pd3dDevice->SetTransform( D3DTS_TEXTURE0, &mTextureTransform );
 g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4 | D3DTTFF_PROJECTED );
 g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION );
    #endif

        // 정점을 그린다.
        g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
        g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
        g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 * 50 - 2 );

       // 렌더링 종료
        g_pd3dDevice->EndScene();
    }

    // 후면 버퍼를 보이는 화면으로
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

 


//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: 윈도우 메시지 프로시저
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:
            Cleanup();
            PostQuitMessage( 0 );
            return 0;

  case WM_KEYDOWN: // 키를 눌렀을때
   if( wParam == VK_ESCAPE ) { // esc를 눌렀을때
    ::DestroyWindow(hWnd);
    return 0;
   }
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

 


//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: 프로그램 시작점
//-----------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
    // 윈도우 클래스 등록
    WNDCLASSEX wc =
    {
        sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
        GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
        L"D3D Tutorial", NULL
    };
    RegisterClassEx( &wc );

    // 윈도우창 생성
    HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 05: Textures",
                              WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                              NULL, NULL, wc.hInstance, NULL );

    // Direct3D 초기화
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    {
        // 기하 정보 초기화
        if( SUCCEEDED( InitGeometry() ) )
        {
            // 윈도우 출력
            ShowWindow( hWnd, SW_SHOWDEFAULT );
            UpdateWindow( hWnd );

            // 메시지 루프
            MSG msg;
            ZeroMemory( &msg, sizeof( msg ) );
            while( msg.message != WM_QUIT )
            {
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
                else
                    Render();
            }
        }
    }
 //등록된 클래스 소거
    UnregisterClass( L"D3D Tutorial", wc.hInstance );
    return 0;
}

반응형

'DirectX > DirectX 9.0' 카테고리의 다른 글

[DirectX 9.0] Meshes  (0) 2014.02.11
[DirectX 9.0] Lights  (0) 2014.02.11
[DirectX 9.0] Matrices  (0) 2014.02.11
[DirectX 9.0] Vertices  (0) 2014.02.11
CreateDevice  (0) 2011.03.02
반응형

//-----------------------------------------------------------------------------
// File: Lights.cpp
//
// Desc: 조명을 사용하면 훨씬더 극적인 연출이 가능하다
//       조명을 사용하기 위해서는 광원이나 재질을 생성해야 한다. 또 기하정보에
//       법선벡터 정보를 포함하고 있어야 한다.
//       광원은 위치, 색상, 방향 등의 정보를 바탕으로 생성된다.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------

// 전역 변수
//-----------------------------------------------------------------------------
LPDIRECT3D9             g_pD3D = NULL; // D3DDevice를 생성할 D3D객체 변수
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // 렌더링에 사용될 D3D 디바이스
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // 정점을 보관할 정점 버퍼

// 정점을 정의할 구조체.
// 광원을 사용하기 때문에 법선 벡터가 있어야 한다.
struct CUSTOMVERTEX
{
    D3DXVECTOR3 position; // 정점의 3차원 자표
    D3DXVECTOR3 normal;   // 정점의 법선벡터
};

// 사용자 정점 구조체에 관한 정보를 나타내는 FVF값
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL)

 


//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Direct3D 초기화
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
    // 디바이스를 생성하기 위한 D3D 객체 생성.
    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;

    // 디바이스를 생성할 구조체
    // Z버퍼를 사용한다.
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof( d3dpp ) );
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;

    // D3DDevice 생성
    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_pd3dDevice ) ) )
    {
        return E_FAIL;
    }

    // 컬러기능을 끈다
    g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

    // Z버퍼 기능을 켠다.
    g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );

    return S_OK;
}

 


//-----------------------------------------------------------------------------
// Name: InitGeometry()
// Desc: 기하 정보 초기화
//-----------------------------------------------------------------------------
HRESULT InitGeometry()
{
    // 정점 버퍼 생성
    if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50 * 2 * sizeof( CUSTOMVERTEX ),
                                                  0, D3DFVF_CUSTOMVERTEX,
                                                  D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
    {
        return E_FAIL;
    }

    // 정점 버퍼를 채운다.알고리즘을 사용해 실린더를 만든다.
    // 법선벡터를 포함하고 조명을 사용한다.
    CUSTOMVERTEX* pVertices;
    if( FAILED( g_pVB->Lock( 0, 0, ( void** )&pVertices, 0 ) ) )
        return E_FAIL;
    for( DWORD i = 0; i < 50; i++ )
    {
        FLOAT theta = ( 2 * D3DX_PI * i ) / ( 50 - 1 );
  // 실린더 아래쪽 원통의 좌표
        pVertices[2 * i + 0].position = D3DXVECTOR3( sinf( theta ), -1.0f, cosf( theta ) );
        // 실린더 아래쪽 원통의 법선 벡터
  pVertices[2 * i + 0].normal = D3DXVECTOR3( sinf( theta ), 0.0f, cosf( theta ) );
        // 실린더 위쪽 원통의 좌표
  pVertices[2 * i + 1].position = D3DXVECTOR3( sinf( theta ), 1.0f, cosf( theta ) );
        // 실린더 위쪽 원통의 법선 벡터
  pVertices[2 * i + 1].normal = D3DXVECTOR3( sinf( theta ), 0.0f, cosf( theta ) );
    }
    g_pVB->Unlock();

    return S_OK;
}

 


//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: 초기화된 객체들 소거
//-----------------------------------------------------------------------------
VOID Cleanup()
{
    if( g_pVB != NULL )
        g_pVB->Release();

    if( g_pd3dDevice != NULL )
        g_pd3dDevice->Release();

    if( g_pD3D != NULL )
        g_pD3D->Release();
}

 

//-----------------------------------------------------------------------------
// Name: SetupMatrices()
// Desc: 월드, 뷰, 프로젝션 메트릭스를 설정한다.
//-----------------------------------------------------------------------------
VOID SetupMatrices()
{
    // 월드행렬 설정
    D3DXMATRIXA16 matWorld;
    D3DXMatrixIdentity( &matWorld ); // 월드 행렬을 단위 행렬로 설정
    D3DXMatrixRotationX( &matWorld, timeGetTime() / 500.0f ); // x축을 중심으로 회전
    g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); // 장치에 월드행렬 적용

    // 뷰행렬 설정
    D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f );
    D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
    D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
    D3DXMATRIXA16 matView;
    D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
    g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

    // 프로젝션 행렬 설정
    D3DXMATRIXA16 matProj;
    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f );
    g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}

 


//-----------------------------------------------------------------------------
// Name: SetupLights()
// Desc: 재질과 조명을 설정한다.
//-----------------------------------------------------------------------------
VOID SetupLights()
{
    // 재질 설정. 여기서는 주변색(Ambient)과 확산색(Diffuse)을 사용 한다.
    // 색상은 노란색. 재질은 디바이스에 단 하나만 설정할수 있다.
    D3DMATERIAL9 mtrl;
    ZeroMemory( &mtrl, sizeof( D3DMATERIAL9 ) );
    mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;
    mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;
    mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f;
    mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
    g_pd3dDevice->SetMaterial( &mtrl );

    // 흰색의 방향성 광원을 설치한다.
    // 많은 조명을 사요할 경우 렌더링 시간이 오래 걸린다.
    // 하지만, 여기서는 하나의 조명만 사용한다. 그리고,
    // 우리는 D3D광원을 사용 렌더링 한다.
    D3DXVECTOR3 vecDir;
    D3DLIGHT9 light;
    ZeroMemory( &light, sizeof( D3DLIGHT9 ) );
    light.Type = D3DLIGHT_DIRECTIONAL;
    light.Diffuse.r = 1.0f;
    light.Diffuse.g = 1.0f;
    light.Diffuse.b = 1.0f;
    vecDir = D3DXVECTOR3( cosf( timeGetTime() / 350.0f ),
                          1.0f,
                          sinf( timeGetTime() / 350.0f ) );
    D3DXVec3Normalize( ( D3DXVECTOR3* )&light.Direction, &vecDir );// 단위벡터로 만든다
    light.Range = 1000.0f; // 광원이 갈수 있는 최대 거리
    g_pd3dDevice->SetLight( 0, &light );
    g_pd3dDevice->LightEnable( 0, TRUE );
    g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );

    // 환경광원 값 설정
    g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00202020 );
}

 


//-----------------------------------------------------------------------------
// Name: Render()
// Desc: 화면 그리기
//-----------------------------------------------------------------------------
VOID Render()
{
    // 후면 버퍼와 Z버퍼를 지운다.
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
                         D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 );

    // 렌더링 시작
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
        // 광원과 재질 설정
        SetupLights();

        // 메트릭스 설정
        SetupMatrices();

        // 정점을 그린다.
        g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
        g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
        g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 * 50 - 2 );

        // 렌더링 종료
        g_pd3dDevice->EndScene();
    }

    // 후면 버퍼를 보이는 화면으로
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

 


//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: 윈도우 메시지 프로지서
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:
            Cleanup();
            PostQuitMessage( 0 );
            return 0;

  case WM_KEYDOWN: // 키를 눌렀을때
   if( wParam == VK_ESCAPE ) { // esc를 눌렀을때
    ::DestroyWindow(hWnd);
    return 0;
   }
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

 


//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: 프로그램 시작점
//-----------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
    // 윈도우 클래스 등록
    WNDCLASSEX wc =
    {
        sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
        GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
        L"D3D Tutorial", NULL
    };
    RegisterClassEx( &wc );

    // Create the application's window
    HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 04: Lights",
                              WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                              NULL, NULL, wc.hInstance, NULL );

    // 윈도우 창 생성
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    {
        // 정점 버퍼 초기화
        if( SUCCEEDED( InitGeometry() ) )
        {
            // 윈도우 출력
            ShowWindow( hWnd, SW_SHOWDEFAULT );
            UpdateWindow( hWnd );

            // 메시지 루프
            MSG msg;
            ZeroMemory( &msg, sizeof( msg ) );
            while( msg.message != WM_QUIT )
            {
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
                else
                    Render();
            }
        }
    }

 //등록된 클래스 소거
    UnregisterClass( L"D3D Tutorial", wc.hInstance );
    return 0;
}

 

 

 

- 재질의 종류
재질이란 메시의 표면 상태를 말하는 것으로 빛이 물체의 표면에서 반사되어 변화된 뒤
사람의 눈에 들어오기까지의 과정을 을 수학적으로 모델링하기 위해서 사용하는 값들.

주변색(ambient) : 광원의 위치와 무관학 똑같은 양으로 모든 점에서 반사되는 색
확산색(diffuse) : 광원에 반사될 때 출력되는 가장 주된 색
반사색(specular) : 특정한 방향으로만 반사되는 색. 광원의 위치와 카메라의 위치에 따라서 달라진다.
방출색(emissive) : 메시 표면에서 자체적으로 방출되는 색. 단 이 빛이 다른 메시에 영향을
   주지는 못한다.


- 광원의 종류


 

광원모델은 D3D의 고정 함수 파이프라인을 사용할 때만 유효하고, 정점 세이더와 픽셀 셰이더를
 사용하게 되면 모두 무용지물이 된다.

반응형

'DirectX > DirectX 9.0' 카테고리의 다른 글

[DirectX 9.0] Meshes  (0) 2014.02.11
[DirectX 9.0] Textures  (0) 2014.02.11
[DirectX 9.0] Matrices  (0) 2014.02.11
[DirectX 9.0] Vertices  (0) 2014.02.11
CreateDevice  (0) 2011.03.02
반응형

//-----------------------------------------------------------------------------
// File: Matrices.cpp
//
// Desc: 우리는 이제 장치를 생성하고 2D 정점을 렌더링하는 법을 알았다.
//   이 튜토리얼은 다음으로 기하학적인 3D를 렌더링을 배운다.
//       기하학적 3D를 다루기 위해서는 4x4 메트릭스 변환을 이용해 기하학적으로
//       변환(이동), 회전, 크기조정 그리고 카메라를 조종할수 있다.
//       
//   3차원 모델계 좌표를 사용하는데, 우리가 월드 변환을 하여 이동, 회전,
//   크기 조정할수 있다. 이떄 월드 행렬이 사용된다. 다시 월드 좌표계의 기하
//   정보를 카메라 좌표계로 변환한다.
//   기하학적 월드좌표를 사용하기 위해서는 카메라의 위치나 눈의 위치 월드계의
//       어느곳을 보고 있는지가 필요하다.
//       또하나의 변환은 view matrix에 의한 시점의 위치와 회전을 한다.
//       마지막 변환으로 투영 변환이 있다. 프로젝션은 3D를 우리가 보이는 
//   2D 화면으로 변환한다.
//
//       OpenGL에서는 행렬 연산 함수를 직접 작성해야 하지만, D3D에서는 D3DX라는 
//   유틸리티 함수들이 여러 개 존재한다. 여기서는 D3DX 계열 함수를 사용할
//   것이다.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------

// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9             g_pD3D = NULL; // D3DDevice를 생성할 D3D객체 변수
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // 렌더링에 사용될 D3D 디바이스
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // 정점을 보관할 정점 버퍼

// 정점을 정의할 구조체
struct CUSTOMVERTEX
{
 FLOAT x, y, z; // 정점의 변화된 좌표(rhw값이 있으면 변환이 완료된 정점)
 DWORD color;        // 정점의 색상
};

// 사용자 정점 구조체에 관한 정보를 나타내는 FVF값
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)

 


//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Direct3D 초기화
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
   if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;

    // 디바이스 생성을 위한 구조체
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof( d3dpp ) );
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

    // D3DDevice 장치 생성
    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_pd3dDevice ) ) )
    {
        return E_FAIL;
    }

    // 컬러 기능을 끈다. 삼각형의 앞면, 뒷면을 모두 렌더링 한다.
    g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );

    // 정점에 색상값이 있으므로, 광원의 기능을 끈다.
    g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );

    return S_OK;
}

 


//-----------------------------------------------------------------------------
// Name: InitGeometry()
// Desc: 기하 정보 초기화
//-----------------------------------------------------------------------------
HRESULT InitGeometry()
{
    // 삼각형을 렌더링 하기 위해 세개의 정점 선언
    CUSTOMVERTEX g_Vertices[] =
    {
        { -1.0f, -1.0f, 0.0f, 0xffff0000, },
        {  1.0f, -1.0f, 0.0f, 0xff0000ff, },
        {  0.0f,  1.0f, 0.0f, 0xffffffff, },
    };

    // 정점 버퍼 생성
    if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3 * sizeof( CUSTOMVERTEX ),
                                                  0, D3DFVF_CUSTOMVERTEX,
                                                  D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
    {
        return E_FAIL;
    }
 
    // 정점 버퍼를 값으로 채운다.
    VOID* pVertices;
    if( FAILED( g_pVB->Lock( 0, sizeof( g_Vertices ), ( void** )&pVertices, 0 ) ) )
        return E_FAIL;
    memcpy( pVertices, g_Vertices, sizeof( g_Vertices ) );
    g_pVB->Unlock();

    return S_OK;
}

 


//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: 초기화된 객체들 소거
//-----------------------------------------------------------------------------
VOID Cleanup()
{
    if( g_pVB != NULL )
        g_pVB->Release();

    if( g_pd3dDevice != NULL )
        g_pd3dDevice->Release();

    if( g_pD3D != NULL )
        g_pD3D->Release();
}

 

//-----------------------------------------------------------------------------
// Name: SetupMatrices()
// Desc: 행렬은 세 개가 있고, 월드. 뷰, 프로젝션 행렬이다.
//-----------------------------------------------------------------------------
VOID SetupMatrices()
{
    // 월드 행렬, 우리가 물체를 Y축으로 돌리기 위해 사용
    D3DXMATRIXA16 matWorld;

    // 회전 행렬 설정은일반적으로 전체 한바퀴 회전은 2*PI radians 이다. 
    // float 연산의 정밀도를 위해 1000으로 나머지 연산을 한다.
    UINT iTime = timeGetTime() % 1000;
 // 1000미리 초마다 한 바퀴씩 회전하는 애니메이션 행렬을 만든다.
    FLOAT fAngle = iTime * ( 2.0f * D3DX_PI ) / 1000.0f; 
    D3DXMatrixRotationY( &matWorld, fAngle );
 // 생성한 회전 행렬을 월드 행렬로 디바이스에 설정
    g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );

 // 뷰행렬을 정의하기 위해서는 세가지 값이 필요하다.
 // 눈의 위치, 눈이 바라보는 위치, 천정 방향을 나타내는 상방벡터
 // 위 세가지의 값으로 뷰 행렬을 생성 한다.
 D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f );
    D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
    D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
    D3DXMATRIXA16 matView;
    D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
 // 생성한 뷰 행렬을 장치에 적용한다.
    g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

 // 프로젝션 행렬을 정의하기 위해서는 시야각(FOV=Field Of View)과
 // 종회비(aspect ratio), 클리핑 평면의 값이 필요하다.
    D3DXMATRIXA16 matProj;
    D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f );
    g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}

 

//-----------------------------------------------------------------------------
// Name: Render()
// Desc: 화면을 그린다
//-----------------------------------------------------------------------------
VOID Render()
{
    // 백버퍼를 검은색으로 지운다.
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 0 ), 1.0f, 0 );

    // 렌더링 시작
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
        // 월드, 뷰, 프로젝션 메트릭스를 설정한다
        SetupMatrices();

        // 정점 정보를 렌더링 한다
        g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
        g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
        g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 1 );

        // 렌더링 종료
        g_pd3dDevice->EndScene();
    }

 // 후면 버퍼를 보이는 화면으로 
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

 


//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: 윈도우 메시지 처리
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:
            Cleanup();
            PostQuitMessage( 0 );
            return 0;

  case WM_KEYDOWN: // 키를 눌렀을때
   if( wParam == VK_ESCAPE ) { // esc를 눌렀을때
    ::DestroyWindow(hWnd);
    return 0;
   }
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

 


//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: 프로그램 시작 지점
//-----------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
 // 윈도우 클래스 등록
    WNDCLASSEX wc =
    {
        sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
        GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
        L"D3D Tutorial", NULL
    };
    RegisterClassEx( &wc );

 // 윈도우 창 생성
    HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 03: Matrices",
                              WS_OVERLAPPEDWINDOW, 100, 100, 256, 256,
                              NULL, NULL, wc.hInstance, NULL );

 // Direct3D 초기화
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    {
  // 정점 버퍼 초기화
        if( SUCCEEDED( InitGeometry() ) )
        {
   // 윈도우 출력
            ShowWindow( hWnd, SW_SHOWDEFAULT );
            UpdateWindow( hWnd );

            // 메시지 루프
            MSG msg;
            ZeroMemory( &msg, sizeof( msg ) );
            while( msg.message != WM_QUIT )
            {
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
                else
                    Render();
            }
        }
    }
 // 등록된 클래스 소거
    UnregisterClass( L"D3D Tutorial", wc.hInstance );
    return 0;
}

 

 

 

 

- 월드 변환(World transform)
 3차원 그래픽에서 모든 정점은 지역 좌표계(로컬 좌표계, 모델 좌표계) 값을 갖는다.
이 값들은 최초에 3차원 데이터가 생성되는 시점에서 기준이 되는 원점을 중심으로 한 좌표계이다.
 모든 물체들이 각각의 고유한 원점을 기준으로 모델링 되어 있으므로 여러개의 물체를 3차원 공간에
 출력할 경우 이들 물체들이 원점을 공유하게 되는 현상이 발생한다.

 (원점에서 물체가 겹쳐서 나타남)

 로컬좌표계를 월드 좌표계로 변화하는 행렬을 간단하게 변환 행렬(Transform Matrix)이라 하며
줄여서 TM이라고 부른다. 100개의 물체를 3차원 공간에 그리려면 100개의 TM이 필요하다.
 과거에는 TM값을 적용해서 물체를 그리기 위해 루프를 돌며 정점과 TM을 일일이 곱해주는 연산을
했지만 D3D 7.0 이후부터는 그렇게 할 경우 TnL지원을 받지 못한다. 
 따라서 TM은 반드시 SetTransform(D3DTS_WORLD, &matWorld)처럼 해주어야 하드웨어 가속을 받을수
있다.


- 카메라 변화(Camera transform)
 3차원 월드 좌표계를 카메라를 기준으로 한 카메라 좌표계로 변환하는 것을 말한다.

 카메라 변환 행렬 계산은 D3DMatrixLookAtLH(&matView, &vEyePt, &LookatPt, &vUpVec) 를 사용 한다.
matView : 변환 행렬이 들어갈 행렬 구조체,
vEyePt : 카메라의 위치 월드 좌표
LookatPt : 카메라가 바라보는 위치 월드 좌표
vUpVec : 카메라의 상방로컬벡터

 카메라 변환 행렬 적용은 SetTransform(D3DTS_VIEW, &matView)처럼 적용해주어야 한다.


- 투영 변환(Projection transform)
 월드 좌표계와 카메라는 모두 3차원 좌표계다. 하지만 우리가 모니터를 통해서 보는 화면은 2차원
화면이다. 그렇기 때문에 3차원을 우리가 볼수있는 2차원으로 변환이 필요하다. 가장 쉬운 방법은
3개의 축중에서 한개의 축을 버리고 2개의 축으로 2차원 좌표계로 변환된다.
 투영에는 가장 많이 사용하는 원근 투영(perspective projection) 기법으로 직교투영 법이 있다.

 투영 변환 행렬 계산은 D3DXMatrixPerspectiveFovLH(&matProj, fov, Sw/Sh, Zn, Zf) 를 사용 한다.
matProj : 변환 행렬이 들어갈 행렬 구조체
fov : 시야 각 (Field Of View)
Sw/Sh : 종횡비(가로세로의 비율)
Zn : 가까운 클리핑 평면(near clipping plane)
Zf : 먼 클리핑 평면(far clipping plane)

 투영 변환 행렬 적용은 SetTransform(D3DTS_PROJECTION, &matProj)처럼 적용해주어야 한다.

- 렌더링 파이프 라인
 렌터링 파이프는 로컬 좌표계 정점 -> 월드 행렬 -> 카메라 행렬 -> 투영 행렬 -> 뷰포트 좌표계 정점 이런 순의 과정을 거치게 된다.


이전 소스에 비해 회전이 들어가고 예제 코드에서 정점 구조체에 rhw값이 없다는 것에 주의할것
#define에서도 D3DFVF_XYZ로 RHW가 빠져있다 이것을 추가하게 되면 화면이 나오지 않는다.

반응형

'DirectX > DirectX 9.0' 카테고리의 다른 글

[DirectX 9.0] Textures  (0) 2014.02.11
[DirectX 9.0] Lights  (0) 2014.02.11
[DirectX 9.0] Vertices  (0) 2014.02.11
CreateDevice  (0) 2011.03.02
DirectX 설치 및 설정 방법  (0) 2011.03.02
반응형

//-----------------------------------------------------------------------------
// File: Vertices.cpp
//
// Desc: 이번 튜토리얼은 정점을 렌더링에 대한것 이다. 여기서 정점 버퍼의 개념에
//       대해 보게 될 것이다. 정점 버퍼란 정점을 보관하기 위한 D3D용 객체인데,
//   사용자가 FVF를 사용하여 자유롭게 형식을 정의할 수 있다. 변환과 광원 
//   처리가 완료된 정점을 이용할 것이다.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------

// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9             g_pD3D = NULL; // D3DDevice 생성하기 위한 변수
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // device에 그리기 위한 변수
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // 정점을 보관할 정점 버퍼

// 정점을 정의할 구조체
struct CUSTOMVERTEX
{
    FLOAT x, y, z, rhw; // 정점의 변화된 좌표(rhw값이 있으면 변환이 완료된 정점)
    DWORD color;        // 정점의 색상
};

// 사용자 정점 구조체에 관한 정보를 나타내는 FVF값
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)

 


//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Direct3D 초기화
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
    // 디바이스 생성하기 위한 D3D객체 생성 및 버전 확인
    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;

    // 디바이스 생성을 위한 구조체
    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof( d3dpp ) );
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

    // D3DDevice 장치 생성
    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_pd3dDevice ) ) )
    {
        return E_FAIL;
    }

    // 디바이스 상태 정보를 처리할 경우 이곳에서 한다.

    return S_OK;
}

 


//-----------------------------------------------------------------------------
// Name: InitVB()
// Desc: 정점 버퍼를 생성하고 정점의 값을 채워 넣는다. 
//       정점 버퍼란 기본적으로 정점 정보를 갖고 있는 메모리 블록이다.
//       정점 버퍼를 생성한 다음에는 반드시 Lock()/Unlock()으로 포인터를 얻어내서 
//       정점퍼에 써넣어야 한다. 또한 D3D는 인덱스 버퍼도 사용 가능하다.
//       정점 버퍼나 인덱스 버퍼는 기본 시스템 메모리 외에 디바이스 메모리
//   (비디오카드 메모리)에 생성될 수 있는데, 대부분의 비디오카드에서는 이렇게
//       할 경우 엄청난 속도의 향상을 얻을 수 있다.
//-----------------------------------------------------------------------------
HRESULT InitVB()
{
    // 삼각형을 렌더링하기 위해 세 개의 정점을 선언
    CUSTOMVERTEX Vertices[] =
    {
        { 250.0f, 150.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, 
        { 350.0f, 350.0f, 0.5f, 1.0f, 0xff00ff00, }, // color(AARRGGBB)
        { 150.0f, 350.0f, 0.5f, 1.0f, 0xff00ffff, }, // 알파알쥐비 순서
    };

    // 정점 버퍼 생성. 3개의 사용자 정점을 보관할 메모리를 할당 한다.
    // FVF를 지정하여 보관할 데이터의 형식을 지정한다.
    if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3 * sizeof( CUSTOMVERTEX ),
                                                  0, D3DFVF_CUSTOMVERTEX,
                                                  D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
    {
        return E_FAIL;
    }

    // 정점 버퍼를 값으로 채운다.
    // 정점 버퍼의 Lock()함수를 호출하여 포인터를 얻어온다
    VOID* pVertices;
    if( FAILED( g_pVB->Lock( 0, sizeof( Vertices ), ( void** )&pVertices, 0 ) ) )
        return E_FAIL;
    memcpy( pVertices, Vertices, sizeof( Vertices ) );
    g_pVB->Unlock();

    return S_OK;
}

 


//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: 초기화된 객체들을 소거한다
//-----------------------------------------------------------------------------
VOID Cleanup()
{
    if( g_pVB != NULL )
        g_pVB->Release();

    if( g_pd3dDevice != NULL )
        g_pd3dDevice->Release();

    if( g_pD3D != NULL )
        g_pD3D->Release();
}

 


//-----------------------------------------------------------------------------
// Name: Render()
// Desc: 화면을 그린다
//-----------------------------------------------------------------------------
VOID Render()
{
    // 백버퍼를 지정딘 색으로 지운다.
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 255 ), 1.0f, 0 );

    // 렌더링 시작
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
        // 정점 버퍼의 삼각형을 그린다.
        // 먼저 정점 정보가 담겨있는 정점 버퍼를 출력 스트림으로 할당한다.
  // D3D에 정점 셰이더 정보를 지정한다. 대부분 FVF만 지정
        // 기하학적 정보를 출력하기 위한 DrawPrimitive() 함수를 호출
        g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
        g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
        g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );
  // DrawPrimitive는 삼각형을 그려주는 함수이다. 다음 6개의 형태가 있다.
  // D3DPT_POINTLIST, D3DPT_LINELIST, D3DPT_LINESTRIP, D3DPT_TRIANGLELIST,
  // D3DPT_TRIANGLESTRIP, D3DPT_TRIANGLEFAN



        // 랜더링 종료
        g_pd3dDevice->EndScene();
    }

    // 후면 버퍼를 보이는 화면으로 
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

 


//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: 윈도우 메시지 처리
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:
            Cleanup();
            PostQuitMessage( 0 );
            return 0;

  case WM_KEYDOWN: // 키를 눌렀을때
   if( wParam == VK_ESCAPE ) { // esc를 눌렀을때
    ::DestroyWindow(hWnd);
    return 0;
   }
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

 


//-----------------------------------------------------------------------------
// Name: wWinMain()
// Desc: 프로그램 시작 지점
//-----------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
    // 윈도우 클래스 등록
    WNDCLASSEX wc =
    {
        sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
        GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
        L"D3D Tutorial", NULL
    };
    RegisterClassEx( &wc );

    // 윈도우 창 생성
    HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 02: Vertices",
                              WS_OVERLAPPEDWINDOW, 100, 100, 500, 500,
                              NULL, NULL, wc.hInstance, NULL );

    // Direct3D 초기화
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    {
        // 정점 버퍼 초기화
        if( SUCCEEDED( InitVB() ) )
        {
            // 윈도우 출력
            ShowWindow( hWnd, SW_SHOWDEFAULT );
            UpdateWindow( hWnd );

            // 메시지 루프
            MSG msg;
            ZeroMemory( &msg, sizeof( msg ) ); // 메시지 루프 초기화
            while( msg.message != WM_QUIT )
            {
    // 메시지 큐에 메시지가 있으면 처리
    // PeekMessage는 메시지가 있으면 처리하고 없으면 즉시 다음 문장으로 넘어 가는 특성이 있다.
    // GetMessage는 새로운 메시지가 발생하기 까지 대기 상태로 들어감 그래서 PeekMessage를 사용
    // 하여 대기 시간없이 남아도는 시간을 게임에 관련된 내용을 처리하는데 사용한다.
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) 
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
                else // 처리할 메시지 없으면 그려준다.
                    Render(); // 반응을 빨리 대처하기 위해 메인에서 사용됨
            }
        }
    }

 // 등록된 클래스 소거
    UnregisterClass( L"D3D Tutorial", wc.hInstance );
    return 0;
}

반응형

'DirectX > DirectX 9.0' 카테고리의 다른 글

[DirectX 9.0] Textures  (0) 2014.02.11
[DirectX 9.0] Lights  (0) 2014.02.11
[DirectX 9.0] Matrices  (0) 2014.02.11
CreateDevice  (0) 2011.03.02
DirectX 설치 및 설정 방법  (0) 2011.03.02
반응형
 출처 : gpg

D3DRS_ZWRITEENABLE을 off하면, zbuffer에 값을 쓰지 않는데...그렇게 해서 얻을수 있는 효과, 성능이 무엇이 있슬까요?

더불어 D3DRS_ZENABLE의 on, off까지 하면 총 4가지의 조합으로 사용할 수 있는데, 각각의 경우는 어느경우에 사용될수 있슬까요?

이런것은 책에도 나와있지 않고, dx-help에도 나와있지 않고..제가 쓸대없는 것을 궁굼해 하는건가요?
이런류의 질문을 올려도 답변해주시는 분도 거의 없고...다들 모르고 계셔서 그런가요? 별로 알필요가 없서서 그런가요..

////////////////////////////////////////////////////  

보통 일반적인 경우 둘다 true(디폴트) 로 놓고 사용하고요

zwriteenable false 같은경우는 파티클 등에 쓰입니다..
연기,광원효과 등의 파티클들은 부피를 가지지 않기 때문에 그런거같고요..

zenable false 는 이전 z버퍼에 저장된 값을 무시하고 무조건 zbuffer 검사를 통과해서
찍으려고 할때 쓰입니다..
주로 3D화면위에 2D 인터페이스를 찍으려 할때 쓰이겠네요..

옵션에 따른 성능은 별차이 없는거 같고
용도에 맞게 쓰는게 좋을거 같네요..

 

스플래팅이나.. 라이트맵등으로 어쩔수 없이 그린곳에 한번 더 그릴때 꺼주면

속도 이득을 볼 수 있다고 합니다.

물론 테스트는 안해 봤습니다만;; 카막아저씨가 그렇게 사용하므로 무의식 적으로 계속 사용중입니다.
 

 수많은 반투명한 오브젝트를 소트하는 것에 CPU 파워를 쓰기 아깝고 

반투명한 오브젝트의 깊이값에 의해 뒷배경이 나타나버리는 현상을 줄여보고자 할때
ZWRITEENABLE, FALSE를 사용합니다.

ZENABLE, FALSE 까지 하면 렌더링 순서에 영향을 받기때문에 순서에 주의하셔야 합니다.
(배경찍은 다음에 파티클 찍으면 분명 배경에 의해 가려져야 하는데 배경위에 찍히게 됩니다. )

  

D3DRS_ZWRITEENABLE 는 Z값 비교는 하지만 Z 버퍼값은 변경 시키지 않으므로 현재의 Z버퍼값을 기준으로
삼아서 컬러 버퍼를 오버라이트하는 데에는 쓸 수가 있다고 봅니다.
현재의 D3DRS_ZFUNC에 따라서 일종의 조건 설정이 된다고 생각합니다.

Z비교를 끄는 것은 마치 도화지위 크래파스로 진하게 덧그리면 먼저 그린것이 가려져서 안보이 듯이
완전히 페인터의 알고리즘이 적용되지요.(나중에 그린 것이 먼저 그린 것을 가린다.)

위 두개의 함수 설정은 서로 다른 결과를 가져온다고 생각합니다.

[출처] D3DRS_ZWRITEENABLE|작성자 무동

반응형
반응형

//-----------------------------------------------------------------------------
// File: CreateDevice.cpp
//
// Desc: 이것은 Direct3D 사용 첫번째 튜토리얼이다. 이 튜토리얼은 Direct3D를 사용해
//          장치 생성과 윈도우 초기화를 사용한다.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include  // Direct3D9 를 사용하기 위한 헤더파일
#pragma warning( disable : 4996 ) // disable deprecated warning
#include
#pragma warning( default : 4996 )

 


//-----------------------------------------------------------------------------
// 전역 변수
//-----------------------------------------------------------------------------
LPDIRECT3D9         g_pD3D = NULL; // D3DDevice를 생성하기 위해 사용하기위한 변수
LPDIRECT3DDEVICE9   g_pd3dDevice = NULL; // device에 그리기 위한 변수

 


//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Direct3D 초기화
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
    // 디바이스 성성하기 위한 D3D객체 생성 및 버전 확인
    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;

    D3DPRESENT_PARAMETERS d3dpp; // 디바이스 생성을 위한 구조체
    ZeroMemory( &d3dpp, sizeof( d3dpp ) ); // 구조체 초기화
    d3dpp.Windowed = TRUE; // 창모드
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // 스왑 효과
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; // 후면 버퍼 생성

    // Direct3D 장치 생성.
    // 디폴트 비디오 카드를 사용한다.
    // HAL 디바이스를 생성한다(HW 가속장치 사용)
    // 정점 처리는 모든 카드에서 지원하는 SW 처리로 생성한다(HW로 생성할 경우 성능 향상

    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,                          hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp,                                  &g_pd3dDevice ) ) )

    {
        return E_FAIL;
    }

    // 디바이스 상태 정보를 처리할 경우 이곳에서 한다.

    return S_OK;
}

 


//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: 초기화된 객체들을 소거한다
//-----------------------------------------------------------------------------
VOID Cleanup()
{
 // 생성의 역순서로 해제 해야한다.
    if( g_pd3dDevice != NULL )
        g_pd3dDevice->Release();

    if( g_pD3D != NULL )
        g_pD3D->Release();
}

 


//-----------------------------------------------------------------------------
// Name: Render()
// Desc: 화면을 그린다
//-----------------------------------------------------------------------------
VOID Render()
{
    if( NULL == g_pd3dDevice )
        return;

    // 백버퍼를 지정된색(RGB)으로 지운다.
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 175, 100 ),                                      1.0f, 0 );

    // 렌더링 시작
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
        // 실제 렌더링 명령들이 나열되는 곳

        // 렌더링 종료
        g_pd3dDevice->EndScene();
    }

    // 후면 버퍼를 보이는 화면으로
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

 


//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: 윈도우 메시지 처리
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY: // 종료
            Cleanup();
            PostQuitMessage( 0 );
            return 0;

  case WM_KEYDOWN: // 키를 눌렀을때
   if( wParam == VK_ESCAPE ) { // esc를 눌렀을때
         ::DestroyWindow(hWnd);
          return 0;
   }

        case WM_PAINT:  // 화면 출력
            Render();
            ValidateRect( hWnd, NULL );
            return 0;
    }

    return DefWindowProc( hWnd, msg, wParam, lParam );
}

 


//-----------------------------------------------------------------------------
// Name: wWinMain()
// Desc: 프로그램 시작 지점
//-----------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
    // 윈도우 클래스 등록
    WNDCLASSEX wc =
    {
        sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
        GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
        L"D3D Tutorial", NULL
    };
    RegisterClassEx( &wc );

    // 윈도우 창 생성
    HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial 01: CreateDevice",
                              WS_OVERLAPPEDWINDOW, 100, 100, 500, 500,
                              NULL, NULL, wc.hInstance, NULL );

    // Direct3D 초기화
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    {
        // 윈도우 출력
        ShowWindow( hWnd, SW_SHOWDEFAULT );
        UpdateWindow( hWnd );

        // 메시지 루프
        MSG msg;
        while( GetMessage( &msg, NULL, 0, 0 ) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
    }
 
 // 등록된 클래스 제거
    UnregisterClass( L"D3D Tutorial", wc.hInstance );
    return 0;
}

반응형

'DirectX > DirectX 9.0' 카테고리의 다른 글

[DirectX 9.0] Textures  (0) 2014.02.11
[DirectX 9.0] Lights  (0) 2014.02.11
[DirectX 9.0] Matrices  (0) 2014.02.11
[DirectX 9.0] Vertices  (0) 2014.02.11
DirectX 설치 및 설정 방법  (0) 2011.03.02
반응형

DirectX를 사용하기 위해 visual studio를 설치하고
Microsoft DirectX SDK (March 2009)를 홈페이지에서 다운 받에 설치 한다.


설정

visual 2008 기준

메뉴에서 Tools -> options 에 들어가서 왼쪽 목록에서  Projects and Solutions -> VC++ Directiories 를 선택한다.
선택 후 Show directiories for: 아래 목록 중 Include files 를 선택하여 DirectX 설치 경로의 Include 폴더를 지정해준다.
C:\Program Files (x86)\Microsoft DirectX SDK (March 2009)\Include

선택 후 Show directiories for: 아래 목록 중 Library files 를 선택하여 DirectX 설치 경로의 Library 폴더를 지정해준다.

// 32bit 경우
C:\Program Files (x86)\Microsoft DirectX SDK (March 2009)\Lib\x86
// 64bit 경우
C:\Program Files (x86)\Microsoft DirectX SDK (March 2009)\Lib\x64

Solution을 생성 후 메뉴에서 Project -> Property 를 선택하여
왼쪽 목록에서 Configuration Properties -> Linker -> Input 을 선택한다.
오른쪽 Additional Dependencies 에 d3dx9.lib d3d9.lib winmm.lib 을 추가해 준다.
디시 왼쪽 목록 Input 아래 System 을 선택한다.
오른쪽 SubSystem 에 windows 를 선택한다.


visual 6.0 기준
메뉴에서 Tools -> options 에 들어가서 상단 탭에서 Directiories 을 선택한다.
선택 후 Show directiories for: 아래 목록 중 Include files 를 선택하여 DirectX 설치 경로의 Include 폴더를 지정해준다.
C:\Program Files (x86)\Microsoft DirectX SDK (March 2009)\Include

선택 후 Show directiories for: 아래 목록 중 Library files 를 선택하여 DirectX 설치 경로의 Library 폴더를 지정해준다.

// 32bit 경우
C:\Program Files (x86)\Microsoft DirectX SDK (March 2009)\Lib\x86
// 64bit 경우
C:\Program Files (x86)\Microsoft DirectX SDK (March 2009)\Lib\x64

Solution을 생성 후 메뉴에서 Project -> Settings 를 선택하여
오른쪽 탭에서 Linker 을 선택한다.
Object/library modules: 에 d3dx9.lib d3d9.lib winmm.lib 을 추가해 준다.
하단에 Project Options: 에서 /subsystem:console에서 /subsystem:windows로 변경 해준다.

반응형

'DirectX > DirectX 9.0' 카테고리의 다른 글

[DirectX 9.0] Textures  (0) 2014.02.11
[DirectX 9.0] Lights  (0) 2014.02.11
[DirectX 9.0] Matrices  (0) 2014.02.11
[DirectX 9.0] Vertices  (0) 2014.02.11
CreateDevice  (0) 2011.03.02

+ Recent posts