Directx11學習筆記【二十二】 用高度圖實現地形

本文由zhangbaochong原創,轉載請註明出處http://www.cnblogs.com/zhangbaochong/p/5827714.htmlhtml

  在前面咱們曾經實現過簡單的地形(Directx11學習筆記【十三】 實現一個簡單地形),只不過原來使用一個固定的函數得到地形高度,這樣跟真實的地形差距比較大。接下來讓咱們學習使用高度圖來進行三維地形模擬。ios

1.高度圖

  高度圖其實就是一組連續的數組,這個數組中的元素與地形網格中的頂點一一對應,且每個元素都指定了地形網格的某個頂點的高度值。高度圖最經常使用的使用灰度圖實現,灰度圖中亮度越大對應的地形高度越高。下面就是一幅灰度圖:算法

  

  灰度圖格式一般爲.raw,google一下高度圖保存圖片改成raw格式就能夠了。高度圖每一個元素一般只分配一個字節,即數值在0~255之間。但在實際使用的時候常常要對高度進行比例變換,所以須要將byte轉爲float,而後經過一個縮放係數進行縮放,這樣就沒必要拘泥於0~255這麼一個範圍了。數組

2.讀取高度圖

  讀取高度圖很簡單,用二進制讀取文件就行了。ide

 1 //讀取高度圖信息
 2 bool TerrainDemo::ReadRawFile(std::string filePath)
 3 {
 4     std::ifstream inFile;
 5     //二進制方式打開文件
 6     inFile.open(filePath.c_str(), std::ios::binary);
 7     //文件指針移動到末尾
 8     inFile.seekg(0, std::ios::end);
 9     //大小爲當前緩衝區大小
10     std::vector<BYTE> inData(inFile.tellg());
11     //文件指針移動到開頭
12     inFile.seekg(std::ios::beg);
13     //讀取高度信息
14     inFile.read((char*)&inData[0], inData.size());
15     inFile.close();
16 
17     m_heightInfos.resize(inData.size());
18     for (int i = 0; i < inData.size(); ++i)
19     {
20         m_heightInfos[i] = inData[i];
21     }
22 
23     return true;
24 }

3.頂點和索引的計算

  頂點和索引的計算同Directx11學習筆記【十三】 實現一個簡單地形相似,這裏就再也不詳細說明了。不同的因爲採用了紋理光照渲染,因此須要獲得法線,在計算索引的同時須要把頂點法線計算出來:函數

 1 //計算法線
 2 void TerrainDemo::ComputeNomal(Vertex& v1, Vertex& v2, Vertex& v3, XMFLOAT3& normal)
 3 {
 4     XMFLOAT3 f1(v2.pos.x - v1.pos.x, v2.pos.y - v1.pos.y, v2.pos.z - v1.pos.z);
 5     XMFLOAT3 f2(v3.pos.x - v1.pos.x, v3.pos.y - v1.pos.y, v3.pos.z - v1.pos.z);
 6     XMVECTOR vec1 = XMLoadFloat3(&f1);
 7     XMVECTOR vec2 = XMLoadFloat3(&f2);
 8     XMVECTOR temp = XMVector3Normalize(XMVector3Cross(vec1, vec2));
 9     XMStoreFloat3(&normal, temp);
10 }

  計算頂點和索引:post

 1 bool TerrainDemo::InitTerrain(float width, float height, UINT m, UINT n,float scale)
 2 {
 3     m_cellsPerRow = m;
 4     m_cellsPerCol = n;
 5     m_verticesPerRow = m + 1;
 6     m_verticesPerCol = n + 1;
 7     m_numsVertices = m_verticesPerRow*m_verticesPerCol;
 8     m_width = width;
 9     m_height = height;
10     m_heightScale = scale;
11 
12     //獲得縮放後的高度
13     for (auto& item : m_heightInfos)
14     {
15         item *= m_heightScale;
16     }
17 
18     //起始x z座標
19     float oX = -width * 0.5f;
20     float oZ = height * 0.5f;
21     //每一格座標變化
22     float dx = width / m;
23     float dz = height / n;
24 
25     m_vertices.resize(m_numsVertices);
26     //計算頂點
27     for (UINT i = 0; i < m_verticesPerCol; ++i)
28     {
29         float tempZ = oZ - dz * i;
30         for (UINT j = 0; j < m_verticesPerRow; ++j)
31         {
32             UINT index = m_verticesPerRow * i + j;
33             m_vertices[index].pos.x = oX + dx * j;
34             m_vertices[index].pos.y = m_heightInfos[index];
35             m_vertices[index].pos.z = tempZ;
36 
37             m_vertices[index].tex = XMFLOAT2(dx*i, dx*j);
38         }
39     }
40 
41     //計算索引和法線
42     //總格子數量:m * n
43     //所以總索引數量: 6 * m * n
44     UINT nIndices = m * n * 6;
45     m_indices.resize(nIndices);
46     UINT tmp = 0;
47     for (UINT i = 0; i < n; ++i)
48     {
49         for (UINT j = 0; j < m; ++j)
50         {
51             m_indices[tmp] = i * m_verticesPerRow + j;
52             m_indices[tmp + 1] = i * m_verticesPerRow + j + 1;
53             m_indices[tmp + 2] = (i + 1) * m_verticesPerRow + j;
54 
55             //計算法線
56             XMFLOAT3 temp;
57             ComputeNomal(m_vertices[m_indices[tmp]], m_vertices[m_indices[tmp + 1]], 
58                 m_vertices[m_indices[tmp + 2]], temp);
59             m_vertices[m_indices[tmp]].normal = temp;
60             m_vertices[m_indices[tmp + 1]].normal = temp;
61             m_vertices[m_indices[tmp + 2]].normal = temp;
62 
63             m_indices[tmp + 3] = i * m_verticesPerRow + j + 1;
64             m_indices[tmp + 4] = (i + 1) * m_verticesPerRow + j + 1;
65             m_indices[tmp + 5] = (i + 1) * m_verticesPerRow + j;
66 
67             ComputeNomal(m_vertices[m_indices[tmp + 3]], m_vertices[m_indices[tmp + 4]],
68                 m_vertices[m_indices[tmp + 5]], temp);
69             m_vertices[m_indices[tmp + 3]].normal = temp;
70             m_vertices[m_indices[tmp + 4]].normal = temp;
71             m_vertices[m_indices[tmp + 5]].normal = temp;
72 
73             tmp += 6;
74         }
75     }
76 
77     return true;
78 }

