首页>
知识库>
详情

LOD地形设计与实现

2020-08-12 来源:CloudBest 阅读量: 0
关键词:

    LOD地形设计与实现
    地形从一开始研究,到实现,分了好多个版本,重构了好多次……主要问题在于对LOD数据结构的不熟悉和对索引用法的不熟悉。经过一系列的研究与学习,总结了如下实现LOD的方法:
    #动态填充索引——在裁剪过程中求出被渲染的地形块。
    #分块实现地形,每块有一定的渲染格。
    下面一步步写出实现过程。
    1、定义数据结构,主要是地义地形的块并实现四叉树。
    2、写好VertexBuffer和IndexBuffer,主要是一边渲染一边填充IndexBuffer,根据裁剪出来的地形块来填充。
    3、写好LOD算法,主要是实现LOD的计算方法。
    4、写好裂缝修补算法。花在该项时间最长最麻烦。
    5、贴纹理写shader。
    地形block数据结构如下:
    class CTerrainBlock
    {
    public:
    private:
    float  m_fCellSpacing;  //地形网格长度
    float  m_fSphereHalf;    //裁剪的半径
    float  m_fDeltaH;    //高度差
    int    m_nLODLevel;    //LOD层数
    vector<CTerrainCell*> m_Child;   //子结点
    int   m_dwSeq;    //索引号,左上角点为索引
    int   m_nRealCell;   //实际每行的渲染格数,根据LOD层数定
    DWORD m_dwCellsPerRender;           //每个渲染块的最小格数
    vector<DWORD>      m_vtCorner;     //四个角的索引,顺序为从左上角开始,顺时针
    int              m_nLeftIndexCount;           //每个渲染格增加的顶点数,一般是1或3
    int              m_nRightIndexCount;
    int              m_nBottomIndexCount;
    int              m_nTopIndexCount;
    int              m_nNeighbor[4];     //分别是上、右、下、左,必须是相同一层的
    }
    地形渲染的流程如下:
    首先用一个递归函数计算出要渲染的block并计算出其LOD值,代码如下:
    oid CTerrain::DrawTerrain(CTerrainBlock* pNode)
    {
    if (pNode == NULL)
    {
    return;
    }
    if (结点是要渲染的块)
    {
    if (在视锥体内)   //判断是否在视锥体内
    {
    for (int i = 0; i < 4; i++)
    {
    DrawTerrain(pNode->GetChildNode(i));
    }
    }
    }
    else             //最小格,直接插入队列
    {
    计算LOD值;
    m_vtDraw.push_back(pNode);
    }
    }
    整个渲染代码如下:
    void CTerrain::Render()
    {
    DrawTerrain(m_pRoot);
    修补裂缝;
    填充索引;
    设置shader;
    设置顶点缓冲;
    设置纹理;
    DrawIndexedPrimitive();
    }