언어/기타
2007.03.25 08:31

[DX&C++] 3D를 다루는 프로그램의 개요

조회 수 1247 추천 수 4 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

 



오늘은 실전 예제를 가지고 분석해보는 것으로써, 3D 프로그래밍의 방식을 알아보는 시간입니다.



 



오늘 분석해볼 예제는, DirectX 3D Tutorial 02 입니다.



 



여러분이 설치했을 SDK에 수록되어 있는 내용입니다만 해설이 영문이고, 정확한 구동방식이 나와있지 않아 혼자서 공부하기는 어려울 수도 있습니다.



 



 



모든 윈도우 프로그램들은 메세지를 처리하는 프로시저를 가지고 있습니다.



 



보통의 프로그램들은 이 프로시저에 '그림을 그릴때입니다!' 라는 메세지가 들어올 때에만 화면처리를 하게 됩니다만, 게임에서는 시도때도없이 그림을 그려주게 됩니다.



 



게임은 화면이 역동적으로 변화하므로 최대한 화상처리에 투자를 하는 것이지요.



 



 



D3D를 이용한 프로그램은 일반적으로 다음과 같은 진행방식을 갖습니다.



 



윈도우 초기화 -> D3D 초기화 -> Geometry 초기화 -> 렌더링 루프(반복) -> 종료



 



Geometry란 그림을 그려줘야할 대상, 즉 사진에 찍힐 모델들을 정의하는 것입니다.



 



 



이런 공부는 소스를 보면서 하는 것이 가장 학습률이 좋으니 다음 예제를 보면서 설명을 드리도록 하겠습니다.



 



 



 



다음예제는 실제 구동가능한 코드이기 때문에, 이 아랫줄 부터 복사를 하여 직접 구동을 시켜보셔도 좋습니다.



 



프로젝트 세팅 -> 구성속성 -> 링커 -> 입력 -> 추가종속성에 다음을 입력합니다.



d3dxof.lib dxguid.lib d3dx9d.lib d3d9.lib winmm.lib



그렇지 않으면 컴파일시 에러가 '반드시' 발생하므로 꼭 입력해주십시오.



(이는 DX가 인터페이스이기 때문에, 링커에서 함수 내용을 알 수 있도록 설정해주는 것입니다.)



--------------------------------------------------------------------------------




#include >D3D9.H<
#pragma warning( disable : 4996 ) // 문자열관련 권장경고를 표시하지 않는다.
#include >STRSAFE.H<
#pragma warning( default : 4996 )



 




//-----------------------------------------------------------------------------
// 전역변수
//-----------------------------------------------------------------------------
LPDIRECT3D9             g_pD3D       = NULL; // D3DDevice의 포인터
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // 렌더링 장치의 포인터
LPDIRECT3DVERTEXBUFFER9 g_pVB        = NULL; // 버텍스들을 저장하는 D3D의 버퍼입니다.



// 버텍스타입에 대한 정의입니다.



// 이것은 프로그래머의 기호에따라 몇가지 속성을 추가할 수 있습니다만, 기본적인 버텍스는 다음과 같습니다.
struct CUSTOMVERTEX
{
    FLOAT x, y, z, rhw; // 버텍스의 위치
    DWORD color;        // 버텍스의 색
};



// 우리가 만든 버텍스에 대한 설정을 다음과 같이 할 수 있습니다.



// 예제상에서는 XYZ,RHW를 사용하고, DIFFUSE 컬러값을 사용하므로 다음과 같이 두가지 속성을 적습니다.



#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;



    // D3Device를 초기화하기위한 설정입니다.



    D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory( &d3dpp, sizeof(d3dpp) );
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;



    // 설정을 이용하여 Device를 만들어냅니다.



    // 여기서 SOFTWARE_VERTEXPROCESSING은 플래그값으로, 하드웨어 가속을 받지 않는 것을 의미합니다.
    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_pd3dDevice ) ) )
    {



        // FAILED함수는 실패하면 TRUE값을 반환하므로 if문에 의해 이곳에 들어오게 됩니다.



        // 에러_실패라는 뜻의 결과값을 반환합니다.



        // 나중에 이 값을 가지고 디바이스 생성이 정상적으로 되었는지 총괄적으로 알 수 있어서 편합니다.
        return E_FAIL;
    }



 



    // 정상적으로 디바이스 생성이 끝난다면 이곳에 오게됩니다.



    // 정상값을 반환하죠.



    return S_OK;
}



 