4.效果截圖

5.詳細源碼

TerrainDemo.h學習

 1 #pragma once
 2 #include <string>
 3 #include <vector>
 4 #include "Dx11Base.h"
 5 #include "Camera.h"
 6 #include "Input.h"
 7 #include "Utility.h"
 8 #include "LightHelper.h"
 9 
10 class TerrainDemo : public Dx11Base
11 {
12 public:
13     TerrainDemo(HINSTANCE hInst, std::wstring title = L"TerrainDemo", int width = 800, int height = 640);
14     ~TerrainDemo();
15 
16     //頂點結構 位置、法線、uv座標
17     struct Vertex
18     {
19         Vertex() {}
20         Vertex(const XMFLOAT3 _pos, XMFLOAT3 _normal,  XMFLOAT2 _tex) :
21             pos(_pos), normal(_normal),  tex(_tex) {}
22 
23         XMFLOAT3        pos;
24         XMFLOAT3        normal;
25         XMFLOAT2        tex;
26     };
27 
28     bool Init() override;
29     void Update(float dt);
30     void Render();
31 
32     bool OnResize() override;
33 private:
34     bool BuildBuffers();
35     bool BuildSRVs();
36     bool BuildInputLayouts();
37     void UpdateCamera(float dt);
38 private:
39     bool ReadRawFile(std::string filePath);                                        //從高度圖讀取高度信息
40     bool InitTerrain(float width, float height, UINT m, UINT n, float scale);    //初始化地形
41     void ComputeNomal(Vertex& v1, Vertex& v2, Vertex& v3, XMFLOAT3& normal);        //計算法線
42 private:
43     std::vector<float>    m_heightInfos;        //高度圖高度信息
44     int        m_cellsPerRow;                    //每行單元格數
45     int        m_cellsPerCol;                    //每列單元格數
46     int        m_verticesPerRow;                //每行頂點數
47     int        m_verticesPerCol;                //每列頂點數
48     int        m_numsVertices;                    //頂點總數
49     float    m_width;                        //地形寬度
50     float    m_height;                        //地形高度
51     float    m_heightScale;                    //高度縮放係數
52 
53     std::vector<Vertex>        m_vertices;        //頂點集合
54     std::vector<UINT>          m_indices;        //索引集合
55 
56 private:
57     ID3D11Buffer*                m_pVertexBuffer;
58     ID3D11Buffer*                m_pIndexBuffer;
59     ID3D11InputLayout*           m_pInputLayout;
60     ID3D11ShaderResourceView*    m_pSRVTerrain;
61 
62     Lights::DirectionalLight     m_dirLights[3];            //3個平行光源
63     Lights::Material             m_materialTerrain;        //材質
64 
65     Camera                        m_camera;
66 
67     XMFLOAT4X4                    m_world;                    //世界變換矩陣
68     XMFLOAT4X4                    m_worldViewProj;            //世界視角投影矩陣
69     XMFLOAT4X4                    m_worldInvTranspose;        //世界逆矩陣的轉置,用於法線變換
70     XMFLOAT4X4                    m_texTrans;                //紋理座標變換矩陣    
71 
72     POINT                m_lastMousePos;        
73 };

