XNA 可以处理多少个(低多边形)模型?

发布于 2024-11-30 14:45:41 字数 1076 浏览 0 评论 0原文

我知道以下是一个模糊的问题,但我遇到了 XNA 中没有预料到的性能问题。

我有一个低多边形模型(它有 18 个面和 14 个顶点),我试图将其多次(高!)地绘制到屏幕上。在我绘制这个模型 5000 多次之前,我的帧速率超过 60 FPS(在一台不错的机器上)。我在这里要求太多了吗?我非常希望至少将这个数字增加一倍或三倍(10-15k)。

下面给出了我实际绘制模型的代码。我试图从绘制周期中消除尽可能多的计算,是否可以从中挤出更多计算,或者更好的替代方案?

注意:tile.Offset 在初始化期间计算一次,而不是每个周期。

foreach (var tile in Tiles)
        {
            var myModel = tile.Model;
            Matrix[] transforms = new Matrix[myModel.Bones.Count];
            myModel.CopyAbsoluteBoneTransformsTo(transforms);

            foreach (ModelMesh mesh in myModel.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    // effect.EnableDefaultLighting();
                    effect.World = transforms[mesh.ParentBone.Index] 
                                 * Matrix.CreateTranslation(tile.Offset);
                    effect.View = CameraManager.ViewMatrix;
                    effect.Projection = CameraManager.ProjectionMatrix;
                }
                mesh.Draw();
            }
        }

I'm aware that the following is a vague question, but I'm hitting performance problems that I did not anticipate in XNA.

I have a low poly model (It has 18 faces and 14 vertices) that I'm trying to draw to the screen a (high!) number of times. I get over 60 FPS (on a decent machine) until I draw this model 5000+ times. Am I asking too much here? I'd very much like to double or triple that number (10-15k) at least.

My code for actually drawing the models is given below. I have tried to eliminate as much computation from the draw cycle as possible, is there more I can squeeze from it, or better alternatives all together?

Note: tile.Offset is computed once during initialisation, not every cycle.

foreach (var tile in Tiles)
        {
            var myModel = tile.Model;
            Matrix[] transforms = new Matrix[myModel.Bones.Count];
            myModel.CopyAbsoluteBoneTransformsTo(transforms);

            foreach (ModelMesh mesh in myModel.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    // effect.EnableDefaultLighting();
                    effect.World = transforms[mesh.ParentBone.Index] 
                                 * Matrix.CreateTranslation(tile.Offset);
                    effect.View = CameraManager.ViewMatrix;
                    effect.Projection = CameraManager.ProjectionMatrix;
                }
                mesh.Draw();
            }
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

内心激荡 2024-12-07 14:45:42

与任何性能问题一样,特定方法的工作也存在局限性。您需要衡量并查看问题出在哪里。最好的选择是使用分析器,但即使是基本的测量(例如查看 CPU 负载)也可能会显示您遇到的瓶颈。

作为第一个调查步骤,我建议删除所有计算(例如矩阵乘法)并查看您得到的改进 - 这意味着 CPU 仍然比 GPU 做更多的工作。

确保您没有在调试构建上进行测量 - 如果应用程序受 CPU 限制,它可能会使应用程序显着变慢。

旁注:当您相对不频繁地发送大型操作时,GPU 的工作效果最佳。您的代码或多或少做了相反的事情 - 发送大量非常小的绘图请求。您应该能够批量处理基元并获得更好的性能。有一些关于如何渲染大量简单对象(包括 DirectX SDK 中的对象)的示例,搜索“GPU 渲染人群”可以为您提供起点。

As with any performance problem there are limits where a particular approach works. You need to measure and see where problems are. The best option is to use profiler but even basic measurements like looking at CPU load may show what bottlencks you have.

As a first investiagtion step I'd recommend to remove all computations (like matrix multiplications) and see you get improvments - this would mean that CPU is still doing more work than GPU.

Make sure you are not doing measurements on debug build - it could make application significantly slower if it is CPU bound.

Side note: GPU works the best when you send large operations relatively infrequently. Your code does more or less opposite - send huge number of very small drawing requests. You should be able to batch your primitives and get better performance. There are samples around how to render large number of simple objects (including ones in DirectX SDK), searching for "gpu rendering crowds" can give you starting point.

小苏打饼 2024-12-07 14:45:41

您显然已达到批次限制。请参阅此演示文稿这个答案此答案了解详细信息。简而言之:每秒可以向 GPU 提交的绘制调用数量是有限的。

批次限制是基于 CPU 的限制,因此一旦您的模型超过 5000 个,您可能会发现您的 CPU 被固定。更糟糕的是,当您的游戏正在进行其他计算时,它会减少可用于提交这些批次的 CPU 时间。

(值得注意的是,相反,您几乎肯定没有达到 GPU 限制。还不必担心网格复杂性。)

有多种方法可以减少批次数量。视锥体剔除就是其中之一。在您的情况下,最好的选择可能是几何实例化,这可以让您在单个批次中绘制多个模型。这是执行此操作的 XNA 示例

更好的是,如果它是静态几何体,您可以简单地将其全部烘焙到一个或几个大网格中吗?

You're quite clearly hitting the batch limit. See this presentation and this answer and this answer for details. Put simply: there is a limit to how many draw calls you can submit to the GPU each second.

The batch limit is a CPU-based limit, so you'll probably see that your CPU gets pegged once you get to your 5000+ models. Worse still, when your game is doing other calculations, it will reduce the CPU time available to submit those batches.

(And it's important to note that, conversely, you are almost certainly not hitting GPU limits. No need to worry about mesh complexity yet.)

There are a number of ways to reduce your batch count. Frustrum culling is one. Probably the best one to persue in your case is Geometry Instancing, this lets you draw multiple models in a single batch. Here is an XNA sample that does this.

Better still, if it's static geometry, can you simply bake it all into one or a few big meshes?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文