好的,我有80000个简单纹理的"Box"网格我设置了一个观看距离只画你能看到的下面的DrawModel函数剩下600到1000问题是我每秒只有10帧,而且我的观看距离很差此外,我已经对所有代码进行了内存测试,"mesh.draw()"每秒减少30帧。没有什么比这更能吸引NEAR了。有什么帮助吗?
private void DrawModel(MeshHolder tmpMH)
{
Model tmpDrawModel = (Model)_Meshs[tmpMH.MeshFileName];
Matrix[] transforms = new Matrix[tmpDrawModel.Bones.Count];
tmpDrawModel.CopyAbsoluteBoneTransformsTo(transforms);
foreach (ModelMesh mesh in tmpDrawModel.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.LightingEnabled = false;
effect.TextureEnabled = true;
effect.Texture = (Texture2D)_Textures[tmpMH.GetTexture(Count)];
effect.View = _MainCam.View;
effect.Projection = _projection;
effect.World =
transforms[mesh.ParentBone.Index] *
Matrix.CreateFromYawPitchRoll(tmpMH.Rotation.Y, tmpMH.Rotation.X, tmpMH.Rotation.Z) *
Matrix.CreateScale(tmpMH.Scale) *
Matrix.CreateTranslation(tmpMH.Position);
}
mesh.Draw();
}
}
正如您所说,正在扼杀您的性能的是ModelMesh.Draw
。当你画模型时,它是这样工作的:
for each frame
for each Model
for each ModelMesh // you call Draw(), which does:
for each ModelMeshPart
for each Effect
for each EffectPass
Draw some triangles // sends a batch of instructions to the GPU
所以问题是:你每帧向GPU发送一个批次多少次?因为在CPU饱和之前,每帧只能发送几千个*批,达到"批限制"。(每个批次都会占用图形驱动程序中的CPU时间——它也会占用一些带宽和GPU时间,但CPU时间占主导地位。)
您可能想阅读此答案、此答案和此幻灯片组以了解更多信息。
解决方案是修改场景(例如:组合一些网格部分,进行一些剔除,添加实例化支持),以减少发送到GPU的批次数量。
此外,在Draw
和Update
循环中尽量避免这样的事情:
Matrix[] transforms = new Matrix[tmpDrawModel.Bones.Count];
你真的应该尽最大努力避免每帧发生内存分配,因为它们最终会导致昂贵的垃圾收集和潜在的帧速率问题(尤其是在Xbox上)。尝试将缓冲区存储在某个地方并重复使用。
effect.World =
transforms[mesh.ParentBone.Index] *
Matrix.CreateFromYawPitchRoll(
tmpMH.Rotation.Y, tmpMH.Rotation.X, tmpMH.Rotation.Z) *
Matrix.CreateScale(tmpMH.Scale) *
Matrix.CreateTranslation(tmpMH.Position);
我不是一个剖析者,但我觉得这句话很痛苦。矩阵的创建和乘法是相当昂贵的!我知道这个代码是必要的,所以,除非你能预先计算这些矩阵,否则我会尝试:
Matrix pitch, scale, translation, temp1, temp2;
Matrix.CreateFromYawPitchRoll(
tmpMH.Rotation.Y, tmpMH.Rotation.X, tmpMH.Rotation.Z, out pitch);
Matrix.CreateScale(ref tmpMH.Scale, out scale);
Matrix.CreateTranslation(ref tmpMH.Position, out translation);
Matrix.Multiply(ref transforms[mesh.ParentBone.Index], ref pitch, out temp1);
Matrix.Multiply(ref temp1, ref scale, out temp2);
Matrix.Multiply(ref temp2, ref translation, out effect.World);
这可能会更快,因为不需要复制堆栈上的每个矩阵来传递参数(要复制的东西要少20多倍!)