頂点/インデックスバッファに入力するデータを処理するより良い方法があるかどうか疑問に思っています(確かにあると思います)。現時点で、地形の頂点の構造体は次のようになります。
struct VertexType
{
D3DXVECTOR3 position;
D3DXVECTOR2 texture;
D3DXVECTOR3 normal;
};
ゲームが起動するたびに地形をランダムに生成し、この高さマップに基づいて法線とテクスチャ座標を計算しています。最後に、この方法で頂点配列を埋めています:
// Calculate the number of vertices in the terrain mesh.
m_vertexCount = (m_terrainWidth - 1) * (m_terrainHeight - 1) * 6;
// Create the vertex array.
m_vertices.resize(m_vertexCount);
// Initialize the index to the vertex buffer.
index = 0;
// Load the vertex and index array with the terrain data.
for(j=0; j<(m_terrainHeight-1); j++)
{
for(i=0; i<(m_terrainWidth-1); i++)
{
index1 = (m_terrainHeight * j) + i; // Bottom left.
index2 = (m_terrainHeight * j) + (i+1); // Bottom right.
index3 = (m_terrainHeight * (j+1)) + i; // Upper left.
index4 = (m_terrainHeight * (j+1)) + (i+1); // Upper right.
// Upper left.
tv = m_heightMap[index3].tv;
// Modify the texture coordinates to cover the top edge.
if(tv == 1.0f) { tv = 0.0f; }
m_vertices[index].position = D3DXVECTOR3(m_heightMap[index3].x, m_heightMap[index3].y, m_heightMap[index3].z);
m_vertices[index].texture = D3DXVECTOR2(m_heightMap[index3].tu, tv);
m_vertices[index].normal = D3DXVECTOR3(m_heightMap[index3].nx, m_heightMap[index3].ny, m_heightMap[index3].nz);
index++;
// Upper right.
tu = m_heightMap[index4].tu;
tv = m_heightMap[index4].tv;
// Modify the texture coordinates to cover the top and right edge.
if(tu == 0.0f) { tu = 1.0f; }
if(tv == 1.0f) { tv = 0.0f; }
m_vertices[index].position = D3DXVECTOR3(m_heightMap[index4].x, m_heightMap[index4].y, m_heightMap[index4].z);
m_vertices[index].texture = D3DXVECTOR2(tu, tv);
m_vertices[index].normal = D3DXVECTOR3(m_heightMap[index4].nx, m_heightMap[index4].ny, m_heightMap[index4].nz);
index++;
// Bottom left.
m_vertices[index].position = D3DXVECTOR3(m_heightMap[index1].x, m_heightMap[index1].y, m_heightMap[index1].z);
m_vertices[index].texture = D3DXVECTOR2(m_heightMap[index1].tu, m_heightMap[index1].tv);
m_vertices[index].normal = D3DXVECTOR3(m_heightMap[index1].nx, m_heightMap[index1].ny, m_heightMap[index1].nz);
index++;
// Bottom left.
m_vertices[index].position = D3DXVECTOR3(m_heightMap[index1].x, m_heightMap[index1].y, m_heightMap[index1].z);
m_vertices[index].texture = D3DXVECTOR2(m_heightMap[index1].tu, m_heightMap[index1].tv);
m_vertices[index].normal = D3DXVECTOR3(m_heightMap[index1].nx, m_heightMap[index1].ny, m_heightMap[index1].nz);
index++;
// Upper right.
tu = m_heightMap[index4].tu;
tv = m_heightMap[index4].tv;
// Modify the texture coordinates to cover the top and right edge.
if(tu == 0.0f) { tu = 1.0f; }
if(tv == 1.0f) { tv = 0.0f; }
m_vertices[index].position = D3DXVECTOR3(m_heightMap[index4].x, m_heightMap[index4].y, m_heightMap[index4].z);
m_vertices[index].texture = D3DXVECTOR2(tu, tv);
m_vertices[index].normal = D3DXVECTOR3(m_heightMap[index4].nx, m_heightMap[index4].ny, m_heightMap[index4].nz);
index++;
// Bottom right.
tu = m_heightMap[index2].tu;
// Modify the texture coordinates to cover the right edge.
if(tu == 0.0f) { tu = 1.0f; }
m_vertices[index].position = D3DXVECTOR3(m_heightMap[index2].x, m_heightMap[index2].y, m_heightMap[index2].z);
m_vertices[index].texture = D3DXVECTOR2(tu, m_heightMap[index2].tv);
m_vertices[index].normal = D3DXVECTOR3(m_heightMap[index2].nx, m_heightMap[index2].ny, m_heightMap[index2].nz);
index++;
}
}
// shrink heightmap because its no longer in use...
m_heightMap.clear();
m_heightMap.swap(m_heightMap);
このコードは、rastertek.com から部分的に取得されます。これは多くの冗長データが保存されているのではないかどうか疑問に思っています (クワッドごとに 6 つの頂点)。ただし、問題は、クワッドツリーのバッファーを形成するために、後でこの構造が必要になることです。各ノードでバッファを埋めるためのコードは次のとおりです (すべてのノードには独自のバッファがあります。これを行うためのより良い方法はありますか?)。
node->triangleCount = numTriangles;
// Calculate the number of vertices.
vertexCount = numTriangles * 3;
// Create the vertex array.
vertices = new VertexType[vertexCount];
// Create the index array.
indices = new unsigned long[vertexCount];
// Create the vertex array.
node->vertexArray = new VectorType[vertexCount];
// Initialize the index for this new vertex and index array.
index = 0;
// Go through all the triangles in the vertex list.
for(i=0; i<m_triangleCount; i++)
{
// If the triangle is inside this node then add it to the vertex array.
result = IsTriangleContained(i, positionX, positionZ, width);
if(result == true)
{
// Calculate the index into the terrain vertex list.
vertexIndex = i * 3;
// Get the three vertices of this triangle from the vertex list.
vertices[index].position = (*m_vertexList)[vertexIndex].position;
vertices[index].texture = (*m_vertexList)[vertexIndex].texture;
vertices[index].normal = (*m_vertexList)[vertexIndex].normal;
indices[index] = index;
// Also store the vertex position information in the node vertex array.
node->vertexArray[index].x = (*m_vertexList)[vertexIndex].position.x;
node->vertexArray[index].y = (*m_vertexList)[vertexIndex].position.y;
node->vertexArray[index].z = (*m_vertexList)[vertexIndex].position.z;
index++;
vertexIndex++;
vertices[index].position = (*m_vertexList)[vertexIndex].position;
vertices[index].texture = (*m_vertexList)[vertexIndex].texture;
vertices[index].normal = (*m_vertexList)[vertexIndex].normal;
indices[index] = index;
node->vertexArray[index].x = (*m_vertexList)[vertexIndex].position.x;
node->vertexArray[index].y = (*m_vertexList)[vertexIndex].position.y;
node->vertexArray[index].z =(*m_vertexList)[vertexIndex].position.z;
index++;
vertexIndex++;
vertices[index].position = (*m_vertexList)[vertexIndex].position;
vertices[index].texture = (*m_vertexList)[vertexIndex].texture;
vertices[index].normal = (*m_vertexList)[vertexIndex].normal;
indices[index] = index;
node->vertexArray[index].x = (*m_vertexList)[vertexIndex].position.x;
node->vertexArray[index].y = (*m_vertexList)[vertexIndex].position.y;
node->vertexArray[index].z = (*m_vertexList)[vertexIndex].position.z;
index++;
}
}
// Set up the description of the vertex buffer.
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(VertexType) * vertexCount;
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
vertexBufferDesc.MiscFlags = 0;
vertexBufferDesc.StructureByteStride = 0;
// Give the subresource structure a pointer to the vertex data.
vertexData.pSysMem = vertices;
vertexData.SysMemPitch = 0;
vertexData.SysMemSlicePitch = 0;
// Now finally create the vertex buffer.
device->CreateBuffer(&vertexBufferDesc, &vertexData, &node->vertexBuffer);
// Set up the description of the index buffer.
indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
indexBufferDesc.ByteWidth = sizeof(unsigned long) * vertexCount;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
indexBufferDesc.CPUAccessFlags = 0;
indexBufferDesc.MiscFlags = 0;
indexBufferDesc.StructureByteStride = 0;
// Give the subresource structure a pointer to the index data.
indexData.pSysMem = indices;
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0;
// Create the index buffer.
device->CreateBuffer(&indexBufferDesc, &indexData, &node->indexBuffer);
// Release the vertex and index arrays now that the data is stored in the buffers in the node.
delete [] vertices;
vertices = 0;
delete [] indices;
indices = 0;
isTriangleContained() メソッドは、現在の三角形が現在のノードにあるかどうかを確認します。そうである場合、三角形は配列に保存され、このノードのバッファが埋められます。ご覧のとおり、上記の構造により、ここでの頂点の選択は非常に簡単です。
問題は、たとえば 2048 より大きい地形を生成してレンダリングしようとすると、m_vertices ベクトルが大量のメモリを割り当てていることです。これをすべて処理するより良い方法はありますか?たぶん、GPUでいくつかの計算を行いますか?
喜んで手伝ってくれる人に感謝します!