zoukankan      html  css  js  c++  java
  • Directx11学习笔记【二十二】 用高度图实现地形

    本文由zhangbaochong原创,转载请注明出处http://www.cnblogs.com/zhangbaochong/p/5827714.html

      在前面我们曾经实现过简单的地形(Directx11学习笔记【十三】 实现一个简单地形),只不过原来使用一个固定的函数获得地形高度,这样跟真实的地形差距比较大。接下来让我们学习使用高度图来进行三维地形模拟。

    1.高度图

      高度图其实就是一组连续的数组,这个数组中的元素与地形网格中的顶点一一对应,且每一个元素都指定了地形网格的某个顶点的高度值。高度图最常用的使用灰度图实现,灰度图中亮度越大对应的地形高度越高。下面就是一幅灰度图:

      

      灰度图格式通常为.raw,google一下高度图保存图片改为raw格式就可以了。高度图每个元素通常只分配一个字节,即数值在0~255之间。但在实际使用的时候经常要对高度进行比例变换,因此需要将byte转为float,然后通过一个缩放系数进行缩放,这样就不必拘泥于0~255这么一个范围了。

    2.读取高度图

      读取高度图很简单,用二进制读取文件就好了。

     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 }

      计算顶点和索引:

     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.cpp

      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 }
  • 相关阅读:
    JavaScript 为字符串添加样式 【每日一段代码80】
    JavaScript replace()方法 【每日一段代码83】
    JavaScript for in 遍历数组 【每日一段代码89】
    JavaScript 创建用于对象的模板【每日一段代码78】
    html5 css3 新元素简单页面布局
    JavaScript Array() 数组 【每日一段代码88】
    JavaScript toUTCString() 方法 【每日一段代码86】
    位运算
    POJ 3259 Wormholes
    POJ 3169 Layout
  • 原文地址:https://www.cnblogs.com/zhangbaochong/p/5827714.html
Copyright © 2011-2022 走看看