티스토리 뷰

공부 이야기

[DirectX3D] 삼각형 그리기

판다(panda) 2009. 1. 3. 00:00
//삼각형 그리기 Microsoft Visual Studio 2005
// simpletriangle.cpp : 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"
#include "simpletriangle.h"
#include <d3d9.h>                   // direct 3d를 사용하기 위한 헤더파일
#include <d3dx9.h>                 // direct 3d에서 제공하는 유틸리티 함수를 위한 헤더파일
#define MAX_LOADSTRING 100
#define D3DFVF_CUSTOM  D3DFVF_XYZRHW | D3DFVF_DIFFUSE
struct CustomVertex
{
    float x, y, z, rhw;      //정점의 위치
    DWORD diffuse;        //정점의 색
};
// 전역 변수:
HINSTANCE hInst;                                            // 현재 인스턴스입니다.
TCHAR szTitle[MAX_LOADSTRING];                  // 제목 표시줄 텍스트입니다.
TCHAR szWindowClass[MAX_LOADSTRING];    // 기본 창 클래스 이름입니다.
IDirect3D9 *g_pD3D;                                          // Direct3D 레이어 인터페이스 핸들
IDirect3DDevice9 *g_pD3DDev;                          // D3D Device 레이어 인터페이스 핸들
HWND g_hWnd;                                               // 윈도우 핸들
// 이 코드 모듈에 들어 있는 함수의 정방향 선언입니다.
ATOM    MyRegisterClass(HINSTANCE hInstance);
BOOL    InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: 여기에 코드를 입력합니다.
    MSG msg;
    HACCEL hAccelTable;

     // 전역 문자열을 초기화합니다.
     LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
     LoadString(hInstance, IDC_SIMPLETRIANGLE, szWindowClass, MAX_LOADSTRING);
     MyRegisterClass(hInstance);

     // 응용 프로그램 초기화를 수행합니다.
     if (!InitInstance (hInstance, nCmdShow))
     {
      return FALSE;
     }

     // Direct3D를 초기화
     g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
     if ( g_pD3D == NULL )
          return FALSE;
     D3DPRESENT_PARAMETERS pp;
     memset(&pp, 0, sizeof(pp));                    // ZeroMemory(&pp, sizeof(pp));
     pp.BackBufferFormat = D3DFMT_UNKNOWN;
     pp.Windowed = TRUE;
     pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
     if( FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pp, &g_pD3DDev)))
          return FALSE;
     hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SIMPLETRIANGLE));
     IDirect3DVertexBuffer9 *pVB;
     if( FAILED( g_pD3DDev->CreateVertexBuffer(
  3*sizeof(CustomVertex), 0, D3DFVF_CUSTOM, D3DPOOL_DEFAULT, &pVB, NULL) ) )
          return FALSE;
 
     CustomVertex *pVerts;
     pVB->Lock(0, 3*sizeof(CustomVertex), (void **)&pVerts, 0);
 
     // 첫번째 정점
     pVerts[0].x = 100;  
     pVerts[0].y = 10;
     pVerts[0].z = 0;
     pVerts[0].rhw = 1;
     pVerts[0].diffuse = D3DCOLOR_RGBA(255, 0, 0, 255);

     // 두번째 정점
     pVerts[1].x = 200;
     pVerts[1].y = 100;
     pVerts[1].z = 0;
     pVerts[1].rhw = 1;
     pVerts[1].diffuse = D3DCOLOR_RGBA(0, 255, 0, 255);

     // 세번째 정점
     pVerts[2].x = 10;
     pVerts[2].y = 100;
     pVerts[2].z = 0;
     pVerts[2].rhw = 1;
     pVerts[2].diffuse = D3DCOLOR_RGBA(0, 0, 255, 255);
     pVB->Unlock();

     // 기본 메시지 루프입니다.
     memset(&msg, 0, sizeof(msg));
     while ( msg.message != WM_QUIT)
     {
            if ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            else
            {

                // Direct3D 랜더링
                //g_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 1.0f, 0); //red, green, blue, alpha

                g_pD3DDev->Clear(0, NULL, NULL, 0, 1.0f, 0);
                g_pD3DDev->BeginScene();

               // 여기에 그리기 함수를 추가한다.
               g_pD3DDev->SetFVF( D3DFVF_CUSTOM );
               g_pD3DDev->SetStreamSource( 0, pVB, 0, sizeof(CustomVertex));
               g_pD3DDev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1);
               g_pD3DDev->EndScene();
               g_pD3DDev->Present(NULL, NULL, NULL, NULL);
              }
         }

         // Direct3D 종류 
         pVB->Release();
         g_pD3DDev->Release();
         g_pD3D->Release();
         return (int) msg.wParam;
}

