我以“Minecraft”游戏的方式为一个项目工作。
我开始使用“模型实例化”来生成大量具有相同模型的立方体。 到现在为止还挺好。 我的问题是,如果我增加矩阵的大小来绘制[300-1-300]( 90,000立方米)[500-1-500]( 250,000立方米< / strong>)我的程序变得非常缓慢。它从60fps到20 ......
我真的不明白为什么。但我正确使用该技术“硬件实例化”。我也在论坛上注意到这种技术允许XNA绘制高达700万立方! 你对我的问题有什么想法吗?
非常感谢
这是我的函数,用于绘制实例化的模型:
// Draw the 3D map (world) of game
public void drawWorld(GameTime gameTime)
{
/ * Draw all the structures that make up the world with the instancing system * /
Array.Resize(ref instanceTransforms, smallListInstance.Count);
for (int i = 0; i < ListInstance.Count; i++)
{
instanceTransforms[i] = ListInstance[i].Transform;
}
DrawModelHardwareInstancing(myModel, myTexture2D,instancedModelBones,instanceTransforms, arcadia.camera.View, arcadia.camera.Projection);
}
// ### end function drawWorld
这是我的函数[DrawModelHardwareInstancing] ,它使用microsoft示例中使用的 [Hardware Instancing] 方法绘制模型。
// Function that will draw all the models instantiated in the list
void DrawModelHardwareInstancing(Model model,Texture2D texture, Matrix[] modelBones,
Matrix[] instances, Matrix view, Matrix projection)
{
Game.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
if (instances.Length == 0)
return;
// If we have more instances than room in our vertex buffer, grow it to the neccessary size.
if ((instanceVertexBuffer == null) ||
(instances.Length > instanceVertexBuffer.VertexCount))
{
if (instanceVertexBuffer != null)
instanceVertexBuffer.Dispose();
instanceVertexBuffer = new DynamicVertexBuffer(Game.GraphicsDevice, instanceVertexDeclaration,
instances.Length, BufferUsage.WriteOnly);
}
// Transfer the latest instance transform matrices into the instanceVertexBuffer.
instanceVertexBuffer.SetData(instances, 0, instances.Length, SetDataOptions.Discard);
foreach (ModelMesh mesh in model.Meshes)
{
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
// Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer.
Game.GraphicsDevice.SetVertexBuffers(
new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0),
new VertexBufferBinding(instanceVertexBuffer, 0, 1)
);
Game.GraphicsDevice.Indices = meshPart.IndexBuffer;
// Set up the instance rendering effect.
Effect effect = meshPart.Effect;
//effect.CurrentTechnique = effect.Techniques["HardwareInstancing"];
effect.Parameters["World"].SetValue(modelBones[mesh.ParentBone.Index]);
effect.Parameters["View"].SetValue(view);
effect.Parameters["Projection"].SetValue(projection);
effect.Parameters["Texture"].SetValue(texture);
// Draw all the instance copies in a single call.
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
Game.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
meshPart.NumVertices, meshPart.StartIndex,
meshPart.PrimitiveCount, instances.Length);
}
}
}
}
// ### end function DrawModelHardwareInstancing
答案 0 :(得分:0)
非常感谢!由于你的建议,我终于解决了我的问题; - )!
我只绘制了我视野“相机”前面的模型。 仅在需要“编辑”,“新位置等等”时更新模型。
我的最后一步是只绘制6个立方体面中的3个以提高性能。
代码示例仅绘制前面的模型
public BoundingFrustum Frustum {get;私人集; }
//Initialize
Matrix viewProjection = View * Projection;
Frustum = new BoundingFrustum(viewProjection);
//Update
Matrix viewProjection = View * Projection;
Frustum.Matrix = viewProjection;
//Check instance and make the instanceTransformation for draw
foreach (var object in ListInstance.Where(m => Frustum.Contains(m.BoundingBox) != ContaintmentType.Disjoint)
{
instanceTransforms[index].Add(smallListInstance[i].Transform);
}
// And now draw ...