原文: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) 画一个简单的地形的更多相关文章

  1. Directx11教程(6) 画一个简单的三角形(2)

    原文:Directx11教程(6) 画一个简单的三角形(2)      在上篇教程中,我们实现了在D3D11中画一个简单的三角形,但是,当我们改变窗口大小时候,三角形形状却随着窗口高宽比例改变而改变, ...

  2. Directx11教程(5) 画一个简单的三角形(1)

    原文:Directx11教程(5) 画一个简单的三角形(1)       在本篇教程中,我们将通过D3D11画一个简单的三角形.在D3D11中,GPU的渲染主要通过shader来操作(当然还有一些操作 ...

  3. Directx11教程(7) 画一个颜色立方体

    原文:Directx11教程(7) 画一个颜色立方体       前面教程我们通过D3D11画了一个三角形,本章我们将画一个颜色立方体,它的立体感更强.主要的变动是ModelClass类,在Model ...

  4. Directx11教程(10) 画一个简易坐标轴

    原文:Directx11教程(10) 画一个简易坐标轴       本篇教程中,我们将在三维场景中,画一个简易的坐标轴,分别用红.绿.蓝三种颜色表示x,y,z轴的正向坐标轴. 为此,我们要先建立一个A ...

  5. Directx11学习笔记【十一】 画一个简单的三角形--effect框架的使用

    这里不再介绍effect框架的具体使用,有关effect框架使用可参考http://www.cnblogs.com/zhangbaochong/p/5475961.html 实现的功能依然是画一个简单 ...

  6. Directx11教程(56) 建立一个skydome

    原文:Directx11教程(56) 建立一个skydome       本章建立一个skydome(天空穹),主要学习如何使用cube mapping.      cube map就是把六张纹理当作 ...

  7. Directx11教程(42) 纹理映射(12)-简单的bump mapping

    原文:Directx11教程(42) 纹理映射(12)-简单的bump mapping        有时候,我们只有一个粗糙的模型,但是我们想渲染纹理细节,比如一个砖墙,我们如何在只有一个平面的时候 ...

  8. Directx11教程(11) 增加一个debug宏

    原文:Directx11教程(11) 增加一个debug宏       现在我们在common.h中增加一个debug的宏,在每个d3d11函数后调用,如果d3d函数出错,它能够给出程序中错误的代码行 ...

  9. Directx11教程(9) 增加一个TimerClass类

    原文:Directx11教程(9) 增加一个TimerClass类      在上篇教程代码的基础上,我们增加一个TimerClass类,这个类的功能很简单,就是可以计算相邻2帧的时间差.利用这个时间 ...

随机推荐

  1. 做网站-mysql表字段设计

    https://mp.weixin.qq.com/s/HhdbmQqKmiw9IVnnL0Zyag VARCHAR与CHAR如何选择 使用VARCHAR理由 字段不经常更新 字段比较长,且长度不均(比 ...

  2. java 并发 详解

    1 普通线程和 守护线程的区别. 守护线程会跟随主线程的结束而结束,普通线程不会. 2 线程的 stop  和 interrupted 的区别. stop 会停止线程,但是不会释放锁之类的资源? in ...

  3. MyBatis映射器(一)--多参数传递方式

    在mybatis映射器的接口中,一般在查询时需要传递一些参数作为查询条件,有时候是一个,有时候是多个.当只有一个参数时,我们只要在sql中使用接口中的参数名称即可,但是如果是多个呢,就不能直接用参数名 ...

  4. 学习mysql数据库

    1.数据库是怎么回事 数据库是存储数据的永久空间,通过一种特殊的方式存储到硬盘中 数据库分为关系型数据库和非关系型数据库 mysql查看数据的方式为:结构化查询语言(SQL语句) 访问mysql数据库 ...

  5. 【DM642学习笔记十】DSP优化记录

    1. 处理的数据先EDMA到片内,具有更高的效率! 以YUV2RGB为例: #pragma DATA_SECTION(onchipBuf0_y,".INTPROCBUFF"); # ...

  6. 提高scrapy的抓取效率

    增加并发 默认scrapy开启的并发线程的个数是32个,可以适当的进行增加.在settings中进行设置CONCURRENT_REQUESTS=100 降低日志级别 在运行的时候,会有大量的日志信息的 ...

  7. H5C3--过渡transition

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. laravel-admin列表排序在使用了$grid->model()->latest()后$grid其它加上sortable()可排序的列在排序时不起作用

    laravel-admin这个基于laravel的后台框架,简单易用,$grid的默认排序是主键升序的排列方式,但在使用了`$grid->model()->latest();`自定义默认排 ...

  9. 利用HttpWebRequest通过POST Json数据在.net后台实现不同平台间的数据传输

    /// <summary> /// 返回JSon数据 /// </summary> /// <param name="JSONData">要处理 ...

  10. idea中隐藏.idea文件夹和.iml文件

    idea中的.idea文件夹和.iml是平常几乎不使用的文件,在创建父子工程或者聚合工程时反而会对我们操作产生干扰,所以,一般情况下,我们都将其隐藏掉,步骤如下: 操作前: 具体操作:File——&g ...