• 热门专题

Directx11教程(19) 画一个简单的地形

作者:迈克老狼2012  发布日期:2012-04-10 11:29:40
Tag标签:Directx11  简单地形  
  •     通常我们在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键来移动摄像机看看地形的效果。

    image

     

    我们还可以修改D3DClass.cpp中,渲染状态Fillmode设置,修改为线框模式后的效果如下:

    image

     

    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://down1.it165.net/pro/201204/0410myTutorialD3D11.zip
About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规