c++ - 在 directx 11 中渲染地形

标签 c++ directx directx-11 terrain

我正在尝试使用 directx 11 渲染地形并对其应用高度图。 我加载高度图,然后将其复制到一个整数 vector ,然后对于每个顶点位置,我将该顶点的 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;
}

最佳答案

我会使用 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;

关于c++ - 在 directx 11 中渲染地形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37103066/

相关文章:

c++ - 编译Arduino代码(NodeMCU)时出错

c++ - 将网格从 .obj(或任何其他)文件加载到 DirectX9/C++ 项目中

c++ - 网格表示 - 一个顶点(空间位置)= 一个位置,tex 坐标,法线?

c++ - 为什么我的 UWP 游戏在发布时比在 Debug模式下慢?

c++ - 有没有办法在调用 boost::bind 对象时显式指定模板参数?

c++ - 在 operator delete[] 中取消析构函数调用

c++ - 有没有办法从仿函数中提取第一个参数的类型?

c++ - 如何处理 DirectX 11 驱动程序崩溃

c++ - WP8.1 认证 - 6.5.1 - 使用 XAML/C++ 的初始启动功能

c++ - D3D11DeviceContext 更新子资源上的模糊内核异常