//-----------------------------------------------------------------------------
// Name: InitVB()
// Desc: 버퍼의 내용을 초기화 하는 함수



//-----------------------------------------------------------------------------
HRESULT InitVB()
{
    // 삼각형을 그리기위한 버텍스 3개 입니다.



    // 좌표를 적당하게 적어주고, 컬러값을 입력해주면 됩니다.
    CUSTOMVERTEX vertices[] =
    {
        { 150.0f,  50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color
        { 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, },
        {  50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, },
    };



    // 버텍스 버퍼를 초기화 합니다.



    // 전역 변수로 선언해둔 g_pVB에 해당 버텍스 버퍼의 주소를 저장합니다.
    if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX),
                                                  0, D3DFVF_CUSTOMVERTEX,
                                                  D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
    {
        return E_FAIL;
    }



    // 버텍스 버퍼에 우리가 선언한 버텍스들을 기입해야합니다.



    // 이 때, VB에 Lock을 걸어 직접 메모리의 내용을 복사해주게 되는데,



    // 이것은 여러 프로세서가 한번에 이 자원에 접근하지 못하도록 하는 것으로,



    // DX는 하드웨어를 직접 다룰 수 있도록 해주기때문에, 이런 과정이 필요합니다.



    VOID* pVertices;



    // 우리가 만든 버텍스만큼의 장소를 (sizeof(vertices)) Lock을 걸어서 해당 구역의 포인터를 pVertices에 저장합니다.
    if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
        return E_FAIL;



    // Lock을 건 구역에 우리의 버텍스들을 옮깁니다.
    memcpy( pVertices, vertices, sizeof(vertices) );



    // Lock을 걸때엔 다음 작업에서 해당 리소스를 이용하기 위해 꼭 Unlock을 해줘야 합니다.
    g_pVB->Unlock();



    return S_OK;
}



 




//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: 모든 객체들을 반환합니다.



//-----------------------------------------------------------------------------
VOID Cleanup()
{



    // 이미 NULL인 객체를 Release할 경우 함수를 찾지못해 에러가 생기므로, 다음과 같이   



    // NULL값인지 확인을 해준 후 Release를 해주게 됩니다.



    // Release는 메모리에 잡아둔 구역설정을 풀어버리는 것으로, 내용자체가 사라지는 건



    // 아니지만 다른 작업에서 해당구역을 덮어쓸 수는 있게 해줍니다.




    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()
{
    // 화면에 출력될 그림이 저장되는 버퍼(BackBuffer)를 파랑색으로 초기화합니다.



    // D3DCOLOR_XRGB는 단순 정의로써 괄호 안에 입력된 숫자를 DWORD값으로 변환해줍니다.




    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );



 



    // 그림을 그릴수 있는 허가를 받기위해 호출하는 함수입니다.



    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
        // 우리는 InitVB를 호출한 다음이라면 g_pVB를 지속적으로 그려주는 것만으로



        // 삼각형을 그릴 수 있습니다.



        // VB에서 0번째 메모리구역에서 CUSTOMVERTEX사이즈 만큼의 소스를 읽어나가는



        // 것을 설정해줍니다.
        g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );



 



        // 맨 처음 설정한 내용을 이곳에서 사용하는 것입니다.



        // 프로그래머가 사용할 버텍스들의 설정이 어떠한지 D3D에게 알려주는 과정입니다.
        g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );



 



        // DrawPrimitive 함수를 이용해 그림을 그려주게 됩니다.



        // D3DPT_TRIANGLELIST는, 앞에서부터 3개의 버텍스씩 끊어 삼각형(폴리곤)을



        // 그리는 방식입니다. 이외에도 여러가지 방식이 있습니다만, 이 예제에서는 삼각형만



        // 그려내는 것이 목적이기 때문에 이 방식을 사용합니다.
        g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );



        // End the scene
        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 )
    {



        // 윈도우가 파괴된다는 메세지가 들어오면 CleanUp() 함수를 이용해 객체를



        // 초기화하고 프로그램을 종료합니다.
        case WM_DESTROY:
            Cleanup();
            PostQuitMessage( 0 );
            return 0;
    }



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



 




//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: 윈도우 프로그램의 시작 함수



