VioletaBabel

DirectX - 1 본문

기본개념/분류가 애매한거
DirectX - 1
Beabletoet 2018. 11. 26. 14:28

DirectX


GDI를 통하지 않고 그래픽카드로 바로 메세지를 꽂아주기 위해 만들어진 것이 DirectX.



Window 운영체제에서 Window Handle[HWND]이라는 창을 만든다.

HINSTANCE도 들어가 있다.


제일 처음엔 WinMain이란 함수가 불리고, 안에는 메세지 프로시저가 들어가있고, 무한 루프가 돌면서 기존은 Idle로 있다가 메세지가 오면 처리하는 방식으로 한다.



DirectXTest라는 프로젝트를 만들고, 윈도우 데스크탑 응용 프로그램으로 만든다.

그리고 해당 프로젝트의 리소스 폴더의 DirectXTest.rc 파일을 연다.

Accelerator 폴더 : 단축키

String Table 폴더 : 문자열 (타이틀 등)



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// 181126_DirectXTest.cpp : 응용 프로그램에 대한 진입점을 정의합니다.
//
 
#include "stdafx.h"
#include "181126_DirectXTest.h"
 
#define MAX_LOADSTRING 100
 
// 전역 변수:
HINSTANCE hInst;                                // 현재 인스턴스입니다.
WCHAR szTitle[MAX_LOADSTRING];                  // 제목 표시줄 텍스트입니다.
WCHAR szWindowClass[MAX_LOADSTRING];            // 기본 창 클래스 이름입니다.
 
// 이 코드 모듈에 포함된 함수의 선언을 전달합니다:
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 wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
 
    // TODO: 여기에 코드를 입력합니다.
 
    // 전역 문자열을 초기화합니다.
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); // 윈도우에서 IDS_APP_TITLE이라는 아이디를 가진 문자열을 szTitle에 넣어라. (rc파일의 String Table에 지정되어있음)
    LoadStringW(hInstance, IDC_MY181126DIRECTXTEST, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance); // 여기까지가 윈도우를 만들어 등록하는 과정.
 
    // 응용 프로그램 초기화를 수행합니다:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }
 
    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY181126DIRECTXTEST));
 
    MSG msg;
 
    // 기본 메시지 루프입니다:
    while (GetMessage(&msg, nullptr, 00)) // 디스트로이가 오면 메세지가 Null이 되어 루프가 끝이 난다.
    //while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // 겟 메세지는 메세지가 오지 않으면 슬립이 된다. 그래서 게임은 계속 돌아가야 하므로 PeekMessage로 바꿔준다
    { 
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
 
    return (int) msg.wParam;
}
 
 
 
//
//  함수: MyRegisterClass()
//
//  용도: 창 클래스를 등록합니다.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex; // WND는 윈도우, EX는 확장, W는 리바이트 문자열을 뜻함. 구조체를 만들었.
 
    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_MY181126DIRECTXTEST)); // 윈도우에 있는 아이콘을 불러와줌
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW); // 커서는 기본 화살표 커서
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1); // 윈도우의 백그라운드 컬러
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_MY181126DIRECTXTEST); // 메뉴의 이름. 역시 아까 String Table에서 설정한 바로 나옴
    wcex.lpszClassName  = szWindowClass; // 클래스 이름. 역시 string table.
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); // 작은 사이즈의 아이콘은 어떻게 할까를 나타냄.
 
    return RegisterClassExW(&wcex);
}
 
