티스토리 뷰

공부 이야기

[DirectX3D] 무지개 그리기

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

#include "stdafx.h"
#include "rainbow.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_RAINBOW, 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_RAINBOW));
     IDirect3DVertexBuffer9 *pVB;
     if ( FAILED( g_pD3DDev->CreateVertexBuffer( 18*sizeof(CustomVertex), 0, D3DFVF_CUSTOM, D3DPOOL_DEFAULT, &pVB, NULL) ) )
          return FALSE;
 
     CustomVertex *pVerts;
     pVB->Lock(0, 18*sizeof(CustomVertex), (void **)&pVerts, 0);
 
     pVerts[0].x = 0;  pVerts[0].y = 0; pVerts[0].z = 0; pVerts[0].rhw = 1;  pVerts[0].diffuse = D3DCOLOR_RGBA(255, 0, 0, 255);
     pVerts[1].x = 200;  pVerts[1].y = 0; pVerts[1].z = 0; pVerts[1].rhw = 1;  pVerts[1].diffuse = D3DCOLOR_RGBA(0, 255, 0, 255);
     pVerts[2].x = 0;  pVerts[2].y = 100; pVerts[2].z = 0; pVerts[2].rhw = 1;  pVerts[2].diffuse = D3DCOLOR_RGBA(255, 0, 0, 255);
     pVerts[3].x = 200;  pVerts[3].y = 0; pVerts[3].z = 0; pVerts[3].rhw = 1;  pVerts[3].diffuse = D3DCOLOR_RGBA(0, 255, 0, 255);
     pVerts[4].x = 200;  pVerts[4].y = 100; pVerts[4].z = 0; pVerts[4].rhw = 1;  pVerts[4].diffuse = D3DCOLOR_RGBA(0, 255, 0, 255);
     pVerts[5].x = 0;  pVerts[5].y = 100; pVerts[5].z = 0; pVerts[5].rhw = 1;  pVerts[5].diffuse = D3DCOLOR_RGBA(255, 0, 0, 255);
     pVerts[6].x = 200;  pVerts[6].y = 0; pVerts[6].z = 0; pVerts[6].rhw = 1;  pVerts[6].diffuse = D3DCOLOR_RGBA(0, 255, 0, 255);
     pVerts[7].x = 400;  pVerts[7].y = 0; pVerts[7].z = 0; pVerts[7].rhw = 1;  pVerts[7].diffuse = D3DCOLOR_RGBA(0, 0, 255, 255);
     pVerts[8].x = 200;  pVerts[8].y = 100; pVerts[8].z = 0; pVerts[8].rhw = 1;  pVerts[8].diffuse = D3DCOLOR_RGBA(0, 255, 0, 255);
     pVerts[9].x = 400;  pVerts[9].y = 0; pVerts[9].z = 0; pVerts[9].rhw = 1;  pVerts[9].diffuse = D3DCOLOR_RGBA(0, 0, 255, 255);
     pVerts[10].x = 400;  pVerts[10].y = 100; pVerts[10].z = 0; pVerts[10].rhw = 1;  pVerts[10].diffuse = D3DCOLOR_RGBA(0, 0, 255, 255);
     pVerts[11].x = 200;  pVerts[11].y = 100; pVerts[11].z = 0; pVerts[11].rhw = 1;  pVerts[11].diffuse = D3DCOLOR_RGBA(0, 255, 0, 255);
     pVerts[12].x = 400;  pVerts[12].y = 0; pVerts[12].z = 0; pVerts[12].rhw = 1;  pVerts[12].diffuse = D3DCOLOR_RGBA(0, 0, 255, 255);
     pVerts[13].x = 500;  pVerts[13].y = 0; pVerts[13].z = 0; pVerts[13].rhw = 1;  pVerts[13].diffuse = D3DCOLOR_RGBA(255, 0, 255, 255);
     pVerts[14].x = 400;  pVerts[14].y = 100; pVerts[14].z = 0; pVerts[14].rhw = 1;  pVerts[14].diffuse = D3DCOLOR_RGBA(0, 0, 255, 255);
     pVerts[15].x = 500;  pVerts[15].y = 0; pVerts[15].z = 0; pVerts[15].rhw = 1;  pVerts[15].diffuse = D3DCOLOR_RGBA(255, 0, 255, 255);
     pVerts[16].x = 500;  pVerts[16].y = 100; pVerts[16].z = 0; pVerts[16].rhw = 1;  pVerts[16].diffuse = D3DCOLOR_RGBA(255, 0, 255, 255);
     pVerts[17].x = 400;  pVerts[17].y = 100; pVerts[17].z = 0; pVerts[17].rhw = 1;  pVerts[17].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_TRIANGLESTRIP, 0, 15);
           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_RAINBOW));
     wcex.hCursor  = LoadCursor(NULL, IDC_ARROW);
     wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
     wcex.lpszMenuName = MAKEINTRESOURCE(IDC_RAINBOW);
     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;
}

결과