其实编译器也不是不做了,只是长时间连续做一个不能看的编译器,总是有点不爽。因此我决定把业余的时间的主要部分花在编译器上,而次要的部分则玩游戏,出去游乐,学DirectX11。
在我还是14岁的时候那会,刚开始学习编程不久就买了那本《Visual Basic高级图形程序设计教程》,从此我走上了做图形的道路上。后来做游戏,到了大学找不到伴,因此果断转做编译器。不过每次见到图形的时候心里总是有点痒痒的。在那之后我依然跟朋友或者自己看一些关于图形的内容,《GPUGems》之流的我也读了,只不过再也没有实践过。后来就做了
软件渲染器,主要原因还是不想完全放弃那个东西。最近又玩了很多游戏,让我更是想再次做一做图形的事情。
以前写了opengl,就想想现在还是做directx好了,于是前几天就去下载最新的DXSDK,然后我才知道Windows7已经内置了DirectX11,免去了不少麻烦。所以从今天开始决定重操旧业,在做编译器之后的闲暇时间里面,玩玩DirectX11,看看能不能搞出什么东西来。
顺便推荐一下
DirectX Tutorial网站,DirectX的文档还是远远没有Win32API文档写得清晰,没有那个重要的about和using章节,只有reference。所以在这个网站上入入门还是不错的。
在这里贴一下我从那个tutorial网站上山寨过来的小程序。运行结果一摸一样,我就不贴图了。之所以把那个破程序改成这样,主要是因为习惯写库了,所以想把一些不太会变化的代码抽出来坐在一起,免得以后总是要写。
DirectXSetup.h
1 #ifndef VCZH_DIRECTXSETUP
2 #define VCZH_DIRECTXSETUP
3
4 #include <D3D11.h>
5 #include <d3dx11.h>
6 #include <d3dx10.h>
7
8 namespace vl
9 {
10 namespace directx
11 {
12 struct DirectXEnvironment
13 {
14 IDXGISwapChain* swapChain;
15 ID3D11Device* device;
16 ID3D11DeviceContext* context;
17 D3D_FEATURE_LEVEL featureLevel;
18
19 ID3D11RenderTargetView* renderTargetView;
20 };
21 extern const DirectXEnvironment* CreateDirectXEnvironment(HWND mainWindowHandle);
22 extern const void DestroyDirectXEnvironment();
23 }
24 }
25
26 #endif
DirectXSetup.cpp
1 #include "DirectXSetup.h"
2
3 #if _DEBUG
4 #define _CRTDBG_MAP_ALLOC
5 #include <stdlib.h>
6 #include <crtdbg.h>
7 #endif
8 #include <Windows.h>
9
10 #pragma comment(lib, "d3d11.lib")
11 #pragma comment(lib, "d3dx11.lib")
12 #pragma comment(lib, "d3dx10.lib")
13
14 using namespace vl;
15 using namespace vl::directx;
16
17 /***********************************************************************
18 DirectX
19 ***********************************************************************/
20
21 HRESULT SetupDirectXEnvironment(DirectXEnvironment* env, HWND outputWindow, int clientWidth, int clientHeight)
22 {
23 //=========================================
24 // define device
25 ZeroMemory(env, sizeof(*env));
26 DXGI_SWAP_CHAIN_DESC sd;
27 ZeroMemory(&sd, sizeof(sd));
28 sd.BufferCount = 1;
29 sd.BufferDesc.Width = clientWidth;
30 sd.BufferDesc.Height = clientHeight;
31 sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
32 sd.BufferDesc.RefreshRate.Numerator = 60;
33 sd.BufferDesc.RefreshRate.Denominator = 1;
34 sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
35 sd.OutputWindow = outputWindow;
36 sd.SampleDesc.Count = 1;
37 sd.SampleDesc.Quality = 0;
38 sd.Windowed = TRUE;
39
40 //=========================================
41 // create device
42 D3D_FEATURE_LEVEL featureLevels = D3D_FEATURE_LEVEL_10_1;
43 HRESULT hr = S_OK;
44 if(FAILED(hr = D3D11CreateDeviceAndSwapChain(
45 NULL,
46 D3D_DRIVER_TYPE_WARP,
47 NULL,
48 0,
49 &featureLevels,
50 1,
51 D3D11_SDK_VERSION,
52 &sd,
53 &env->swapChain,
54 &env->device,
55 &env->featureLevel,
56 &env->context
57 ))
58 )
59 {
60 return hr;
61 }
62
63 //=========================================
64 // create render target
65 {
66 ID3D11Texture2D* texture2DBackBuffer=0;
67 env->swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&texture2DBackBuffer);
68 if(FAILED(hr = env->device->CreateRenderTargetView(texture2DBackBuffer, NULL, &env->renderTargetView)))
69 return hr;
70 texture2DBackBuffer->Release();
71 env->context->OMSetRenderTargets(1, &env->renderTargetView, NULL);
72 }
73
74 //=========================================
75 // set viewport
76 {
77 D3D11_VIEWPORT viewport;
78 ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
79 viewport.TopLeftX = 0;
80 viewport.TopLeftY = 0;
81 viewport.Width = (FLOAT)clientWidth;
82 viewport.Height = (FLOAT)clientHeight;
83 env->context->RSSetViewports(1, &viewport);
84 }
85
86 //=========================================
87 // succeeded
88 return S_OK;
89 }
90
91 void ReleaseDirectXEnvironment(DirectXEnvironment* env)
92 {
93 env->renderTargetView->Release();
94 env->swapChain->Release();
95 env->device->Release();
96 env->context->Release();
97 }
98
99 /***********************************************************************
100 Interface
101 ***********************************************************************/
102
103 namespace vl
104 {
105 namespace directx
106 {
107 DirectXEnvironment* directXEnvironment=0;
108
109 const DirectXEnvironment* CreateDirectXEnvironment(HWND mainWindowHandle)
110 {
111 if(!directXEnvironment)
112 {
113 directXEnvironment=new DirectXEnvironment;
114
115 RECT required={0,0,0,0};
116 RECT bounds;
117 GetWindowRect(mainWindowHandle, &bounds);
118 AdjustWindowRect(&required, GetWindowLongPtr(mainWindowHandle, GWL_STYLE), FALSE);
119 int width=(bounds.right-bounds.left)-(required.right-required.left);
120 int height=(bounds.bottom-bounds.top)-(required.bottom-required.top);
121
122 SetupDirectXEnvironment(directXEnvironment, mainWindowHandle, width, height);
123 }
124 return directXEnvironment;
125 }
126
127 const void DestroyDirectXEnvironment()
128 {
129 if(directXEnvironment)
130 {
131 ReleaseDirectXEnvironment(directXEnvironment);
132 delete directXEnvironment;
133 directXEnvironment=0;
134 }
135 }
136 }
137 }
138 using namespace vl;
139 using namespace vl::directx;
140
141 /***********************************************************************
142 Window
143 ***********************************************************************/
144
145 extern LRESULT CALLBACK DirectXProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& callDefWindowProc);
146
147 LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
148 {
149 bool callDefWindowProc=true;
150 switch(uMsg)
151 {
152 case WM_DESTROY:
153 PostQuitMessage(0);
154 break;
155 case WM_ERASEBKGND:
156 callDefWindowProc=false;
157 break;
158 }
159
160 LRESULT result=DirectXProc(hwnd, uMsg, wParam, lParam, callDefWindowProc);
161 if(!callDefWindowProc)
162 {
163 return result;
164 }
165 return DefWindowProc(hwnd, uMsg, wParam, lParam);
166 }
167
168 BOOL CALLBACK PrimaryMonitorSelector(
169 HMONITOR hMonitor,
170 HDC hdcMonitor,
171 LPRECT lprcMonitor,
172 LPARAM dwData
173 )
174 {
175 MONITORINFOEX info;
176 info.cbSize=sizeof(MONITORINFOEX);
177 GetMonitorInfo(hMonitor, &info);
178 if(info.dwFlags==MONITORINFOF_PRIMARY)
179 {
180 HMONITOR* pMonitor=(HMONITOR*)dwData;
181 *pMonitor=hMonitor;
182 return FALSE;
183 }
184 else
185 {
186 return TRUE;
187 }
188 }
189
190 void RunWindow(HINSTANCE hInstance, int clientWidth, int clientHeight)
191 {
192 //=========================================
193 // global variables
194 WNDCLASSEX windowClass;
195 HWND mainWindowHandle;
196
197 //=========================================
198 // create class
199 {
200 windowClass.cbSize=sizeof(windowClass);
201 windowClass.style=CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC;
202 windowClass.lpfnWndProc=WndProc;
203 windowClass.cbClsExtra=0;
204 windowClass.cbWndExtra=0;
205 windowClass.hInstance=hInstance;
206 windowClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
207 windowClass.hCursor=LoadCursor(NULL,IDC_ARROW);
208 windowClass.hbrBackground=GetSysColorBrush(COLOR_BTNFACE);
209 windowClass.lpszMenuName=NULL;
210 windowClass.lpszClassName=L"VczhDirectXWindowClass";
211 windowClass.hIconSm=NULL;
212 RegisterClassEx(&windowClass);
213 }
214
215 //=========================================
216 // create window
217 {
218 DWORD exStyle=WS_EX_APPWINDOW | WS_EX_CONTROLPARENT;
219 DWORD style=WS_BORDER | WS_CAPTION | WS_SIZEBOX | WS_SYSMENU | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_MAXIMIZEBOX | WS_MINIMIZEBOX;
220 mainWindowHandle=CreateWindowEx(exStyle, windowClass.lpszClassName, L"Vczh DirectX Window", style, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
221 }
222
223 //=========================================
224 // calculate position
225 {
226 HMONITOR primaryMonitor=0;
227 EnumDisplayMonitors(NULL, NULL, PrimaryMonitorSelector, (LPARAM)(&primaryMonitor));
228 MONITORINFOEX monitorInfo;
229 monitorInfo.cbSize=sizeof(MONITORINFOEX);
230 GetMonitorInfo(primaryMonitor, &monitorInfo);
231
232 RECT required={0, 0, clientWidth, clientHeight};
233 AdjustWindowRect(&required, GetWindowLongPtr(mainWindowHandle, GWL_STYLE), FALSE);
234
235 int width=required.right-required.left;
236 int height=required.bottom-required.top;
237 int left=monitorInfo.rcWork.left+(monitorInfo.rcWork.right-monitorInfo.rcWork.left-width)/2;
238 int top=monitorInfo.rcWork.top+(monitorInfo.rcWork.bottom-monitorInfo.rcWork.top-height)/2;
239 MoveWindow(mainWindowHandle, left, top, width, height, TRUE);
240 }
241
242 //=========================================
243 // run
244 {
245 ShowWindow(mainWindowHandle, SW_SHOWNORMAL);
246 MSG message;
247 while(GetMessage(&message, NULL, 0, 0))
248 {
249 TranslateMessage(&message);
250 DispatchMessage(&message);
251 }
252 }
253
254 //=========================================
255 // exit
256 DestroyWindow(mainWindowHandle);
257 }
258
259 /***********************************************************************
260 WinMain
261 ***********************************************************************/
262
263 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
264 {
265 RunWindow(hInstance, 800, 600);
266 #if _DEBUG
267 _CrtDumpMemoryLeaks();
268 #endif
269 return 0;
270 }
Shaders.txt
1 struct VOut
2 {
3 float4 position : SV_POSITION;
4 float4 color : COLOR;
5 };
6
7 VOut VShader(float4 position : POSITION, float4 color : COLOR)
8 {
9 VOut output;
10
11 output.position = position;
12 output.color = color;
13
14 return output;
15 }
16
17 float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
18 {
19 return color;
20 }
Main.cpp
1 #include "..\Shared\DirectXSetup.h"
2
3 using namespace vl;
4 using namespace vl::directx;
5
6 struct VERTEX
7 {
8 FLOAT X, Y, Z;
9 D3DXCOLOR Color;
10 };
11
12 struct World
13 {
14 const DirectXEnvironment* env;
15 ID3D11VertexShader* vertexShader;
16 ID3D11InputLayout* vertexLayout;
17 ID3D11PixelShader* pixelShader;
18 ID3D11Buffer* vertexBuffer;
19
20 World(const DirectXEnvironment* _env)
21 :env(_env)
22 ,vertexShader(0)
23 ,vertexLayout(0)
24 ,pixelShader(0)
25 ,vertexBuffer(0)
26 {
27 ID3D10Blob* vsBlob=0;
28 ID3D10Blob* psBlob=0;
29 D3DX11CompileFromFile(L"Shaders.txt", 0, 0, "VShader", "vs_4_0", 0, 0, 0, &vsBlob, 0, 0);
30 D3DX11CompileFromFile(L"Shaders.txt", 0, 0, "PShader", "ps_4_0", 0, 0, 0, &psBlob, 0, 0);
31 if(vsBlob)
32 {
33 env->device->CreateVertexShader(vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), NULL, &vertexShader);
34 env->context->VSSetShader(vertexShader, 0, 0);
35 }
36 if(psBlob)
37 {
38 env->device->CreatePixelShader(psBlob->GetBufferPointer(), psBlob->GetBufferSize(), NULL, &pixelShader);
39 env->context->PSSetShader(pixelShader, 0, 0);
40 }
41 if(vsBlob)
42 {
43 D3D11_INPUT_ELEMENT_DESC ied[] =
44 {
45 {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
46 {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
47 };
48 env->device->CreateInputLayout(ied, 2, vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), &vertexLayout);
49 env->context->IASetInputLayout(vertexLayout);
50 }
51
52 {
53 VERTEX vertices[] =
54 {
55 {0.0f, 0.5f, 0.0f, D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f)},
56 {0.45f, -0.5, 0.0f, D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f)},
57 {-0.45f, -0.5f, 0.0f, D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f)}
58 };
59
60 D3D11_BUFFER_DESC bd;
61 ZeroMemory(&bd, sizeof(bd));
62 bd.Usage = D3D11_USAGE_DYNAMIC;
63 bd.ByteWidth = sizeof(vertices);
64 bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
65 bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
66 env->device->CreateBuffer(&bd, NULL, &vertexBuffer);
67
68 D3D11_MAPPED_SUBRESOURCE ms;
69 env->context->Map(vertexBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);
70 memcpy(ms.pData, vertices, sizeof(vertices));
71 env->context->Unmap(vertexBuffer, NULL);
72 }
73 }
74
75 ~World()
76 {
77 if(vertexShader) vertexShader->Release();
78 if(pixelShader) pixelShader->Release();
79 if(vertexLayout) vertexLayout->Release();
80 if(vertexBuffer) vertexBuffer->Release();
81 }
82
83 void Render()
84 {
85 env->context->ClearRenderTargetView(env->renderTargetView, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));
86 {
87 UINT stride=sizeof(VERTEX);
88 UINT offset=0;
89 env->context->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
90 env->context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
91 env->context->Draw(3, 0);
92 }
93 env->swapChain->Present(0, 0);
94 }
95 };
96 World* world=0;
97
98 LRESULT CALLBACK DirectXProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& callDefWindowProc)
99 {
100 switch(uMsg)
101 {
102 case WM_SHOWWINDOW:
103 {
104 if(wParam==TRUE)
105 {
106 if(!world)
107 {
108 const DirectXEnvironment* env=CreateDirectXEnvironment(hwnd);
109 world=new World(env);
110 world->Render();
111 }
112 }
113 }
114 break;
115 case WM_DESTROY:
116 {
117 if(world)
118 {
119 delete world;
120 world=0;
121 DestroyDirectXEnvironment();
122 }
123 }
124 break;
125 }
126 return 0;
127 }