Directx11教程(19) 画一个简单的地形 |
您所在的位置:网站首页 › directx11教程 › Directx11教程(19) 画一个简单的地形 |
原文:
Directx11教程(19) 画一个简单的地形
通常我们在xz平面定义一个二维的网格,然后y的值根据一定的函数计算得到,比如正弦、余弦函数的组合等等,可以得到一个看似不错的地形或者水面的效果。 在本教程中我们修改ModelClass.h和ModelClass.cpp,得到一个近似的地形。
在本章代码中,我们定义300*300=90000个顶点,共(300-1)(300-1)*2个三角形,每个网格的大小都为1. 我们得到y值的函数为: float ModelClass::getHeight(float x, float z) const { return 0.3f*( z*sinf(0.1f*x) + x*cosf(0.1f*z) ); }
ModelClass.h主要代码如下: #pragma once #include #include #include "common.h" class ModelClass { … int GetIndexCount(); //根据顶点的x值和z值,计算出y值 float getHeight(float x, float z)const; private: bool InitializeBuffers(ID3D11Device*, int, int, float); void ShutdownBuffers(); void RenderBuffers(ID3D11DeviceContext*); //顶点缓冲和顶点索引缓冲 ID3D11Buffer *m_vertexBuffer, *m_indexBuffer; int m_vertexCount, m_indexCount; }; ModelClass.cpp主要代码如下: bool ModelClass::Initialize(ID3D11Device* device, int m, int n, float dx) { bool result;// 初始化顶点缓冲和顶点索引缓冲. result = InitializeBuffers(device, m, n, dx); if(!result) { return false; } return true; } void ModelClass::Shutdown() { // 释放顶点和索引缓冲. ShutdownBuffers(); return; } float ModelClass::getHeight(float x, float z) const { return 0.3f*( z*sinf(0.1f*x) + x*cosf(0.1f*z) ); } void ModelClass::Render(ID3D11DeviceContext* deviceContext) { // 把顶点和索引缓冲放入图形管线,准备渲染. RenderBuffers(deviceContext); return; } int ModelClass::GetIndexCount() { //返回索引顶点计数 return m_indexCount; } bool ModelClass::InitializeBuffers(ID3D11Device* device, int m, int n, float dx) { VertexType* vertices; unsigned long* indices; D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc; D3D11_SUBRESOURCE_DATA vertexData, indexData; HRESULT result; //计算得到顶点和索引顶点数目 //首先得到三角形的数目,然后乘以3就是顶点索引数目 m_vertexCount = m*n; m_indexCount = (m-1)*(n-1)*2*3; // 创建顶点临时缓冲. vertices = new VertexType[m_vertexCount]; if(!vertices) { return false; } float halfWidth = (n-1)*dx*0.5f; float halfDepth = (m-1)*dx*0.5f; for(int i = 0; i < m; ++i) { float z = halfDepth - i*dx; for(int j = 0; j < n; ++j) { float x = -halfWidth + j*dx; // 计算得到z值. float y = getHeight(x,z); vertices[i*n+j].position = D3DXVECTOR3(x, y, z); // 根据高度来定义颜色 if( y < -10.0f ) vertices[i*n+j].color = BEACH_SAND; else if( y < 5.0f ) vertices[i*n+j].color = LIGHT_YELLOW_GREEN; else if( y < 12.0f ) vertices[i*n+j].color = DARK_YELLOW_GREEN; else if( y < 20.0f ) vertices[i*n+j].color = DARKBROWN; else vertices[i*n+j].color = WHITE; } } // 创建索引缓冲. indices = new unsigned long[m_indexCount]; if(!indices) { return false; } // 迭代每个grid,计算得出索引. int k = 0; for(int i = 0; i < m-1; ++i) { for(int j = 0; j < n-1; ++j) { indices[k] = i*n+j; indices[k+1] = i*n+j+1; indices[k+2] = (i+1)*n+j; indices[k+3] = (i+1)*n+j; indices[k+4] = i*n+j+1; indices[k+5] = (i+1)*n+j+1; k += 6; //下一个grid } } // 设置顶点缓冲描述 … return true; } 还要修改一下GraphicsClass.cpp中初始化ModelClass的代码:// 初始化模型对象. result = m_Model->Initialize(m_D3D->GetDevice(), 300, 300, 1.0f); if(!result) { MessageBox(hwnd, L"Could not initialize the model object.", L"Error", MB_OK); return false; } 运行程序后,效果如下,我们还可以用a/s/d/w键来移动摄像机看看地形的效果。 我们还可以修改D3DClass.cpp中,渲染状态Fillmode设置,修改为线框模式后的效果如下: D3DClass.cpp中修改代码如下: // 设置光栅化描述,指定多边形如何被渲染. rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_BACK; rasterDesc.DepthBias = 0; rasterDesc.DepthBiasClamp = 0.0f; rasterDesc.DepthClipEnable = true; rasterDesc.FillMode = D3D11_FILL_WIREFRAME; rasterDesc.FrontCounterClockwise = false; rasterDesc.MultisampleEnable = false; rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias = 0.0f;
完整的代码请参考: 工程文件myTutorialD3D11_13 代码下载: http://files.cnblogs.com/mikewolf2002/myTutorialD3D11.zip |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |