由于之前一直在看directx11龙书学习,因此sdk一直用的Microsoft DirectX SDK (June 2010) 版本,最近在stackoverflow上问dx11相关问题时,一直被大神吐槽为何还用已经废弃的directx sdk,由于directx sdk现在已经和windows sdk合并到一起了,只能去下windows sdk了。为了方便索性直接换了vs 2015社区版,里面自带了(windows sdk),既然sdk换了最新的,effect框架也要换最新的啊(Effect框架已经被微软开源托管在github上,https://github.com/Microsoft/FX11/wiki)。还有stackoverflow上都推荐DirectXTK,这方面中文资料非常少,只能靠自己慢慢看文档示例学了,等看得差不多了,会考虑用DirectXTK写的。以后教程还是基本跟着龙书走,我会将龙书实现的效果用自己封装的框架写一遍,尤其是一些过时的函数方法我也会换上对应的新方法。
由于directx sdk集成在windows sdk中了,所以在建项目的时候就不用设置引用目录和库目录的路径了,只需设置链接库就可以了,还是挺方便的。由于换了sdk,一些方法参数之类的都略有不同,我又把之前的基类Dx11DemoBase重新封装了一遍,为了练习把前一个教程HillsDemo又重新写了一遍,体会一下有哪些改动。不同之处都在代码中给出了注释。
前面教程编译shader用的是两个方法D3DX11CompileFromFile和
D3DX11CreateEffectFromMemory,显得比较麻烦,在最新的FX11(Effect框架)中这两个方法已经废弃了,我们可以采用D3DX11CompileEffectFromFile来编译shader,一步到位尤为方便
1 //compile shader 2 ID3DBlob* errorBlob; 3 DWORD shaderFlags = D3DCOMPILE_ENABLE_STRICTNESS; 4 5 #if defined _DEBUG || defined DEBUG 6 shaderFlags = D3DCOMPILE_DEBUG; 7 #endif 8 9 hr = D3DX11CompileEffectFromFile(L"color.fx", nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE, shaderFlags, 10 0, m_pd3dDevice, &m_pFx, &errorBlob); 11 if (FAILED(hr)) 12 { 13 MessageBox(nullptr, (LPCWSTR)errorBlob->GetBufferPointer(), L"error", MB_OK); 14 return hr; 15 } 16 17 m_pTechnique = m_pFx->GetTechniqueByName("ColorTech"); 18 m_pFxWorldViewProj = m_pFx->GetVariableByName("gWorldViewProj")->AsMatrix();
下面给出改动后的HillsDemo代码(其实大体差不多),在看新的官方实例时发现代码都是c++11风格(使用nullptr代替NULL,使用c++风格类型转换static_cast/reinterpret_cast,DirectXTK中大量使用智能指针等),因此咱也尽量保持相同的风格以养成写规范代码的好习惯。此外注释我也尽量用英文写,一方面有些用汉语不太好说明,另一方面由于要经常在stackoverflow上提问老外看不懂汉语还得临时改英文挺麻烦的。
Base基类这次我们添加了depth/stencil缓冲,以便以后用到的时候不用再临时添加了。
1 //create depth stencil texture 2 D3D11_TEXTURE2D_DESC descDepth; 3 descDepth.Width = m_width; 4 descDepth.Height = m_height; 5 descDepth.ArraySize = 1; 6 descDepth.MipLevels = 1; 7 descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; 8 descDepth.SampleDesc.Count = 1; 9 descDepth.SampleDesc.Quality = 0; 10 descDepth.Usage = D3D11_USAGE_DEFAULT; 11 descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; 12 descDepth.CPUAccessFlags = 0; 13 descDepth.MiscFlags = 0; 14 hr = m_pd3dDevice->CreateTexture2D(&descDepth, nullptr, &m_pDepthStencilBuffer); 15 if (FAILED(hr)) 16 return hr; 17 18 //create the depth stencil view 19 D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; 20 ZeroMemory(&descDSV, sizeof(descDSV)); 21 descDSV.Format = descDepth.Format; 22 descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; 23 descDSV.Texture2D.MipSlice = 0; 24 hr = m_pd3dDevice->CreateDepthStencilView(m_pDepthStencilBuffer, &descDSV, &m_pDepthStencilView); 25 if (FAILED(hr)) 26 return hr;
在实际Demo中每帧要clear一下
1 //clear depth/stencil view 2 m_pImmediateContext->ClearDepthStencilView(m_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 3 1.0f, 0);
Dx11DemoBase.h
1 #ifndef _DX11DEMOBASE_H_ 2 #define _DX11DEMOBASE_H_ 3 4 #include <string> 5 #include6 #include 7 #include 8 #include //don't use xnamath.h 9 #include 10 11 using namespace DirectX; 12 13 class Dx11DemoBase 14 { 15 public: 16 Dx11DemoBase(); 17 virtual ~Dx11DemoBase(); 18 19 std::wstring m_mainWndCaption; //title 20 float AspectRatio() const; //width/height 21 22 bool InitDirect3D(HINSTANCE hInstance, HWND hWnd); 23 24 void ShutDown(); //release 25 26 virtual bool LoadContent(); //init concrete content 27 virtual void UnLoadContent(); //release 28 29 virtual void Update(float dt) = 0; 30 virtual void Render() = 0; 31 32 virtual void OnMouseDown(WPARAM btnState, int x, int y) {} 33 virtual void OnMouseUp(WPARAM btnState, int x, int y) {} 34 virtual void OnMouseMove(WPARAM btnState, int x, int y) {} 35 36 protected: 37 UINT m_width; //window width 38 UINT m_height; //window height 39 HINSTANCE m_hInstance; 40 HWND m_hWnd; 41 D3D_DRIVER_TYPE m_driverType; 42 D3D_FEATURE_LEVEL m_featureLevel; 43 ID3D11Device* m_pd3dDevice; 44 ID3D11DeviceContext* m_pImmediateContext; 45 IDXGISwapChain* m_pSwapChain; 46 ID3D11RenderTargetView* m_pRenderTargetView; 47 ID3D11Texture2D* m_pDepthStencilBuffer; 48 ID3D11DepthStencilView* m_pDepthStencilView; 49 }; 50 51 #endif//_DX11DEMOBASE_H_
Dx11DemoBase.cpp
1 #include "Dx11DemoBase.h" 2 3 Dx11DemoBase::Dx11DemoBase(): 4 m_mainWndCaption(L"Directx11 Application"), 5 m_driverType(D3D_DRIVER_TYPE_HARDWARE), 6 m_featureLevel(D3D_FEATURE_LEVEL_11_0), 7 m_pd3dDevice(nullptr), 8 m_pImmediateContext(nullptr), 9 m_pRenderTargetView(nullptr), 10 m_pDepthStencilBuffer(nullptr), 11 m_pDepthStencilView(nullptr), 12 m_pSwapChain(nullptr), 13 m_hWnd(nullptr), 14 m_width(800), 15 m_height(600) 16 {} 17 18 Dx11DemoBase::~Dx11DemoBase() 19 { 20 ShutDown(); 21 } 22 23 float Dx11DemoBase::AspectRatio() const 24 { 25 return static_cast<float>(m_width / m_height); 26 } 27 28 bool Dx11DemoBase::InitDirect3D(HINSTANCE hInstance, HWND hWnd) 29 { 30 HRESULT hr = S_OK; 31 m_hInstance = hInstance; 32 m_hWnd = hWnd; 33 RECT rc; 34 GetClientRect(m_hWnd, &rc); 35 m_width = rc.right - rc.left; 36 m_height = rc.bottom - rc.top; 37 38 UINT createDeviceFlags = 0; 39 40 #ifdef _DEBUG 41 createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; 42 #endif 43 44 D3D_DRIVER_TYPE driverTypes[] = 45 { 46 D3D_DRIVER_TYPE_HARDWARE, 47 D3D_DRIVER_TYPE_WARP, 48 D3D_DRIVER_TYPE_REFERENCE 49 }; 50 UINT numDriverTypes = ARRAYSIZE(driverTypes); 51 52 D3D_FEATURE_LEVEL featureLevels[] = 53 { 54 D3D_FEATURE_LEVEL_11_0, 55 D3D_FEATURE_LEVEL_10_1, 56 D3D_FEATURE_LEVEL_10_0 57 }; 58 UINT numFeatureLevels = ARRAYSIZE(featureLevels); 59 60 DXGI_SWAP_CHAIN_DESC sd; 61 ZeroMemory(&sd, sizeof(sd)); 62 sd.BufferCount = 1; 63 sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 64 sd.BufferDesc.Width = m_width; 65 sd.BufferDesc.Height = m_height; 66 sd.BufferDesc.RefreshRate.Numerator = 60; 67 sd.BufferDesc.RefreshRate.Denominator = 1; 68 sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 69 sd.OutputWindow = m_hWnd; 70 sd.SampleDesc.Count = 1; 71 sd.SampleDesc.Quality = 0; 72 sd.Windowed = TRUE; 73 74 //create device and swapchain 75 for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; ++driverTypeIndex) 76 { 77 hr = D3D11CreateDeviceAndSwapChain(nullptr, driverTypes[driverTypeIndex], nullptr, 78 createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &sd, &m_pSwapChain, 79 &m_pd3dDevice, &m_featureLevel, &m_pImmediateContext); 80 if (SUCCEEDED(hr)) 81 { 82 m_driverType = driverTypes[driverTypeIndex]; 83 break; 84 } 85 } 86 if (FAILED(hr)) 87 return hr; 88 89 //create render target view 90 ID3D11Texture2D *pBackBuffer = nullptr; 91 hr = m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer)); 92 if (FAILED(hr)) 93 return hr; 94 95 hr = m_pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &m_pRenderTargetView); 96 pBackBuffer->Release(); 97 if (FAILED(hr)) 98 return hr; 99 100 m_pImmediateContext->OMSetRenderTargets(1, &m_pRenderTargetView, nullptr); 101 102 //create depth stencil texture 103 D3D11_TEXTURE2D_DESC descDepth; 104 descDepth.Width = m_width; 105 descDepth.Height = m_height; 106 descDepth.ArraySize = 1; 107 descDepth.MipLevels = 1; 108 descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; 109 descDepth.SampleDesc.Count = 1; 110 descDepth.SampleDesc.Quality = 0; 111 descDepth.Usage = D3D11_USAGE_DEFAULT; 112 descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; 113 descDepth.CPUAccessFlags = 0; 114 descDepth.MiscFlags = 0; 115 hr = m_pd3dDevice->CreateTexture2D(&descDepth, nullptr, &m_pDepthStencilBuffer); 116 if (FAILED(hr)) 117 return hr; 118 119 //create the depth stencil view 120 D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; 121 ZeroMemory(&descDSV, sizeof(descDSV)); 122 descDSV.Format = descDepth.Format; 123 descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; 124 descDSV.Texture2D.MipSlice = 0; 125 hr = m_pd3dDevice->CreateDepthStencilView(m_pDepthStencilBuffer, &descDSV, &m_pDepthStencilView); 126 if (FAILED(hr)) 127 return hr; 128 129 m_pImmediateContext->OMSetRenderTargets(1, &m_pRenderTargetView, m_pDepthStencilView); 130 131 //setup the viewport 132 D3D11_VIEWPORT vp; 133 vp.Width = static_cast<float>(m_width); 134 vp.Height = static_cast<float>(m_height); 135 vp.MinDepth = 0.0f; 136 vp.MaxDepth = 1.0f; 137 vp.TopLeftX = 0.0f; 138 vp.TopLeftY = 0.0f; 139 m_pImmediateContext->RSSetViewports(1, &vp); 140 141 return LoadContent(); 142 } 143 144 145 void Dx11DemoBase::ShutDown() 146 { 147 UnLoadContent(); 148 if (m_pImmediateContext) m_pImmediateContext->ClearState(); 149 150 if (m_pRenderTargetView) m_pRenderTargetView->Release(); 151 if (m_pSwapChain) m_pSwapChain->Release(); 152 if (m_pImmediateContext) m_pImmediateContext->Release(); 153 if (m_pd3dDevice) m_pd3dDevice->Release(); 154 if (m_pDepthStencilBuffer) m_pDepthStencilBuffer->Release(); 155 if (m_pDepthStencilView) m_pDepthStencilView->Release(); 156 } 157 158 bool Dx11DemoBase::LoadContent() 159 { 160 return true; 161 } 162 163 void Dx11DemoBase::UnLoadContent(){}
GeometryGenerator类中代码没什么改变不再给出
HillsDemo.h
1 #ifndef _HILLSDEMO_H_ 2 #define _HILLSDEMO_H_ 3 4 #include "Dx11DemoBase.h" 5 #include "d3dx11effect.h" 6 #include "GeometryGenerator.h" 7 8 9 #pragma comment(lib,"d3d11.lib") 10 #pragma comment(lib,"Effects11.lib") 11 #pragma comment(lib,"d3dcompiler.lib") 12 #pragma comment(lib,"winmm.lib") 13 #pragma comment(lib,"comctl32.lib") 14 #pragma comment(lib,"dxguid.lib") 15 16 class HillsDemo : public Dx11DemoBase 17 { 18 public: 19 HillsDemo(); 20 ~HillsDemo(); 21 22 bool LoadContent() override; 23 void UnLoadContent() override; 24 25 void Update(float dt) override; 26 void Render() override; 27 28 void OnMouseDown(WPARAM btnState, int x, int y) override; 29 void OnMouseUp(WPARAM btnState, int x, int y) override; 30 void OnMouseMove(WPARAM btnState, int x, int y) override; 31 private: 32 ID3D11Buffer* m_pVertexBuffer; 33 ID3D11Buffer* m_pIndexBuffer; 34 ID3D11InputLayout* m_pInputLayout; 35 36 ID3DX11Effect* m_pFx; 37 ID3DX11EffectTechnique* m_pTechnique; 38 ID3DX11EffectMatrixVariable* m_pFxWorldViewProj; 39 XMFLOAT4X4 m_world; 40 XMFLOAT4X4 m_view; 41 XMFLOAT4X4 m_proj; 42 43 44 UINT m_gridIndexCount; 45 float m_theta; 46 float m_phi; 47 float m_radius; 48 POINT m_lastMousePos; 49 50 float GetHeight(float x, float z)const; 51 52 }; 53 54 #endif//_HILLSDEMO_H_
HillsDemo.cpp
1 #include "HillsDemo.h" 2 3 struct Vertex 4 { 5 XMFLOAT3 pos; 6 XMFLOAT4 color; 7 Vertex(XMFLOAT3 p, XMFLOAT4 c) : pos(p), color(c) {} 8 }; 9 10 HillsDemo::HillsDemo() :m_pInputLayout(nullptr), m_pVertexBuffer(nullptr),m_pFx(nullptr), m_gridIndexCount(0), 11 m_theta(1.5f*XM_PI), m_phi(0.1f*XM_PI), m_radius(200.0f) 12 { 13 XMMATRIX I = XMMatrixIdentity(); 14 XMStoreFloat4x4(&m_world, I); 15 XMStoreFloat4x4(&m_view, I); 16 XMStoreFloat4x4(&m_proj, I); 17 } 18 19 HillsDemo::~HillsDemo() 20 { 21 22 } 23 24 bool HillsDemo::LoadContent() 25 { 26 HRESULT hr; 27 28 //create vertex buffer 29 GeometryGenerator::MeshData grid; 30 GeometryGenerator geoGen; 31 geoGen.CreateGrid(160.0f, 160.0f, 50, 50, grid); 32 m_gridIndexCount = grid.indices.size(); 33 34 std::vectorvertices(grid.vertices.size(), Vertex(XMFLOAT3(0, 0, 0), XMFLOAT4(0, 0, 0, 0))); 35 for (UINT i = 0; i < grid.vertices.size(); ++i) 36 { 37 XMFLOAT3 p = grid.vertices[i].Position; 38 p.y = GetHeight(p.x, p.z); 39 40 vertices[i].pos = p; 41 42 //render vertex with different color according to height 43 if (p.y < -10.0f) 44 { 45 //sandy beach color 46 vertices[i].color = XMFLOAT4(1.0f, 0.96f, 0.62f, 1.0f); 47 } 48 else if (p.y < 5.0f) 49 { 50 //dark yellow-green color 51 vertices[i].color = XMFLOAT4(0.1f, 0.48f, 0.19f, 1.0f); 52 } 53 else if (p.y < 12.0f) 54 { 55 //light yellow-green color 56 vertices[i].color = XMFLOAT4(0.48f, 0.77f, 0.46f, 1.0f); 57 } 58 else if (p.y < 20.f) 59 { 60 //dark brown color 61 vertices[i].color = XMFLOAT4(0.45f, 0.39f, 0.34f, 1.0f); 62 } 63 else 64 { 65 //white snow color 66 vertices[i].color = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f); 67 } 68 } 69 70 D3D11_BUFFER_DESC vertexDesc; 71 ZeroMemory(&vertexDesc, sizeof(vertexDesc)); 72 vertexDesc.Usage = D3D11_USAGE_IMMUTABLE; 73 vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 74 vertexDesc.ByteWidth = sizeof(Vertex)* grid.vertices.size(); 75 D3D11_SUBRESOURCE_DATA resourceData; 76 ZeroMemory(&resourceData, sizeof(resourceData)); 77 resourceData.pSysMem = &vertices[0]; 78 hr = m_pd3dDevice->CreateBuffer(&vertexDesc, &resourceData, &m_pVertexBuffer); 79 if (FAILED(hr)) 80 { 81 return false; 82 } 83 84 //set vertex buffer 85 UINT stride = sizeof(Vertex); 86 UINT offset = 0; 87 m_pImmediateContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset); 88 //set primitive topology 89 m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 90 91 //create index buffer 92 D3D11_BUFFER_DESC indexDesc; 93 ZeroMemory(&indexDesc, sizeof(indexDesc)); 94 indexDesc.Usage = D3D11_USAGE_IMMUTABLE; 95 indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; 96 indexDesc.ByteWidth = sizeof(UINT)* m_gridIndexCount; 97 98 D3D11_SUBRESOURCE_DATA indexData; 99 ZeroMemory(&indexData, sizeof(indexData)); 100 indexData.pSysMem = &grid.indices[0]; 101 hr = m_pd3dDevice->CreateBuffer(&indexDesc, &indexData, &m_pIndexBuffer); 102 if (FAILED(hr)) 103 { 104 return false; 105 } 106 107 //set index buffer 108 m_pImmediateContext->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R32_UINT, 0); 109 110 //compile shader 111 ID3DBlob* errorBlob; 112 DWORD shaderFlags = D3DCOMPILE_ENABLE_STRICTNESS; 113 114 #if defined _DEBUG || defined DEBUG 115 shaderFlags = D3DCOMPILE_DEBUG; 116 #endif 117 118 hr = D3DX11CompileEffectFromFile(L"color.fx", nullptr, D3D_COMPILE_STANDARD_FILE_INCLUDE, shaderFlags, 119 0, m_pd3dDevice, &m_pFx, &errorBlob); 120 if (FAILED(hr)) 121 { 122 MessageBox(nullptr, (LPCWSTR)errorBlob->GetBufferPointer(), L"error", MB_OK); 123 return hr; 124 } 125 126 m_pTechnique = m_pFx->GetTechniqueByName("ColorTech"); 127 m_pFxWorldViewProj = m_pFx->GetVariableByName("gWorldViewProj")->AsMatrix(); 128 129 130 //define the input layout 131 D3D11_INPUT_ELEMENT_DESC colorLayout[] = 132 { 133 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, 134 { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 } 135 }; 136 137 UINT numLayoutElements = ARRAYSIZE(colorLayout); 138 D3DX11_PASS_DESC passDesc; 139 m_pTechnique->GetPassByIndex(0)->GetDesc(&passDesc); 140 141 //create the input layout 142 hr = m_pd3dDevice->CreateInputLayout(colorLayout, numLayoutElements, passDesc.pIAInputSignature, 143 passDesc.IAInputSignatureSize, &m_pInputLayout); 144 if (FAILED(hr)) 145 return hr; 146 147 //set input layout 148 m_pImmediateContext->IASetInputLayout(m_pInputLayout); 149 150 return true; 151 } 152 153 void HillsDemo::UnLoadContent() 154 { 155 if (m_pVertexBuffer) m_pVertexBuffer->Release(); 156 if (m_pIndexBuffer) m_pIndexBuffer->Release(); 157 if (m_pInputLayout) m_pInputLayout->Release(); 158 if (m_pTechnique) m_pTechnique->Release(); 159 } 160 161 void HillsDemo::Update(float dt) 162 { 163 float x = m_radius*sinf(m_phi)*cosf(m_theta); 164 float z = m_radius*sinf(m_phi)*sinf(m_theta); 165 float y = m_radius*cosf(m_phi); 166 167 XMVECTOR pos = XMVectorSet(x, y, z, 1.0f); 168 XMVECTOR target = XMVectorSet(0.0f, 0.0f, 0.0f, 1.0f); 169 XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); 170 171 XMMATRIX V = XMMatrixLookAtLH(pos, target, up); 172 XMStoreFloat4x4(&m_view, V); 173 XMMATRIX T = XMMatrixPerspectiveFovLH(XM_PIDIV4, m_width / static_cast<float>(m_height), 174 1.0f, 1000.0f); 175 XMStoreFloat4x4(&m_proj, T); 176 } 177 178 void HillsDemo::Render() 179 { 180 if (m_pImmediateContext == 0) 181 return; 182 //clear render target view 183 float clearColor[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; 184 m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, clearColor); 185 186 //clear depth/stencil view 187 m_pImmediateContext->ClearDepthStencilView(m_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 188 1.0f, 0); 189 190 //set constant buffer 191 XMMATRIX world = XMLoadFloat4x4(&m_world); 192 XMMATRIX view = XMLoadFloat4x4(&m_view); 193 XMMATRIX proj = XMLoadFloat4x4(&m_proj); 194 XMMATRIX worldViewProj = world*view*proj; 195 196 197 D3DX11_TECHNIQUE_DESC techDesc; 198 m_pTechnique->GetDesc(&techDesc); 199 for (UINT i = 0; i < techDesc.Passes; ++i) 200 { 201 m_pFxWorldViewProj->SetMatrix(reinterpret_cast<float*>(&worldViewProj)); 202 m_pTechnique->GetPassByIndex(i)->Apply(0, m_pImmediateContext); 203 m_pImmediateContext->DrawIndexed(m_gridIndexCount, 0, 0); 204 } 205 206 m_pSwapChain->Present(0, 0); 207 } 208 209 void HillsDemo::OnMouseDown(WPARAM btnState, int x, int y) 210 { 211 m_lastMousePos.x = x; 212 m_lastMousePos.y = y; 213 SetCapture(m_hWnd); 214 } 215 216 void HillsDemo::OnMouseUp(WPARAM btnState, int x, int y) 217 { 218 ReleaseCapture(); 219 } 220 221 //restrict the number 222 template 223 static T Clamp(const T& x, const T& low, const T& high) 224 { 225 return x < low ? low : (x > high ? high : x); 226 } 227 228 void HillsDemo::OnMouseMove(WPARAM btnState, int x, int y) 229 { 230 if ((btnState & MK_LBUTTON) != 0) 231 { 232 // make each pixel correspond to a quarter of a degree. 233 float dx = XMConvertToRadians(0.25f*static_cast<float>(x - m_lastMousePos.x)); 234 float dy = XMConvertToRadians(0.25f*static_cast<float>(y - m_lastMousePos.y)); 235 236 // update angles based on input to orbit camera around box. 237 m_theta += dx; 238 m_phi += dy; 239 240 // restrict the angle mPhi. 241 m_phi = Clamp(m_phi, 0.1f, XM_PI - 0.1f); 242 } 243 else if ((btnState & MK_RBUTTON) != 0) 244 { 245 // make each pixel correspond to 0.2 unit in the scene. 246 float dx = 0.2f*static_cast<float>(x - m_lastMousePos.x); 247 float dy = 0.2f*static_cast<float>(y - m_lastMousePos.y); 248 249 // update the camera radius based on input. 250 m_radius += dx - dy; 251 252 // restrict the radius. 253 m_radius = Clamp(m_radius, 50.0f, 500.0f); 254 } 255 256 m_lastMousePos.x = x; 257 m_lastMousePos.y = y; 258 } 259 260 float HillsDemo::GetHeight(float x, float z) const 261 { 262 return 0.3f*(z*sinf(0.1f*x) + x*cosf(0.1f*z)); 263 }
main.cpp
1 #include2 #include 3 #include 4 #include "HillsDemo.h" 5 using namespace std; 6 7 std::shared_ptr demo = make_shared (); 8 9 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 10 11 int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) 12 { 13 UNREFERENCED_PARAMETER(hPrevInstance); 14 UNREFERENCED_PARAMETER(lpCmdLine); 15 16 WNDCLASSEX wcex; 17 wcex.cbClsExtra = 0; 18 wcex.cbSize = sizeof(wcex); 19 wcex.cbWndExtra = 0; 20 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 21 wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); 22 wcex.hIcon = LoadIcon(nullptr, IDI_WINLOGO); 23 wcex.hIconSm = wcex.hIcon; 24 wcex.hInstance = hInstance; 25 wcex.lpfnWndProc = WndProc; 26 wcex.lpszClassName = L"HillsDemo"; 27 wcex.lpszMenuName = nullptr; 28 wcex.style = CS_HREDRAW | CS_VREDRAW; 29 30 if (!RegisterClassEx(&wcex)) 31 return 0; 32 33 34 RECT rc = { 0, 0, 800, 600 }; 35 AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false); 36 37 HWND hwnd = CreateWindowEx(WS_EX_APPWINDOW, L"HillsDemo", L"HillsDemo", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 38 CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, hInstance, nullptr); 39 40 if (!hwnd) 41 return 0; 42 43 ShowWindow(hwnd, nShowCmd); 44 45 46 bool result = demo->InitDirect3D(hInstance, hwnd); 47 if (!result) 48 return 0; 49 50 MSG msg; 51 ZeroMemory(&msg, sizeof(msg)); 52 while (msg.message != WM_QUIT) 53 { 54 if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) 55 { 56 TranslateMessage(&msg); 57 DispatchMessage(&msg); 58 } 59 demo->Update(0.0f); 60 demo->Render(); 61 } 62 demo->ShutDown(); 63 return static_cast<int>(msg.wParam); 64 } 65 66 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 67 { 68 PAINTSTRUCT paintStruct; 69 HDC hdc; 70 switch (message) 71 { 72 case WM_PAINT: 73 hdc = BeginPaint(hWnd, &paintStruct); 74 EndPaint(hWnd, &paintStruct); 75 break; 76 case WM_DESTROY: 77 PostQuitMessage(0); 78 break; 79 case WM_LBUTTONDOWN: 80 case WM_MBUTTONDOWN: 81 case WM_RBUTTONDOWN: 82 demo->OnMouseDown(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); 83 return 0; 84 case WM_LBUTTONUP: 85 case WM_MBUTTONUP: 86 case WM_RBUTTONUP: 87 demo->OnMouseUp(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); 88 return 0; 89 case WM_MOUSEMOVE: 90 demo->OnMouseMove(wParam, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); 91 return 0; 92 default: 93 return DefWindowProc(hWnd, message, wParam, lParam); 94 } 95 return 0; 96 }
好了代码就这些了,最后让我们看张图缓解下疲劳吧