问题:我试图用许多(大约10000)个相似的物体来画一个场景(在我的例子中,灌木丛,但可能是任何东西)。对于每一个灌木,我有三个网格,有一个不同数量的三角形,我想使用这些网格中的一个取决于距离相机。
第一种方法:我可以选择正确的网格在CPU上,更新模型矩阵后,每灌木,然后绘制与正确的网格VBO。问题是我需要每帧更新10000次模型矩阵.您可以猜到这意味着性能方面的问题。
第二种方法:在CPU上再次选择正确的网格,但这一次使用实例渲染在一次绘制调用中绘制所有具有最低lod的灌木,然后是中间lod的灌木,然后是高lod的灌木丛。我已经在GPU上储存了灌木丛的位置。但我在这里的问题是,我仍然需要发送一个数组作为统一变量,其中包含必须在哪个位置绘制网格的信息。通过这种方法,我遇到了统一变量的极限。
问题:我想做的是计算从灌木丛到GPU摄像机的距离(例如,在顶点着色器中没有问题)。然后,根据结果,只绘制具有正确细节级别的VBO。因此,我的问题是,是否有可能选择哪个VBO来使用GPU (我不认为有任何可能这样做,因为在顶点和片段着色器,我是一个已经很远的管道)?或者你还有什么我可以尝试的想法?
最好的,艾伯特
发布于 2016-06-27 19:28:07
海事组织,你的第二种方法的一个变体将是最简单的,而且可能相当快。
你分析过什么了吗?一个CPU应该极快地咀嚼10000矩阵乘法。如果您想获得更高的性能,可以使用SIMD /线程更新。也就是说,最慢的部分可能是在PCIE总线上发送10000块矩阵的带宽。
但是,再说一遍,这都是假设。试一试,然后分析一下。
我在想这样的事情:
(我为DX的功能道歉。我不太熟悉相应的OpenGL函数。也就是说,OpenGL应该是非常相似的)
// Variable definitions
vector<matrix> lod0;
vector<matrix> lod1;
vector<matrix> lod2;
ID3D11Buffer lod0VertexBuffer;
uint lod0VertexCount;
ID3D11Buffer lod1VertexBuffer;
uint lod1VertexCount;
ID3D11Buffer lod2VertexBuffer;
uint lod2VertexCount;
ID3D11Buffer instanceBuffer;
/// ..................
/// Per frame...
lod0.clear();
lod1.clear();
lod2.clear();
for (uint i = 0; i < bushes.size(); ++i) {
float distance = distance(bushes[i].pos, camera.origin);
if (distance < 50.0f) {
lod0.push_back(bushes[i].matrix);
} else if (distance < 100.0f) {
lod1.push_back(bushes[i].matrix);
} else {
lod2.push_back(bushes[i].matrix);
}
}
D3D11_MAPPED_SUBRESOURCE mappedResource;
ID3D11Buffer vertexBuffers[] = {
lod0VertexBuffer,
instanceBuffer
};
// Update lod0 matrices
context->Map(instanceBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
memcpy(mappedResource.pData, &lod0[0], sizeof(matrix) * lod0.size());
context->Unmap(instanceBuffer, 0);
// Draw lod0
context->IASetVertexBuffers(0, 2, vertexBuffers, nullptr, nullptr);
context->DrawInstanced(lod0VertexCount, lod0.size(), 0, 0);
// Update lod1 matrices
context->Map(instanceBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
memcpy(mappedResource.pData, &lod1[0], sizeof(matrix) * lod1.size());
context->Unmap(instanceBuffer, 0);
// Draw lod1
vertexBuffers[0] = lod1VertexBuffer;
context->IASetVertexBuffers(0, 2, vertexBuffers, nullptr, nullptr);
context->DrawInstanced(lod1VertexCount, lod1.size(), 0, 0);
// Update lod2 matrices
context->Map(instanceBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
memcpy(mappedResource.pData, &lod2[0], sizeof(matrix) * lod1.size());
context->Unmap(instanceBuffer, 0);
// Draw lod2
vertexBuffers[0] = lod2VertexBuffer;
context->IASetVertexBuffers(0, 2, vertexBuffers, nullptr, nullptr);
context->DrawInstanced(lod1VertexCount, lod2.size(), 0, 0);如果结果太慢,您可以尝试在计算着色器中进行此计算,然后使用间接绘图调用绘制结果。见AZDO。
https://computergraphics.stackexchange.com/questions/3688
复制相似问题