在directx中渲染地形11

时间:2016-05-08 18:00:37

标签: c++ directx directx-11 terrain

我尝试使用directx 11渲染地形并对其应用高度贴图。 我加载高度图然后将其复制到整数向量,然后对于每个顶点位置,我将该顶点的Y位置分配给高度图值,但是地形被完全破坏和扭曲。当我删除Y轴上的计算时,我得到一个平面网格,没有问题。

bool cGrid::readRawFile(std::string fileName, int m, int n)
{
   // A height for each vertex
    std::vector<BYTE> in(m*n);
    std::ifstream inFile(fileName.c_str(), std::ios_base::binary);
    if (!inFile)
        return false;
    inFile.read(
        (char*)&in[0], // buffer
        in.size());// number of bytes to read into buffer
    inFile.close();
    // copy BYTE vector to int vector
    m_heightmap.resize(n*m);
    for (int i = 0; i < in.size(); i++)
        m_heightmap[i] = in[i];
    return true;
}

for (size_t i = 0; i<m_Mesh.m_Vertices.size(); ++i)
    {
        XMFLOAT3 p = m_Mesh.m_Vertices[i].Position;
        p.y = (float)m_heightmap[i]*0.5f;
        m_Mesh.m_Vertices[i].Position = p;
    }

这是一个问题视频

https://www.youtube.com/watch?v=lnlIz3DjebM&feature=youtu.be enter image description here

enter image description here

HRESULT cGrid::CreateGrid(float width, float depth, UINT n, UINT m)
{
    HRESULT hr;
    int vertexCount = m*n;
    UINT faceCount = (m - 1)*(n - 1) * 2; // each quad consists of two triangles

    float halfWidth = 0.5f*width;
    float halfDepth = 0.5f*depth;

    // project the grid into xz plane 
    float dx = width / (n - 1);
    float dz = depth / (m - 1);

    float du = 1.0f / (n - 1); // texture co-ordinates
    float dv = 1.0f / (m - 1);


    m_Mesh.m_Vertices.resize(vertexCount);

    // build the vertices of the grid, including the normals and the tangent,
    //you can build then the bitanget by cross product for normal maps -_- 

    for (UINT i = 0; i < m; ++i)
    {
        float z = halfDepth - i*dz; // reset for the next cell 
        for (UINT j = 0; j < n; ++j)
        {
            float x = -halfWidth + j*dx;
            float y = (float)m_heightmap[j + i*m];
            m_Mesh.m_Vertices[i*n + j].Position = XMFLOAT3(x, y, z);
//          m_Mesh.m_Vertices[i*n + j].Normal = XMFLOAT3(0.0f, 1.0f, 0.0f);
//          m_Mesh.m_Vertices[i*n + j].TangentU = XMFLOAT3(1.0f, 0.0f, 0.0f);

            // Stretch texture over grid.
            m_Mesh.m_Vertices[i*n + j].TextureCords.x = j*du;
            m_Mesh.m_Vertices[i*n + j].TextureCords.y = i*dv;
        }
    }

    m_Mesh.m_Indices.resize(faceCount * 3); // 3 indices per face

    // Iterate over each quad and compute indices.
    UINT k = 0;
    for (UINT i = 0; i < m - 1; ++i)
    {
        for (UINT j = 0; j < n - 1; ++j)
        {
            m_Mesh.m_Indices[k] = i*n + j;
            m_Mesh.m_Indices[k + 1] = i*n + j + 1;
            m_Mesh.m_Indices[k + 2] = (i + 1)*n + j;

            m_Mesh.m_Indices[k + 3] = (i + 1)*n + j;
            m_Mesh.m_Indices[k + 4] = i*n + j + 1;
            m_Mesh.m_Indices[k + 5] = (i + 1)*n + j + 1;

            k += 6; // next quad
        }
    }

    m_IndicesSize = m_Mesh.m_Indices.size();


    // Pack all the vertices into vertex buffer
    D3D11_BUFFER_DESC vbd;
    vbd.Usage = D3D11_USAGE_IMMUTABLE;
    vbd.ByteWidth = sizeof(MeshVertex)* vertexCount;
    vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vbd.CPUAccessFlags = 0;
    vbd.MiscFlags = 0;
    D3D11_SUBRESOURCE_DATA vinitData;
    vinitData.pSysMem = &(m_Mesh.m_Vertices[0]);
    m_pGraphics->getDevice()->CreateBuffer(&vbd, &vinitData, &mVB);

    // Pack the indices of all the meshes into one index buffer.
    D3D11_BUFFER_DESC ibd;
    ibd.Usage = D3D11_USAGE_DEFAULT;
    ibd.ByteWidth = sizeof(UINT)* m_IndicesSize;
    ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
    ibd.CPUAccessFlags = 0;
    ibd.MiscFlags = 0;
    D3D11_SUBRESOURCE_DATA iinitData;
    iinitData.pSysMem = &m_Mesh.m_Indices[0];
    m_pGraphics->getDevice()->CreateBuffer(&ibd, &iinitData, &mIB);

    // Create the constant buffer
    ibd.Usage = D3D11_USAGE_DEFAULT;
    ibd.ByteWidth = sizeof(ConstantBuffer);
    ibd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    ibd.CPUAccessFlags = 0;
    hr = m_pGraphics->getDevice()->CreateBuffer(&ibd, nullptr, &m_pConstantBuffer);
    if (FAILED(hr))
        return hr;

    return hr;
}

1 个答案:

答案 0 :(得分:1)

在定义unsigned char时,我会使用BYTE而不是std::vector<BYTE> in(m*n),因为它不是C标准库的一部分,因此它取决于系统。

也在这一行使用演员

in.size());// number of bytes to read into buffer

ifstream::read的实际参数类型std::streamsize

像这样:

(std::streamsize)in.size());// number of bytes to read into buffer

由于您正在使用8位高度贴图,因此您可能不应该只将RAW文件中的值复制到高度贴图中,如下所示:

for (int i = 0; i < in.size(); i++)
    m_heightmap[i] = in[i];

由于每个高度贴图值都由8位整数表示,因此您可以尝试将高度贴图值除以及将其与某个缩放修改器相乘。如果您想测试一些好的值,这将使它更方便。纯粹出于视觉目的......

for (int i = 0; i < in.size(); i++)
    m_heightmap[i] = (float)( in[i] / 255.0f ) * scaleModifier;