//
//   함수: InitInstance(HINSTANCE, int)
//
//   용도: 인스턴스 핸들을 저장하고 주 창을 만듭니다.
//
//   주석:
//
//        이 함수를 통해 인스턴스 핸들을 전역 변수에 저장하고
//        주 프로그램 창을 만든 다음 표시합니다.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // 인스턴스 핸들을 전역 변수에 저장합니다.
 
   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
 
   if (!hWnd)
   {
      return FALSE;
   }
 
   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) // 윈도우에서 호출해주면 받는 콜백 함수. 리턴은 주소.
{//핸들, 메세지, 파라미터 2개를 받음
    switch (message)
    {
    case WM_COMMAND:
        {//일반적인 명령은 다 여기
            int wmId = LOWORD(wParam);
            // 메뉴 선택을 구문 분석합니다:
            switch (wmId)
            {
            case IDM_ABOUT: //해당 ID에 따라 처리하는 일이 달라짐.
                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:
        {//화면을 업데이트 하라고 했거나 화면을 가렸다가 보이거나 할 때 수행됨.
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: 여기에 hdc를 사용하는 그리기 코드를 추가합니다...
            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;
}
 
cs




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#include "stdafx.h"
#include <windows.h>
#include <windowsx.h>
#include <d3d11.h> // Direct에 쓰이는 기본적인 것들. 그래픽 카드와 통신하는 부분.
#include <d3dx11.h> // 수학이나 계산 등과, (비교적) 편리하게 쓸 수 있도록 만든 것들을 모아둔 곳.
#include <d3dx10.h> 
 
// include the Direct3D Library file
#pragma comment (lib, "d3d11.lib"// lib와 dll의 차이. dll은 dynamic linked library. 정적 라이브러리와 동적 라이브러리의 차이이다.
#pragma comment (lib, "d3dx11.lib"// lib는 전체 코드를 포함하는 바이너리이다. exe 파일 자체가 커지는 단점이 있으나 속도가 빠르고 이식성이 좋으며 안정적.
#pragma comment (lib, "d3dx10.lib"// dll은 함수명(함수 정보)를 제공한다. 메모리 절약, 소스 외부 유출이 방지. 허나 이식성이 어렵고 속도 저하가 생김.
 
// global declarations
IDXGISwapChain *swapchain;             // the pointer to the swap chain interface // 화면에 하드웨어적으로 출력되는 프론트 버퍼와 렌더가 일어나는 백 버퍼들이 순차적으로 연결된 프레임 버퍼들의 집합
ID3D11Device *dev;                     // the pointer to our Direct3D device interface
ID3D11DeviceContext *devcon;           // the pointer to our Direct3D device context
 
                                       // function prototypes
void InitD3D(HWND hWnd);    // sets up and initializes Direct3D
void CleanD3D(void);        // closes Direct3D and releases memory
 
                            // the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
 
 
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
{
    HWND hWnd;
    WNDCLASSEX wc;
 
    ZeroMemory(&wc, sizeof(WNDCLASSEX));
 
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpszClassName = L"WindowClass";
 
    RegisterClassEx(&wc);
 
    RECT wr = { 00800600 };
    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
 
    hWnd = CreateWindowEx(NULL,
        L"WindowClass",
        L"Our First Direct3D Program",
        WS_OVERLAPPEDWINDOW,
        300,
        300,
        wr.right - wr.left,
        wr.bottom - wr.top,
        NULL,
        NULL,
        hInstance,
        NULL);
 
    ShowWindow(hWnd, nCmdShow);
 
    // set up and initialize Direct3D
    InitD3D(hWnd);
 
    // enter the main loop:
 
    MSG msg;
 
    while (TRUE)
    {
        if (PeekMessage(&msg, NULL00, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
 
            if (msg.message == WM_QUIT)
                break;
        }
        else
        {
            // Run game code here
            // ...
            // ...
        }
    }
 
    // clean up DirectX and COM
    CleanD3D();
 
    return msg.wParam;
}
 
 
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
    {
        PostQuitMessage(0);
        return 0;
    } break;
    }
 
    return DefWindowProc(hWnd, message, wParam, lParam);
}
 
 
// this function initializes and prepares Direct3D for use
void InitD3D(HWND hWnd)
{
    // create a struct to hold information about the swap chain
    DXGI_SWAP_CHAIN_DESC scd; // 스왑체인 만든다
 
    // clear out the struct for use
    ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC)); // 크기 잡는다
 
    // fill the swap chain description struct
    scd.BufferCount = 1;                                    // one back buffer
    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color // 색상
    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used
    scd.OutputWindow = hWnd;                                // the window to be used
    scd.SampleDesc.Count = 4;                               // how many multisamples // 스왑체인 몇 개 할거냐
    scd.Windowed = TRUE;                                    // windowed/full-screen mode
 
                                                            // create a device, device context and swap chain using the information in the scd struct
    D3D11CreateDeviceAndSwapChain(NULL,
        D3D_DRIVER_TYPE_HARDWARE,
        NULL,
        NULL,
        NULL,
        NULL,
        D3D11_SDK_VERSION,
        &scd,
        &swapchain,
        &dev,
        NULL,
        &devcon);
}
 
 
// this is the function that cleans up Direct3D and COM
void CleanD3D(void)
{
    // close and release all existing COM objects
    swapchain->Release();
    dev->Release();
    devcon->Release();
}
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// include the basic windows header files and the Direct3D header files
#include <windows.h>
#include <windowsx.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
 
// include the Direct3D Library file
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")
 
// global declarations
IDXGISwapChain *swapchain;             // the pointer to the swap chain interface
ID3D11Device *dev;                     // the pointer to our Direct3D device interface
ID3D11DeviceContext *devcon;           // the pointer to our Direct3D device context
ID3D11RenderTargetView *backbuffer;    // the pointer to our back buffer
 
// function prototypes
void InitD3D(HWND hWnd);    // sets up and initializes Direct3D
void RenderFrame(void);     // renders a single frame
void CleanD3D(void);        // closes Direct3D and releases memory
 
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
 
 
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
{
    HWND hWnd;
    WNDCLASSEX wc;
 
    ZeroMemory(&wc, sizeof(WNDCLASSEX));
 
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpszClassName = L"WindowClass";
 
    RegisterClassEx(&wc);
 
    RECT wr = { 00800600 };
    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
 
    hWnd = CreateWindowEx(NULL,
        L"WindowClass",
        L"Our First Direct3D Program",
        WS_OVERLAPPEDWINDOW,
        300,
        300,
        wr.right - wr.left,
        wr.bottom - wr.top,
        NULL,
        NULL,
        hInstance,
        NULL);
 
    ShowWindow(hWnd, nCmdShow);
 
    // set up and initialize Direct3D
    InitD3D(hWnd);
 
    // enter the main loop:
 
    MSG msg;
 
    while (TRUE)
    {
        if (PeekMessage(&msg, NULL00, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
 
            if (msg.message == WM_QUIT)
                break;
        }
 
        RenderFrame();
    }
 
    // clean up DirectX and COM
    CleanD3D();
 
    return msg.wParam;
}
 
 
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
    {
        PostQuitMessage(0);
        return 0;
    } break;
    }
 
    return DefWindowProc(hWnd, message, wParam, lParam);
}
 
 
// this function initializes and prepares Direct3D for use
void InitD3D(HWND hWnd)
{
    // create a struct to hold information about the swap chain
    DXGI_SWAP_CHAIN_DESC scd;
 
    // clear out the struct for use
    ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
 
    // fill the swap chain description struct
    scd.BufferCount = 1;                                    // one back buffer
    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;     // use 32-bit color
    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;      // how swap chain is to be used
    scd.OutputWindow = hWnd;                                // the window to be used
    scd.SampleDesc.Count = 1;                               // how many multisamples
    scd.SampleDesc.Quality = 0;                             // multisample quality level
    scd.Windowed = TRUE;                                    // windowed/full-screen mode
 
    // create a device, device context and swap chain using the information in the scd struct
    D3D11CreateDeviceAndSwapChain(NULL,
        D3D_DRIVER_TYPE_HARDWARE,
        NULL,
        NULL,
        NULL,
        NULL,
        D3D11_SDK_VERSION,
        &scd,
        &swapchain,
        &dev,
        NULL,
        &devcon);
 
 
    // get the address of the back buffer
    ID3D11Texture2D *pBackBuffer;
    swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); // 그래픽 카드의 메모리를 얻어오는 곳.
 
    // use the back buffer address to create the render target
    dev->CreateRenderTargetView(pBackBuffer, NULL&backbuffer);
    pBackBuffer->Release();
 
    // set the render target as the back buffer
    devcon->OMSetRenderTargets(1&backbuffer, NULL); // 메모리를 날려 줌.
 
 
    // Set the viewport
    D3D11_VIEWPORT viewport;
    ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT)); // 메모리를 초기화
 
    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
    viewport.Width = 800//뷰포트를 800x600으로 잡음
    viewport.Height = 600;
 
    devcon->RSSetViewports(1&viewport);
}
 
 
// this is the function used to render a single frame
void RenderFrame(void)
{
    // clear the back buffer to a deep blue
    devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f)); // 백버퍼로 초기화, 그리고 칼라를 넣어줌.
 
    // do 3D rendering on the back buffer here
 
    // switch the back buffer and the front buffer
    swapchain->Present(00);
}
 
 
// this is the function that cleans up Direct3D and COM
void CleanD3D(void)
{
    // close and release all existing COM objects
    swapchain->Release();
    backbuffer->Release();
    dev->Release();
    devcon->Release(); // 프로그램 종료가 아닌, 릴리즈를 불러줘야 메모리에서 사라짐
}
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
// include the basic windows header files and the Direct3D header files
#include "stdafx.h"
#include <windows.h>
#include <windowsx.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dx10.h>
 
