rev |
line source |
nuclear@3
|
1 #include <stdio.h>
|
nuclear@3
|
2 #include <stdlib.h>
|
nuclear@3
|
3 #include <math.h>
|
nuclear@3
|
4 #include <stddef.h>
|
nuclear@3
|
5 #include <d3d11.h>
|
nuclear@3
|
6 #include <d3dx11.h>
|
nuclear@3
|
7
|
nuclear@3
|
8 struct Vertex {
|
nuclear@3
|
9 float pos[3];
|
nuclear@3
|
10 float color[4];
|
nuclear@3
|
11 };
|
nuclear@3
|
12
|
nuclear@3
|
13 struct RenderState {
|
nuclear@3
|
14 float modelview[16];
|
nuclear@3
|
15 float projection[16];
|
nuclear@3
|
16 };
|
nuclear@3
|
17
|
nuclear@3
|
18 static bool init();
|
nuclear@3
|
19 static void cleanup();
|
nuclear@3
|
20 static void display();
|
nuclear@3
|
21 static void reshape(int x, int y);
|
nuclear@3
|
22 static void keyb(int key, bool pressed);
|
nuclear@3
|
23 static HWND create_window(int xsz, int ysz);
|
nuclear@3
|
24 static void destroy_window(HWND win);
|
nuclear@3
|
25 static void main_loop();
|
nuclear@3
|
26 static long CALLBACK win_proc(HWND win, unsigned int msg, unsigned int wparam, long lparam);
|
nuclear@3
|
27
|
nuclear@3
|
28 static int width, height;
|
nuclear@3
|
29
|
nuclear@3
|
30 static HWND win;
|
nuclear@3
|
31 static IDXGISwapChain *swap;
|
nuclear@3
|
32 static ID3D11Device *dev;
|
nuclear@3
|
33 static ID3D11DeviceContext *ctx;
|
nuclear@3
|
34 static ID3D11RenderTargetView *rtarg_view;
|
nuclear@3
|
35 static ID3D11InputLayout *vertex_layout;
|
nuclear@3
|
36 static ID3D11VertexShader *vsdr;
|
nuclear@3
|
37 static ID3D11PixelShader *psdr;
|
nuclear@3
|
38 static ID3D11Buffer *vbuf;
|
nuclear@3
|
39 static ID3D11Buffer *rstate_buf;
|
nuclear@3
|
40
|
nuclear@3
|
41 static RenderState rstate;
|
nuclear@3
|
42
|
nuclear@3
|
43 int main()
|
nuclear@3
|
44 {
|
nuclear@3
|
45 if(!init()) {
|
nuclear@3
|
46 return 1;
|
nuclear@3
|
47 }
|
nuclear@3
|
48 atexit(cleanup);
|
nuclear@3
|
49
|
nuclear@3
|
50 main_loop();
|
nuclear@3
|
51 return 0;
|
nuclear@3
|
52 }
|
nuclear@3
|
53
|
nuclear@3
|
54 static bool init()
|
nuclear@3
|
55 {
|
nuclear@3
|
56 if(!(win = create_window(800, 600))) {
|
nuclear@3
|
57 return false;
|
nuclear@3
|
58 }
|
nuclear@3
|
59
|
nuclear@3
|
60 unsigned int sdrflags = 0;//D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_DEBUG;
|
nuclear@3
|
61
|
nuclear@3
|
62 ID3DBlob *vsbuf, *psbuf, *msgblob;
|
nuclear@3
|
63 if(D3DX11CompileFromFile("shader.hlsl", 0, 0, "vertex_main", "vs_4_0", sdrflags, 0, 0, &vsbuf, &msgblob, 0) != 0) {
|
nuclear@3
|
64 fprintf(stderr, "failed to load vertex shader\n");
|
nuclear@3
|
65 if(msgblob->GetBufferSize() > 0) {
|
nuclear@3
|
66 fprintf(stderr, "Vertex Shader:\n%s\n", (char*)msgblob->GetBufferPointer());
|
nuclear@3
|
67 }
|
nuclear@3
|
68 return false;
|
nuclear@3
|
69 }
|
nuclear@3
|
70 if(D3DX11CompileFromFile("shader.hlsl", 0, 0, "pixel_main", "ps_4_0", sdrflags, 0, 0, &psbuf, &msgblob, 0) != 0) {
|
nuclear@3
|
71 fprintf(stderr, "failed to load pixel shader\n");
|
nuclear@3
|
72 if(msgblob->GetBufferSize() > 0) {
|
nuclear@3
|
73 fprintf(stderr, "Pixel Shader:\n%s\n", (char*)msgblob->GetBufferPointer());
|
nuclear@3
|
74 }
|
nuclear@3
|
75 return false;
|
nuclear@3
|
76 }
|
nuclear@3
|
77
|
nuclear@3
|
78 if(dev->CreateVertexShader(vsbuf->GetBufferPointer(), vsbuf->GetBufferSize(), 0, &vsdr) != 0) {
|
nuclear@3
|
79 fprintf(stderr, "failed to create vertex shader\n");
|
nuclear@3
|
80 return false;
|
nuclear@3
|
81 }
|
nuclear@3
|
82 if(dev->CreatePixelShader(psbuf->GetBufferPointer(), psbuf->GetBufferSize(), 0, &psdr) != 0) {
|
nuclear@3
|
83 fprintf(stderr, "failed to create pixel shader\n");
|
nuclear@3
|
84 return false;
|
nuclear@3
|
85 }
|
nuclear@3
|
86
|
nuclear@3
|
87 D3D11_INPUT_ELEMENT_DESC elem_desc[2];
|
nuclear@3
|
88 elem_desc[0].SemanticName = "position";
|
nuclear@3
|
89 elem_desc[0].SemanticIndex = 0;
|
nuclear@3
|
90 elem_desc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
nuclear@3
|
91 elem_desc[0].InputSlot = 0;
|
nuclear@3
|
92 elem_desc[0].AlignedByteOffset = 0;
|
nuclear@3
|
93 elem_desc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
nuclear@3
|
94 elem_desc[0].InstanceDataStepRate = 0;
|
nuclear@3
|
95
|
nuclear@3
|
96 elem_desc[1].SemanticName = "color";
|
nuclear@3
|
97 elem_desc[1].SemanticIndex = 0;
|
nuclear@3
|
98 elem_desc[1].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
nuclear@3
|
99 elem_desc[1].InputSlot = 0;
|
nuclear@3
|
100 elem_desc[1].AlignedByteOffset = offsetof(Vertex, color);
|
nuclear@3
|
101 elem_desc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
nuclear@3
|
102 elem_desc[1].InstanceDataStepRate = 0;
|
nuclear@3
|
103
|
nuclear@3
|
104 if(dev->CreateInputLayout(elem_desc, 2, vsbuf->GetBufferPointer(), vsbuf->GetBufferSize(), &vertex_layout) != 0) {
|
nuclear@3
|
105 fprintf(stderr, "failed to create vertex layout\n");
|
nuclear@3
|
106 return 0;
|
nuclear@3
|
107 }
|
nuclear@3
|
108 vsbuf->Release();
|
nuclear@3
|
109 psbuf->Release();
|
nuclear@3
|
110
|
nuclear@3
|
111 // --- create vertex buffer ---
|
nuclear@3
|
112 Vertex varr[] = {
|
nuclear@3
|
113 {{-0.6, -0.4, 0}, {1, 0, 0, 1}},
|
nuclear@3
|
114 {{0.0, 0.6, 0}, {0, 1, 0, 1}},
|
nuclear@3
|
115 {{0.6, -0.4, 0}, {0, 0, 1, 1}}
|
nuclear@3
|
116 };
|
nuclear@3
|
117
|
nuclear@3
|
118 D3D11_BUFFER_DESC buf_desc;
|
nuclear@3
|
119 memset(&buf_desc, 0, sizeof buf_desc);
|
nuclear@3
|
120 buf_desc.Usage = D3D11_USAGE_DEFAULT;
|
nuclear@3
|
121 buf_desc.ByteWidth = sizeof varr;
|
nuclear@3
|
122 buf_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
nuclear@3
|
123
|
nuclear@3
|
124 D3D11_SUBRESOURCE_DATA subdata;
|
nuclear@3
|
125 memset(&subdata, 0, sizeof subdata);
|
nuclear@3
|
126 subdata.pSysMem = varr;
|
nuclear@3
|
127 if(dev->CreateBuffer(&buf_desc, &subdata, &vbuf) != 0) {
|
nuclear@3
|
128 fprintf(stderr, "failed to create vertex buffer\n");
|
nuclear@3
|
129 return false;
|
nuclear@3
|
130 }
|
nuclear@3
|
131
|
nuclear@3
|
132 // render state buffer
|
nuclear@3
|
133 memset(&buf_desc, 0, sizeof buf_desc);
|
nuclear@3
|
134 buf_desc.Usage = D3D11_USAGE_DEFAULT;
|
nuclear@3
|
135 buf_desc.ByteWidth = sizeof(RenderState);
|
nuclear@3
|
136 buf_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
nuclear@3
|
137
|
nuclear@3
|
138 memset(&subdata, 0, sizeof subdata);
|
nuclear@3
|
139 subdata.pSysMem = &rstate;
|
nuclear@3
|
140 if(dev->CreateBuffer(&buf_desc, &subdata, &rstate_buf) != 0) {
|
nuclear@3
|
141 fprintf(stderr, "failed to create render state buffer\n");
|
nuclear@3
|
142 return false;
|
nuclear@3
|
143 }
|
nuclear@3
|
144
|
nuclear@3
|
145 return true;
|
nuclear@3
|
146 }
|
nuclear@3
|
147
|
nuclear@3
|
148 static void cleanup()
|
nuclear@3
|
149 {
|
nuclear@3
|
150 vbuf->Release();
|
nuclear@3
|
151 rstate_buf->Release();
|
nuclear@3
|
152 vsdr->Release();
|
nuclear@3
|
153 psdr->Release();
|
nuclear@3
|
154 vertex_layout->Release();
|
nuclear@3
|
155 destroy_window(win);
|
nuclear@3
|
156 }
|
nuclear@3
|
157
|
nuclear@3
|
158 static void set_identity(float *mat)
|
nuclear@3
|
159 {
|
nuclear@3
|
160 mat[0] = mat[5] = mat[10] = mat[15] = 1.0;
|
nuclear@3
|
161 mat[1] = mat[2] = mat[3] = mat[4] = mat[6] = mat[7] = mat[8] = mat[9] = mat[11] = mat[12] = mat[13] = mat[14] = 0.0;
|
nuclear@3
|
162 }
|
nuclear@3
|
163
|
nuclear@3
|
164 static void set_rotation_z(float *mat, float angle)
|
nuclear@3
|
165 {
|
nuclear@3
|
166 set_identity(mat);
|
nuclear@3
|
167
|
nuclear@3
|
168 mat[0] = cos(angle);
|
nuclear@3
|
169 mat[1] = -sin(angle);
|
nuclear@3
|
170 mat[4] = sin(angle);
|
nuclear@3
|
171 mat[5] = cos(angle);
|
nuclear@3
|
172 }
|
nuclear@3
|
173
|
nuclear@3
|
174 static void set_ortho(float *mat, float aspect)
|
nuclear@3
|
175 {
|
nuclear@3
|
176 set_identity(mat);
|
nuclear@3
|
177 mat[0] = 1.0 / aspect;
|
nuclear@3
|
178 }
|
nuclear@3
|
179
|
nuclear@3
|
180 static void display()
|
nuclear@3
|
181 {
|
nuclear@3
|
182 unsigned int msec = timeGetTime();
|
nuclear@3
|
183
|
nuclear@3
|
184 float fbcolor[] = {0.2f, 0.2f, 0.2f, 1.0f};
|
nuclear@3
|
185 ctx->ClearRenderTargetView(rtarg_view, fbcolor);
|
nuclear@3
|
186
|
nuclear@3
|
187 // set render state constant buffer data
|
nuclear@3
|
188 set_ortho(rstate.projection, (float)width / (float)height);
|
nuclear@3
|
189 set_rotation_z(rstate.modelview, msec / 1000.0);
|
nuclear@3
|
190
|
nuclear@3
|
191 ctx->UpdateSubresource(rstate_buf, 0, 0, &rstate, 0, 0);
|
nuclear@3
|
192 ctx->VSSetConstantBuffers(0, 1, &rstate_buf);
|
nuclear@3
|
193
|
nuclear@3
|
194
|
nuclear@3
|
195 unsigned int stride = sizeof(Vertex);
|
nuclear@3
|
196 unsigned int offset = 0;
|
nuclear@3
|
197 ctx->IASetVertexBuffers(0, 1, &vbuf, &stride, &offset);
|
nuclear@3
|
198 ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
nuclear@3
|
199 ctx->IASetInputLayout(vertex_layout);
|
nuclear@3
|
200
|
nuclear@3
|
201 ctx->VSSetShader(vsdr, 0, 0);
|
nuclear@3
|
202 ctx->PSSetShader(psdr, 0, 0);
|
nuclear@3
|
203
|
nuclear@3
|
204 ctx->Draw(3, 0);
|
nuclear@3
|
205
|
nuclear@3
|
206 swap->Present(0, 0);
|
nuclear@3
|
207 }
|
nuclear@3
|
208
|
nuclear@3
|
209 static void reshape(int x, int y)
|
nuclear@3
|
210 {
|
nuclear@3
|
211 width = x;
|
nuclear@3
|
212 height = y;
|
nuclear@3
|
213
|
nuclear@3
|
214 D3D11_VIEWPORT vp;
|
nuclear@3
|
215 vp.Width = (float)x;
|
nuclear@3
|
216 vp.Height = (float)y;
|
nuclear@3
|
217 vp.MinDepth = 0;
|
nuclear@3
|
218 vp.MaxDepth = 1;
|
nuclear@3
|
219 vp.TopLeftX = 0;
|
nuclear@3
|
220 vp.TopLeftY = 0;
|
nuclear@3
|
221 ctx->RSSetViewports(1, &vp);
|
nuclear@3
|
222
|
nuclear@3
|
223 // TODO probably we also need to resize render targets or whatever...
|
nuclear@3
|
224 }
|
nuclear@3
|
225
|
nuclear@3
|
226 static void keyb(int key, bool pressed)
|
nuclear@3
|
227 {
|
nuclear@3
|
228 if(key == 27) {
|
nuclear@3
|
229 exit(0);
|
nuclear@3
|
230 }
|
nuclear@3
|
231 }
|
nuclear@3
|
232
|
nuclear@3
|
233 // ---- system crap ----
|
nuclear@3
|
234
|
nuclear@3
|
235 static HWND create_window(int xsz, int ysz)
|
nuclear@3
|
236 {
|
nuclear@3
|
237 HINSTANCE app_inst = GetModuleHandle(0);
|
nuclear@3
|
238
|
nuclear@3
|
239 WNDCLASS wclass;
|
nuclear@3
|
240 memset(&wclass, 0, sizeof wclass);
|
nuclear@3
|
241 wclass.hInstance = app_inst;
|
nuclear@3
|
242 wclass.lpfnWndProc = win_proc;
|
nuclear@3
|
243 wclass.lpszClassName = "mutantstargoatwin";
|
nuclear@3
|
244 wclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
nuclear@3
|
245 wclass.hIcon = LoadIcon(0, IDI_APPLICATION);
|
nuclear@3
|
246 wclass.hCursor = LoadCursor(0, IDC_ARROW);
|
nuclear@3
|
247 wclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
nuclear@3
|
248 RegisterClass(&wclass);
|
nuclear@3
|
249
|
nuclear@3
|
250 int posx = (GetSystemMetrics(SM_CXSCREEN) - xsz) / 2;
|
nuclear@3
|
251 int posy = (GetSystemMetrics(SM_CYSCREEN) - ysz) / 2;
|
nuclear@3
|
252
|
nuclear@3
|
253 HWND win = CreateWindow("mutantstargoatwin", "DX11 Test", WS_OVERLAPPEDWINDOW, posx, posy,
|
nuclear@3
|
254 xsz, ysz, 0, 0, app_inst, 0);
|
nuclear@3
|
255 ShowWindow(win, SW_SHOW);
|
nuclear@3
|
256
|
nuclear@3
|
257 // initialize D3D device
|
nuclear@3
|
258 DXGI_SWAP_CHAIN_DESC swap_desc;
|
nuclear@3
|
259 memset(&swap_desc, 0, sizeof swap_desc);
|
nuclear@3
|
260 swap_desc.BufferCount = 1;
|
nuclear@3
|
261 swap_desc.BufferDesc.Width = xsz;
|
nuclear@3
|
262 swap_desc.BufferDesc.Height = ysz;
|
nuclear@3
|
263 swap_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
nuclear@3
|
264 swap_desc.BufferDesc.RefreshRate.Numerator = 60;
|
nuclear@3
|
265 swap_desc.BufferDesc.RefreshRate.Denominator = 1;
|
nuclear@3
|
266 swap_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
nuclear@3
|
267 swap_desc.OutputWindow = win;
|
nuclear@3
|
268 swap_desc.SampleDesc.Count = 1;
|
nuclear@3
|
269 swap_desc.SampleDesc.Quality = 0;
|
nuclear@3
|
270 swap_desc.Windowed = 1;
|
nuclear@3
|
271
|
nuclear@3
|
272 D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0;
|
nuclear@3
|
273
|
nuclear@3
|
274 if(D3D11CreateDeviceAndSwapChain(0, D3D_DRIVER_TYPE_HARDWARE, 0, 0, &feature_level, 1,
|
nuclear@3
|
275 D3D11_SDK_VERSION, &swap_desc, &swap, &dev, 0, &ctx) != 0) {
|
nuclear@3
|
276 fprintf(stderr, "Failed to create d3d device and swap chain\n");
|
nuclear@3
|
277 return 0;
|
nuclear@3
|
278 }
|
nuclear@3
|
279
|
nuclear@3
|
280 ID3D11Texture2D *rtex;
|
nuclear@3
|
281 if(swap->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&rtex) != 0) {
|
nuclear@3
|
282 fprintf(stderr, "Failed to get default render target texture\n");
|
nuclear@3
|
283 return 0;
|
nuclear@3
|
284 }
|
nuclear@3
|
285 if(dev->CreateRenderTargetView(rtex, 0, &rtarg_view) != 0) {
|
nuclear@3
|
286 fprintf(stderr, "Failed to create render target view\n");
|
nuclear@3
|
287 rtex->Release();
|
nuclear@3
|
288 return 0;
|
nuclear@3
|
289 }
|
nuclear@3
|
290 rtex->Release();
|
nuclear@3
|
291 ctx->OMSetRenderTargets(1, &rtarg_view, 0);
|
nuclear@3
|
292
|
nuclear@3
|
293 reshape(xsz, ysz);
|
nuclear@3
|
294 return win;
|
nuclear@3
|
295 }
|
nuclear@3
|
296
|
nuclear@3
|
297 static void destroy_window(HWND win)
|
nuclear@3
|
298 {
|
nuclear@3
|
299 CloseWindow(win);
|
nuclear@3
|
300 UnregisterClass("mutantstargoatwin", GetModuleHandle(0));
|
nuclear@3
|
301
|
nuclear@3
|
302 rtarg_view->Release();
|
nuclear@3
|
303 ctx->Release();
|
nuclear@3
|
304 dev->Release();
|
nuclear@3
|
305 swap->Release();
|
nuclear@3
|
306 }
|
nuclear@3
|
307
|
nuclear@3
|
308 static void main_loop()
|
nuclear@3
|
309 {
|
nuclear@3
|
310 MSG msg;
|
nuclear@3
|
311
|
nuclear@3
|
312 for(;;) {
|
nuclear@3
|
313 while(PeekMessage(&msg, win, 0, 0, PM_REMOVE)) {
|
nuclear@3
|
314 TranslateMessage(&msg);
|
nuclear@3
|
315 DispatchMessage(&msg);
|
nuclear@3
|
316
|
nuclear@3
|
317 if(msg.message == WM_QUIT) {
|
nuclear@3
|
318 return;
|
nuclear@3
|
319 }
|
nuclear@3
|
320 }
|
nuclear@3
|
321
|
nuclear@3
|
322 display();
|
nuclear@3
|
323 }
|
nuclear@3
|
324 }
|
nuclear@3
|
325
|
nuclear@3
|
326 static long CALLBACK win_proc(HWND win, unsigned int msg, unsigned int wparam, long lparam)
|
nuclear@3
|
327 {
|
nuclear@3
|
328 switch(msg) {
|
nuclear@3
|
329 case WM_KEYDOWN:
|
nuclear@3
|
330 keyb(wparam, true);
|
nuclear@3
|
331 break;
|
nuclear@3
|
332
|
nuclear@3
|
333 case WM_KEYUP:
|
nuclear@3
|
334 keyb(wparam, false);
|
nuclear@3
|
335 break;
|
nuclear@3
|
336
|
nuclear@3
|
337 default:
|
nuclear@3
|
338 return DefWindowProc(win, msg, wparam, lparam);
|
nuclear@3
|
339 }
|
nuclear@3
|
340 return 0;
|
nuclear@3
|
341 }
|