TerrainDemo.cppui

  1 #include <fstream>
  2 #include <memory>
  3 #include "TerrainDemo.h"
  4 #include "Utility.h"
  5 #include "WICTextureLoader.h"
  6 #include "d3dx11effect.h"
  7 #include "Effects.h"
  8 
  9 TerrainDemo::TerrainDemo(HINSTANCE hInst, std::wstring title, int width, int height)
 10     :Dx11Base(hInst, title, width, height)
 11 {
 12     //"三點式"照明
 13     //主光源
 14     m_dirLights[0].ambient = XMFLOAT4(0.3f, 0.3f, 0.3f, 1.0f);
 15     m_dirLights[0].diffuse = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
 16     m_dirLights[0].specular = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
 17     m_dirLights[0].direction = XMFLOAT3(0.57735f, -0.57735f, 0.57735f);
 18     //側光源
 19     m_dirLights[1].ambient = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
 20     m_dirLights[1].diffuse = XMFLOAT4(0.20f, 0.20f, 0.20f, 1.0f);
 21     m_dirLights[1].specular = XMFLOAT4(0.25f, 0.25f, 0.25f, 1.0f);
 22     m_dirLights[1].direction = XMFLOAT3(-0.57735f, -0.57735f, 0.57735f);
 23     //背光源
 24     m_dirLights[2].ambient = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
 25     m_dirLights[2].diffuse = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
 26     m_dirLights[2].specular = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
 27     m_dirLights[2].direction = XMFLOAT3(0.0f, -0.707f, -0.707f);
 28 
 29     //材質
 30     m_materialTerrain.ambient = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
 31     m_materialTerrain.diffuse = XMFLOAT4(1.f, 1.f, 1.f, 1.0f);
 32     m_materialTerrain.specular = XMFLOAT4(0.3f, 0.3f, 0.3f, 16.0f);
 33 
 34     //設置相機
 35     m_lastMousePos = { 0,0 };
 36     XMVECTOR Eye = XMVectorSet(0.0f, 50.0f, 0.1f, 0.0f);
 37     XMVECTOR At = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
 38     XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
 39     m_camera.LookAtXM(Eye, At, Up);
 40     //設置投影矩陣
 41     m_camera.SetLens(XM_PIDIV4, AspectRatio(), 0.1f, 1000.f);
 42 
 43     //初始化世界矩陣 逆轉置矩陣 及紋理座標矩陣
 44     //這些每一幀不改變
 45     XMMATRIX I = XMMatrixIdentity();
 46     XMStoreFloat4x4(&m_world, I);
 47     XMVECTOR det = XMMatrixDeterminant(I);
 48     XMMATRIX worldInvTranspose = XMMatrixTranspose(XMMatrixInverse(&det,I));
 49     XMStoreFloat4x4(&m_worldInvTranspose, worldInvTranspose);
 50     XMStoreFloat4x4(&m_texTrans, I);
 51 }
 52 
 53 TerrainDemo::~TerrainDemo()
 54 {
 55     SafeRelease(m_pVertexBuffer);
 56     SafeRelease(m_pIndexBuffer);
 57     SafeRelease(m_pInputLayout);
 58     SafeRelease(m_pSRVTerrain);
 59     Effects::ReleaseAll();
 60 }
 61 
 62 bool TerrainDemo::Init()
 63 {
 64     if (!Dx11Base::Init())
 65         return false;
 66     if (!Effects::InitAll(m_pd3dDevice))
 67         return false;
 68     if (!ReadRawFile("Texture\\heightmap.raw"))
 69     return false;
 70     if (!InitTerrain(500, 500, 255, 255, 0.2f))
 71         return false;
 72     if (!BuildBuffers())
 73         return false;
 74     if (!BuildSRVs())
 75         return false;
 76     if (!BuildInputLayouts())
 77         return false;
 78 }
 79 
 80 void TerrainDemo::Update(float dt)
 81 {
 82     UpdateCamera(dt);
 83     XMMATRIX world = XMLoadFloat4x4(&m_world);
 84     XMMATRIX worldViewProj = world * m_camera.GetViewProj();
 85     XMStoreFloat4x4(&m_worldViewProj, worldViewProj);
 86 
 87     //設置燈光
 88     Effects::ms_pBasicEffect->m_pFxDirLights->SetRawValue(&m_dirLights, 0,
 89         3 * sizeof(Lights::DirectionalLight));
 90     Effects::ms_pBasicEffect->m_pFxEyePos->SetRawValue(&m_camera.GetPosition(), 0, 
 91         sizeof(m_camera.GetPosition()));
 92 }
 93 
 94 void TerrainDemo::Render()
 95 {
 96     m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, Colors::Silver);
 97     m_pImmediateContext->ClearDepthStencilView(m_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
 98     m_pImmediateContext->IASetInputLayout(m_pInputLayout);
 99 
100     UINT stride = sizeof(Vertex);
101     UINT offset = 0;
102     m_pImmediateContext->IASetVertexBuffers(0, 1, &m_pVertexBuffer, &stride, &offset);
103     m_pImmediateContext->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R32_UINT, offset);
104     m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
105 
106     D3DX11_TECHNIQUE_DESC desc;
107     ID3DX11EffectTechnique* tech = Effects::ms_pBasicEffect->m_pFxLight3TexTech;
108     tech->GetDesc(&desc);
109 
110     for (UINT i = 0; i < desc.Passes; ++i)
111     {
112         //設置着色器變量
113         Effects::ms_pBasicEffect->m_pFxWorld->SetMatrix(reinterpret_cast<const float*>(&m_world));
114         Effects::ms_pBasicEffect->m_pFxWorldViewProj->SetMatrix(reinterpret_cast<const float*>(
115             &m_worldViewProj));
116         Effects::ms_pBasicEffect->m_pFxWorldInvTranspose->SetMatrix(reinterpret_cast<const float*>(
117             &m_worldInvTranspose));
118         Effects::ms_pBasicEffect->m_pFxTexTrans->SetMatrix(reinterpret_cast<const float*>(
119             &m_texTrans));
120         Effects::ms_pBasicEffect->m_pFxMaterial->SetRawValue(&m_materialTerrain, 0, sizeof(m_materialTerrain));
121         Effects::ms_pBasicEffect->m_pFxSR->SetResource(m_pSRVTerrain);
122         tech->GetPassByIndex(i)->Apply(0, m_pImmediateContext);
123         m_pImmediateContext->DrawIndexed(m_indices.size(), 0, 0);
124     }
125 
126     m_pSwapChain->Present(0, 0);
127 }
128 
129 bool TerrainDemo::OnResize()
130 {
131     if (!Dx11Base::OnResize())
132         return false;
133     //更新camera參數
134     m_camera.SetLens(XM_PIDIV4, AspectRatio(), 1.f, 1000.f);
135 
136     return true;
137 }
138 
139 bool TerrainDemo::BuildBuffers()
140 {
141     //建立頂點緩衝區
142     D3D11_BUFFER_DESC vertexDesc;
143     ZeroMemory(&vertexDesc, sizeof(vertexDesc));
144     vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
145     vertexDesc.ByteWidth = sizeof(Vertex) * m_numsVertices;
146     vertexDesc.Usage = D3D11_USAGE_IMMUTABLE;
147 
148     D3D11_SUBRESOURCE_DATA vertexData;
149     vertexData.pSysMem = &m_vertices[0];
150     vertexData.SysMemPitch = 0;
151     vertexData.SysMemSlicePitch = 0;
152     if (FAILED(m_pd3dDevice->CreateBuffer(&vertexDesc, &vertexData, &m_pVertexBuffer)))
153     {
154         MessageBox(nullptr, L"Create Vertex Buffer failed!", L"Error", MB_OK);
155         return false;
156     }
157 
158     //建立索引緩衝區
159     D3D11_BUFFER_DESC indexDesc;
160     ZeroMemory(&indexDesc, sizeof(indexDesc));
161     indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
162     indexDesc.ByteWidth = sizeof(UINT) * m_indices.size();
163     indexDesc.Usage = D3D11_USAGE_IMMUTABLE;
164 
165     D3D11_SUBRESOURCE_DATA indexData;
166     indexData.pSysMem = &m_indices[0];
167     indexData.SysMemPitch = 0;
168     indexData.SysMemSlicePitch = 0;
169     if (FAILED(m_pd3dDevice->CreateBuffer(&indexDesc, &indexData, &m_pIndexBuffer)))
170     {
171         MessageBox(nullptr, L"Create Index Buffer failed!", L"Error", MB_OK);
172         return false;
173     }
174 
175     return true;
176 }
177 
178 bool TerrainDemo::BuildSRVs()
179 {
180     if (FAILED(CreateWICTextureFromFile(m_pd3dDevice, L"Texture\\desert.bmp", nullptr, &m_pSRVTerrain)))
181     {
182         MessageBox(nullptr, L"create texture failed!", L"error", MB_OK);
183         return false;
184     }
185     return true;
186 }
187 
188 bool TerrainDemo::BuildInputLayouts()
189 {
190     D3D11_INPUT_ELEMENT_DESC layout[] = 
191     {
192         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
193         { "NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12,D3D11_INPUT_PER_VERTEX_DATA, 0 },
194         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,     0, 24,D3D11_INPUT_PER_VERTEX_DATA, 0 }
195     };
196 
197     UINT numLayoutElements = ARRAYSIZE(layout);
198     D3DX11_PASS_DESC passDesc;
199     Effects::ms_pBasicEffect->m_pFxLight3TexTech->GetPassByIndex(0)->GetDesc(&passDesc);
200     if (FAILED(m_pd3dDevice->CreateInputLayout(layout, numLayoutElements, passDesc.pIAInputSignature,
201         passDesc.IAInputSignatureSize, &m_pInputLayout)))
202     {
203         MessageBox(nullptr, L"create inputLayout failed!", L"error", MB_OK);
204         return false;
205     }
206     return true;
207 }
208 
209 void TerrainDemo::UpdateCamera(float dt)
210 {
211     //先後左右行走
212     if (Input::GetInstance()->IsKeyDown('A'))
213     {
214         m_camera.Strafe(-60.f*dt);
215     }
216     else if (Input::GetInstance()->IsKeyDown('D'))
217     {
218         m_camera.Strafe(60.f*dt);
219     }
220     if (Input::GetInstance()->IsKeyDown('W'))
221     {
222         m_camera.Walk(60.f*dt);
223     }
224     else if (Input::GetInstance()->IsKeyDown('S'))
225     {
226         m_camera.Walk(-60.f*dt);
227     }
228 
229 
230     if (Input::GetInstance()->IsMouseMove())
231     {
232         float mouseX = Input::GetInstance()->GetMouseX();
233         float mouseY = Input::GetInstance()->GetMouseY();
234         if (Input::GetInstance()->IsLMouseDown())
235         {
236             float dx = XMConvertToRadians(0.25f*(mouseX - m_lastMousePos.x));
237             float dy = XMConvertToRadians(0.25f*(mouseY - m_lastMousePos.y));
238 
239             OutputDebugString(L"left btn click");
240             m_camera.Pitch(dy);
241             m_camera.RotateY(dx);
242         }
243         m_lastMousePos.x = mouseX;
244         m_lastMousePos.y = mouseY;
245     }
246 
247     m_camera.UpdateViewMatrix();
248 }
249 
250 //讀取高度圖信息
251 bool TerrainDemo::ReadRawFile(std::string filePath)
252 {
253     std::ifstream inFile;
254     //二進制方式打開文件
255     inFile.open(filePath.c_str(), std::ios::binary);
256     //文件指針移動到末尾
257     inFile.seekg(0, std::ios::end);
258     //大小爲當前緩衝區大小
259     std::vector<BYTE> inData(inFile.tellg());
260     //文件指針移動到開頭
261     inFile.seekg(std::ios::beg);
262     //讀取高度信息
263     inFile.read((char*)&inData[0], inData.size());
264     inFile.close();
265 
266     m_heightInfos.resize(inData.size());
267     for (int i = 0; i < inData.size(); ++i)
268     {
269         m_heightInfos[i] = inData[i];
270     }
271 
272     return true;
273 }
274 
275 bool TerrainDemo::InitTerrain(float width, float height, UINT m, UINT n,float scale)
276 {
277     m_cellsPerRow = m;
278     m_cellsPerCol = n;
279     m_verticesPerRow = m + 1;
280     m_verticesPerCol = n + 1;
281     m_numsVertices = m_verticesPerRow*m_verticesPerCol;
282     m_width = width;
283     m_height = height;
284     m_heightScale = scale;
285 
286     //獲得縮放後的高度
287     for (auto& item : m_heightInfos)
288     {
289         item *= m_heightScale;
290     }
291 
292     //起始x z座標
293     float oX = -width * 0.5f;
294     float oZ = height * 0.5f;
295     //每一格座標變化
296     float dx = width / m;
297     float dz = height / n;
298 
299     m_vertices.resize(m_numsVertices);
300     //計算頂點
301     for (UINT i = 0; i < m_verticesPerCol; ++i)
302     {
303         float tempZ = oZ - dz * i;
304         for (UINT j = 0; j < m_verticesPerRow; ++j)
305         {
306             UINT index = m_verticesPerRow * i + j;
307             m_vertices[index].pos.x = oX + dx * j;
308             m_vertices[index].pos.y = m_heightInfos[index];
309             m_vertices[index].pos.z = tempZ;
310 
311             m_vertices[index].tex = XMFLOAT2(dx*i, dx*j);
312         }
313     }
314 
315     //計算索引和法線
316     //總格子數量:m * n
317     //所以總索引數量: 6 * m * n
318     UINT nIndices = m * n * 6;
319     m_indices.resize(nIndices);
320     UINT tmp = 0;
321     for (UINT i = 0; i < n; ++i)
322     {
323         for (UINT j = 0; j < m; ++j)
324         {
325             m_indices[tmp] = i * m_verticesPerRow + j;
326             m_indices[tmp + 1] = i * m_verticesPerRow + j + 1;
327             m_indices[tmp + 2] = (i + 1) * m_verticesPerRow + j;
328 
329             //計算法線
330             XMFLOAT3 temp;
331             ComputeNomal(m_vertices[m_indices[tmp]], m_vertices[m_indices[tmp + 1]], 
332                 m_vertices[m_indices[tmp + 2]], temp);
333             m_vertices[m_indices[tmp]].normal = temp;
334             m_vertices[m_indices[tmp + 1]].normal = temp;
335             m_vertices[m_indices[tmp + 2]].normal = temp;
336 
337             m_indices[tmp + 3] = i * m_verticesPerRow + j + 1;
338             m_indices[tmp + 4] = (i + 1) * m_verticesPerRow + j + 1;
339             m_indices[tmp + 5] = (i + 1) * m_verticesPerRow + j;
340 
341             ComputeNomal(m_vertices[m_indices[tmp + 3]], m_vertices[m_indices[tmp + 4]],
342                 m_vertices[m_indices[tmp + 5]], temp);
343             m_vertices[m_indices[tmp + 3]].normal = temp;
344             m_vertices[m_indices[tmp + 4]].normal = temp;
345             m_vertices[m_indices[tmp + 5]].normal = temp;
346 
347             tmp += 6;
348         }
349     }
350 
351     return true;
352 }
353 
354 //計算法線
355 void TerrainDemo::ComputeNomal(Vertex& v1, Vertex& v2, Vertex& v3, XMFLOAT3& normal)
356 {
357     XMFLOAT3 f1(v2.pos.x - v1.pos.x, v2.pos.y - v1.pos.y, v2.pos.z - v1.pos.z);
358     XMFLOAT3 f2(v3.pos.x - v1.pos.x, v3.pos.y - v1.pos.y, v3.pos.z - v1.pos.z);
359     XMVECTOR vec1 = XMLoadFloat3(&f1);
360     XMVECTOR vec2 = XMLoadFloat3(&f2);
361     XMVECTOR temp = XMVector3Normalize(XMVector3Cross(vec1, vec2));
362     XMStoreFloat3(&normal, temp);
363 }
364 
365 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow)
366 {
367     std::shared_ptr<Dx11Base> bd(new TerrainDemo(hInstance));
368     if (!bd->Init())
369         return -1;
370     return bd->Run();
371 }
相關文章
相關標籤/搜索