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 <d3d11.h>
#include <d3dx10math.h>
#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
Directx11教程(19) 画一个简单的地形的更多相关文章
- Directx11教程(6) 画一个简单的三角形(2)
原文:Directx11教程(6) 画一个简单的三角形(2) 在上篇教程中,我们实现了在D3D11中画一个简单的三角形,但是,当我们改变窗口大小时候,三角形形状却随着窗口高宽比例改变而改变, ...
- Directx11教程(5) 画一个简单的三角形(1)
原文:Directx11教程(5) 画一个简单的三角形(1) 在本篇教程中,我们将通过D3D11画一个简单的三角形.在D3D11中,GPU的渲染主要通过shader来操作(当然还有一些操作 ...
- Directx11教程(7) 画一个颜色立方体
原文:Directx11教程(7) 画一个颜色立方体 前面教程我们通过D3D11画了一个三角形,本章我们将画一个颜色立方体,它的立体感更强.主要的变动是ModelClass类,在Model ...
- Directx11教程(10) 画一个简易坐标轴
原文:Directx11教程(10) 画一个简易坐标轴 本篇教程中,我们将在三维场景中,画一个简易的坐标轴,分别用红.绿.蓝三种颜色表示x,y,z轴的正向坐标轴. 为此,我们要先建立一个A ...
- Directx11学习笔记【十一】 画一个简单的三角形--effect框架的使用
这里不再介绍effect框架的具体使用,有关effect框架使用可参考http://www.cnblogs.com/zhangbaochong/p/5475961.html 实现的功能依然是画一个简单 ...
- Directx11教程(56) 建立一个skydome
原文:Directx11教程(56) 建立一个skydome 本章建立一个skydome(天空穹),主要学习如何使用cube mapping. cube map就是把六张纹理当作 ...
- Directx11教程(42) 纹理映射(12)-简单的bump mapping
原文:Directx11教程(42) 纹理映射(12)-简单的bump mapping 有时候,我们只有一个粗糙的模型,但是我们想渲染纹理细节,比如一个砖墙,我们如何在只有一个平面的时候 ...
- Directx11教程(11) 增加一个debug宏
原文:Directx11教程(11) 增加一个debug宏 现在我们在common.h中增加一个debug的宏,在每个d3d11函数后调用,如果d3d函数出错,它能够给出程序中错误的代码行 ...
- Directx11教程(9) 增加一个TimerClass类
原文:Directx11教程(9) 增加一个TimerClass类 在上篇教程代码的基础上,我们增加一个TimerClass类,这个类的功能很简单,就是可以计算相邻2帧的时间差.利用这个时间 ...
随机推荐
- anime.js 学习笔记
官网演示/文档 anime.js 是一个简便的JS动画库,用法简单而且适用范围广,涵盖CSS,DOM,SVG还有JS的对象,各种带数值属性的东西都可以动起来. 实际演示和代码,官网写得很详细清楚了,这 ...
- Python之通配符--提取文件中的内容并输出
前言:我的学习进度其实没有那么快的,因为现在是网络工程师实习,只有晚上一点时间和周末有空,所以周一到周天的学习进度很慢,今天之所以突然跳到通配符是因为工作需要,大体讲一下我的工作需求:网络工程师就是写 ...
- xshell下载免费版
正在使用的xshell 5不能使用,提示xshell 5评估期已过,重新安装还是不行.其实xshell 5有免费版的,即Home & school 版本.卸载原程序,下载安装免费版本的xshe ...
- mybatis学习:mybatis的环境搭建与入门
一.mybatis的概述: mybatis是一个持久层框架,用java编写 它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动,创建连接登繁杂过程 它使用了ORM思想 ...
- fft模板 HDU 1402
// fft模板 HDU 1402 #include <iostream> #include <cstdio> #include <cstdlib> #includ ...
- 【vuex】vue2-happyfri
我发现我对使用vuex并不擅长,现在跟我一起多多研究项目,好好补补vuex吧 这个开源项目地址为:https://github.com/bailicangdu/vue2-happyfri 这是一个答题 ...
- 【html、CSS、javascript-5】css应用场景补充
一.CSS全局应用 父标签div下包含两个子标签div,当子标签dvi全部向左float,此时父标签设置的背景色是不显示的 <!DOCTYPE html> <html lang=&q ...
- LUOGU P2441 角色属性树
题目描述 绪萌同人社是一个有趣的组织,该组织结构是一个树形结构.有一个社长,直接下属一些副社长.每个副社长又直接下属一些部长--. 每个成员都有一个萌点的属性,萌点属性是由一些质数的萌元素乘积构成(例 ...
- css3动画曲线运动
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- thinkphp用swiftmailer发邮件demo
QQ邮箱 include_once APPPATH . 'libraries/swiftmailer/swift_required.php'; $transport = Swift_SmtpTrans ...