6

好的,我有 80,000 个带有简单纹理的“盒子”网格我已经设置了一个视图距离,只绘制你可以看到的那些,为下面的 DrawModel 函数留下 600 到 1000 个问题是我每秒只能获得 10 帧和我的视图距离很糟糕另外,我已经对我的所有代码进行了内存测试,并且“mesh.draw()”每秒需要 30 帧。没有其他东西需要这么多。有什么帮助吗?

        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();               
            }
        }
4

2 回答 2

7

是什么扼杀了你的表现——正如你所说的——是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 的批次数量。


另外,尽量避免在你的DrawandUpdate循环中发生这样的事情:

Matrix[] transforms = new Matrix[tmpDrawModel.Bones.Count];

您真的应该尽最大努力避免每帧发生的内存分配 - 因为它们最终会导致昂贵的垃圾收集和潜在的帧速率中断(尤其是在 Xbox 上)。尝试将缓冲区存储在某个地方并重用它。

于 2011-06-03T04:08:46.037 回答
3
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 倍以上!)

于 2011-06-02T22:20:11.977 回答