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