//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
    // 윈도우 설정을 정의하고 등록합니다.



    // 이것은 OS가 프로그램의 윈도우에 이벤트 메세지를 보내줄 수 있도록 하기 위함입니다.



    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                      "D3D Tutorial", NULL };
    RegisterClassEx( &wc );



 



    // 응용프로그램내의 윈도우를 생성합니다.



    // 이것이 우리가 실제로 사용할 윈도우입니다.



    HWND hWnd = CreateWindow( "D3D Tutorial", "D3D Tutorial 02: Vertices",
                              WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                              NULL, NULL, wc.hInstance, NULL );



 



    // 프로그램이 시작되면 D3D객체를 생성해야합니다.
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    {
        // InitVB를 호출하여 우리가 설정한 삼각형 모양의 VB를 완성합니다.
        if( SUCCEEDED( InitVB() ) )
        {
            // 윈도우가 처음 생성되었을때에는 창이 보이지 않는 상태로 나타나게됩니다.



            // 설정을 바꿔주면 이제 눈에 보이는 윈도우가 생성되는 것입니다.




            ShowWindow( hWnd, SW_SHOWDEFAULT );
            UpdateWindow( hWnd );



 



            // 이제 메세지를 처리하는 루프로 들어갑니다.
            MSG msg;
            ZeroMemory( &msg, sizeof(msg) );



 



            // WM_QUIT은 윈도우 메세지중의 하나입니다. 이제 프로그램을 나간다는



            // 뜻이겠지요?
            while( msg.message!=WM_QUIT )
            {



                // 대기중인 윈도우 메세지가 있다면 받아와서 메세지 처리를 합니다.
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
                else
                    Render(); // 그것이 아니라면, Render() 함수를 호출하여 그림을 그려줍니다.
            }
        }
    }



   



    // 이곳은 프로그램이 종료되려면 무조건 도착하는 부분입니다.



    // 처음 등록한 윈도우 설정을 등록해제 해주는 것으로 프로그램의 마지막입니다.



    UnregisterClass( "D3D Tutorial", wc.hInstance );
    return 0;
}

?

List of Articles
번호 분류 제목 글쓴이 날짜 조회 수
844 언어/기타 렉없는 자동세이브 스크립트!!! 귀찮아‡ 2007.04.22 1474
843 언어/기타 [DX&C++] 3D를 넘어 2D로! Zeprod 2007.04.18 1675
842 언어/기타 코드진행 기초테크닉 1 나그네M 2007.04.14 709
841 언어/기타 그림 메뉴 2 [제 2의 타이틀 메뉴 (기본 메뉴편)] [거히 치트비법..] file 우드록맨 2007.04.12 771
840 RPG Maker 마우스 이동 스크립트 2 아크로s 2007.04.11 1965
839 언어/기타 '에피소드'형식이 아닌 '화' 형식의 시나리오는 어떨까요? 우드록맨 2007.04.09 1529
838 RPG Maker [초 노가다 시스템]그림 메뉴 1 file 우드록맨 2007.04.08 880
837 언어/기타 [DX&C++]3D공간상 카메라 시점의 대한 정의 실베 2007.04.02 1351
836 언어/기타 [DX&C++] IndexBuffer를 알아보자! Zeprod 2007.03.31 1240
835 언어/기타 3D좌표계에 3D물체를 찍기위환 기초과정 실베 2007.03.31 1355
834 언어/기타 [공개자료] 먼치킨 액알 만들기 책벌레공상가 2007.03.30 2499
833 언어/기타 [DX&C++] 3대 행렬 연산의 사용 Zeprod 2007.03.30 1404
832 언어/기타 숫자 게이지 색에 관한 팁 『덩키동크』 2007.03.30 1427
» 언어/기타 [DX&C++] 3D를 다루는 프로그램의 개요 Zeprod 2007.03.25 1247
830 언어/기타 template에 관한 간단한 예. 김두한 2007.03.12 1180
829 언어/기타 [고난도 시스템] 당구를 만들어 보자 5 SSS 2007.03.12 1197
828 언어/기타 2D격투게임만들기95 황금잉어빵 2007.03.08 2410
827 RPG Maker 1 - 1. 변수 응용 프로그램 만들기 (난수) 천영진 2007.03.06 1279
826 언어/기타 몬스터 성향 괴인X 2007.03.04 1256
825 언어/기타 [DX&C++] 3D 공간에 대한 이해 Zeprod 2007.03.04 1247
Board Pagination Prev 1 ... 4 5 6 7 8 9 10 11 12 13 ... 51 Next
/ 51






[개인정보취급방침] | [이용약관] | [제휴문의] | [후원창구] | [인디사이드연혁]

Copyright © 1999 - 2016 INdiSide.com/(주)씨엘쓰리디 All Rights Reserved.
인디사이드 운영자 : 천무(이지선) | kernys(김원배) | 사신지(김병국)