// include the Direct3D Library file
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")
 
// define the screen resolution
#define SCREEN_WIDTH  800
#define SCREEN_HEIGHT 600
 
// global declarations
IDXGISwapChain *swapchain;             // the pointer to the swap chain interface
ID3D11Device *dev;                     // the pointer to our Direct3D device interface
ID3D11DeviceContext *devcon;           // the pointer to our Direct3D device context
ID3D11RenderTargetView *backbuffer;    // the pointer to our back buffer
ID3D11InputLayout *pLayout;            // the pointer to the input layout
ID3D11VertexShader *pVS;               // the pointer to the vertex shader
ID3D11PixelShader *pPS;                // the pointer to the pixel shader
ID3D11Buffer *pVBuffer;                // the pointer to the vertex buffer
 
// a struct to define a single vertex
struct VERTEX { FLOAT X, Y, Z; D3DXCOLOR Color; };
 
// function prototypes
void InitD3D(HWND hWnd);    // sets up and initializes Direct3D
void RenderFrame(void);     // renders a single frame
void CleanD3D(void);        // closes Direct3D and releases memory
void InitGraphics(void);    // creates the shape to render
void InitPipeline(void);    // loads and prepares the shaders
 
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
 
 
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
{
    HWND hWnd;
    WNDCLASSEX wc;
 
    ZeroMemory(&wc, sizeof(WNDCLASSEX));
 
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = L"WindowClass";
 
    RegisterClassEx(&wc);
 
    RECT wr = { 00, SCREEN_WIDTH, SCREEN_HEIGHT };
    AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
 
    hWnd = CreateWindowEx(NULL,
        L"WindowClass",
        L"Our First Direct3D Program",
        WS_OVERLAPPEDWINDOW,
        300,
        300,
        wr.right - wr.left,
        wr.bottom - wr.top,
        NULL,
        NULL,
        hInstance,
        NULL);
 
    ShowWindow(hWnd, nCmdShow);
 
    // set up and initialize Direct3D
    InitD3D(hWnd);
 
    // enter the main loop:
 
    MSG msg;
 
    while (TRUE)
    {
        if (PeekMessage(&msg, NULL00, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
 
            if (msg.message == WM_QUIT)
                break;
        }
 
        RenderFrame(); // 매 프레임마다 렌더프레임을 불러줌.
    }
 
    // clean up DirectX and COM
    CleanD3D();
 
    return msg.wParam;
}
 
 
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
    {
        PostQuitMessage(0);
        return 0;
    } break;
    }
 
    return DefWindowProc(hWnd, message, wParam, lParam);
}
 
 
// this function initializes and prepares Direct3D for use
void InitD3D(HWND hWnd)
{
    // create a struct to hold information about the swap chain
    DXGI_SWAP_CHAIN_DESC scd;
 
    // clear out the struct for use
    ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
 
    // fill the swap chain description struct
    scd.BufferCount = 1;                                   // one back buffer
    scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;    // use 32-bit color
    scd.BufferDesc.Width = SCREEN_WIDTH;                   // set the back buffer width
    scd.BufferDesc.Height = SCREEN_HEIGHT;                 // set the back buffer height
    scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;     // how swap chain is to be used
    scd.OutputWindow = hWnd;                               // the window to be used
    scd.SampleDesc.Count = 4;                              // how many multisamples
    scd.Windowed = TRUE;                                   // windowed/full-screen mode
    scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;    // allow full-screen switching
 
    // create a device, device context and swap chain using the information in the scd struct
    D3D11CreateDeviceAndSwapChain(NULL,
        D3D_DRIVER_TYPE_HARDWARE,
        NULL,
        NULL,
        NULL,
        NULL,
        D3D11_SDK_VERSION,
        &scd,
        &swapchain,
        &dev,
        NULL,
        &devcon);
 
 
    // get the address of the back buffer
    ID3D11Texture2D *pBackBuffer;
    swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
 
    // use the back buffer address to create the render target
    dev->CreateRenderTargetView(pBackBuffer, NULL&backbuffer);
    pBackBuffer->Release();
 
    // set the render target as the back buffer
    devcon->OMSetRenderTargets(1&backbuffer, NULL);
 
 
    // Set the viewport
    D3D11_VIEWPORT viewport;
    ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
 
    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
    viewport.Width = SCREEN_WIDTH;
    viewport.Height = SCREEN_HEIGHT;
 
    devcon->RSSetViewports(1&viewport);
 
    InitPipeline(); // 파이프라인을 초기화
    InitGraphics(); // 그래픽 초기화
}
 
 
// this is the function used to render a single frame
void RenderFrame(void)
{
    // clear the back buffer to a deep blue
    devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));
 
    // select which vertex buffer to display
    UINT stride = sizeof(VERTEX);
    UINT offset = 0;
    devcon->IASetVertexBuffers(01&pVBuffer, &stride, &offset); // 버텍스를 넣어준다
 
    // select which primtive type we are using
    devcon->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // 일반적인 삼각형을 그림
 
    // draw the vertex buffer to the back buffer
    devcon->Draw(30); // 점 3개를 그림
 
    // switch the back buffer and the front buffer
    swapchain->Present(00); // 프론트 버퍼랑 셋 버퍼
}
 
 
// this is the function that cleans up Direct3D and COM
void CleanD3D(void)
{
    swapchain->SetFullscreenState(FALSE, NULL);    // switch to windowed mode
 
    // close and release all existing COM objects
    pLayout->Release();
    pVS->Release();
    pPS->Release();
    pVBuffer->Release();
    swapchain->Release();
    backbuffer->Release();
    dev->Release();
    devcon->Release();
}
 
 
// this is the function that creates the shape to render
void InitGraphics()
{
    // create a triangle using the VERTEX struct
    VERTEX OurVertices[] =
    {
        {0.0f, 0.5f, 0.0f, D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f)},
        {0.45f, -0.50.0f, D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f)},
        {-0.45f, -0.5f, 0.0f, D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f)}
    };
 
 
    // create the vertex buffer // 버텍스 버퍼를 만듦. 셰이더에 집어넣어줌
    D3D11_BUFFER_DESC bd; 
    ZeroMemory(&bd, sizeof(bd));
 
    bd.Usage = D3D11_USAGE_DYNAMIC;                // write access access by CPU and GPU
    bd.ByteWidth = sizeof(VERTEX) * 3;             // size is the VERTEX struct * 3
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;       // use as a vertex buffer // 버텍스 버퍼랑 바인드
    bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;    // allow CPU to write in buffer // CPU에 쓰겠다
 
    dev->CreateBuffer(&bd, NULL&pVBuffer);       // create the buffer
 
 
    // copy the vertices into the buffer
    D3D11_MAPPED_SUBRESOURCE ms;
    devcon->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL&ms);    // map the buffer // 그래픽 카드의 메모리를 잠근다.
    memcpy(ms.pData, OurVertices, sizeof(OurVertices));                 // copy the data // 만든 버텍스 버퍼를 넣는다.
    devcon->Unmap(pVBuffer, NULL);                                      // unmap the buffer //메모리 잠근 것을 풀어준다.
}
 
 
// this function loads and prepares the shaders
void InitPipeline()
{
    // load and compile the two shaders
    ID3D10Blob *VS, *PS;
    D3DX11CompileFromFile(L"shaders.shader"00"VShader""vs_4_0"000&VS, 00); // 문자열에 L이 붙는 건 유니코드
    D3DX11CompileFromFile(L"shaders.shader"00"PShader""ps_4_0"000&PS, 00);
 
    // encapsulate both shaders into shader objects
    dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL&pVS);
    dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL&pPS);
 
    // set the shader objects
    devcon->VSSetShader(pVS, 00); // vShader를 0번째부터 0번 ID에 넣겠다
    devcon->PSSetShader(pPS, 00);
 
    // create the input layout object
    D3D11_INPUT_ELEMENT_DESC ied[] =
    { // 구조체의 내용과 그릴 내용(포지션, 컬러)을 일치 시킴
        {"POSITION"0, DXGI_FORMAT_R32G32B32_FLOAT, 00, D3D11_INPUT_PER_VERTEX_DATA, 0},
        {"COLOR"0, DXGI_FORMAT_R32G32B32A32_FLOAT, 012, D3D11_INPUT_PER_VERTEX_DATA, 0},
    };
 
    dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
    devcon->IASetInputLayout(pLayout);
}
 
cs


'기본개념 > 분류가 애매한거' 카테고리의 다른 글

버니 킹덤 점수 계산기 (미완)  (0) 2018.12.22
[강연] 혼자서 성장하기  (0) 2018.12.04
콘솔창에 색 넣기  (0) 2018.02.09
Comments