//
//  함수: MyRegisterClass()
//
//  목적: 창 클래스를 등록합니다.
//
//  설명:
//
//    Windows 95에서 추가된 'RegisterClassEx' 함수보다 먼저
//    해당 코드가 Win32 시스템과 호환되도록
//    하려는 경우에만 이 함수를 사용합니다. 이 함수를 호출해야
//    해당 응용 프로그램에 연결된
//    '올바른 형식의' 작은 아이콘을 가져올 수 있습니다.
//

ATOM MyRegisterClass(HINSTANCE hInstance)
{
     WNDCLASSEX wcex;
     wcex.cbSize = sizeof(WNDCLASSEX);
     wcex.style   = CS_HREDRAW | CS_VREDRAW;
     wcex.lpfnWndProc = WndProc;
     wcex.cbClsExtra  = 0;
     wcex.cbWndExtra  = 0;
     wcex.hInstance  = hInstance;
     wcex.hIcon   = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SIMPLETRIANGLE));
     wcex.hCursor  = LoadCursor(NULL, IDC_ARROW);
     wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
     wcex.lpszMenuName = MAKEINTRESOURCE(IDC_SIMPLETRIANGLE);
     wcex.lpszClassName = szWindowClass;
     wcex.hIconSm  = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
     return RegisterClassEx(&wcex);
}

//
//   함수: InitInstance(HINSTANCE, int)
//
//   목적: 인스턴스 핸들을 저장하고 주 창을 만듭니다.
//
//   설명:
//
//        이 함수를 통해 인스턴스 핸들을 전역 변수에 저장하고
//        주 프로그램 창을 만든 다음 표시합니다.
//

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    HWND hWnd;
    hInst = hInstance;                   // 인스턴스 핸들을 전역 변수에 저장합니다.
    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    if (!hWnd)
    {
        return FALSE;
    }
    g_hWnd = hWnd;                    // 전역으로 선언된 g_hWnd에 윈도우 핸들 복사
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    return TRUE;
}

//
//  함수: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  목적: 주 창의 메시지를 처리합니다.
//
//  WM_COMMAND - 응용 프로그램 메뉴를 처리합니다.
//  WM_PAINT - 주 창을 그립니다.
//  WM_DESTROY - 종료 메시지를 게시하고 반환합니다.
//
//

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     int wmId, wmEvent;
     PAINTSTRUCT ps;
     HDC hdc;
     switch (message)
     {
         case WM_COMMAND:
            wmId    = LOWORD(wParam);
            wmEvent = HIWORD(wParam);

            // 메뉴의 선택 영역을 구문 분석합니다.
            switch (wmId)
            {
                case IDM_ABOUT:
                    DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                    break;
                case IDM_EXIT:
                    DestroyWindow(hWnd);
                    break;
                default:
                    return DefWindowProc(hWnd, message, wParam, lParam);
            }
            break;
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);

            // TODO: 여기에 그리기 코드를 추가합니다.
            EndPaint(hWnd, &ps);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
}

// 정보 대화 상자의 메시지 처리기입니다.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
         case WM_INITDIALOG:
             return (INT_PTR)TRUE;
         case WM_COMMAND:
             if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
            {
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE;
            }
            break;
    }
    return (INT_PTR)FALSE;
}
 
결과