2

我正在尝试通过使用 DrawUserIndexedPrimitives 绘制由线条组成的模型来在 XNA 中制作 3D WP7 游戏这一切都很好,但现在我想给每个模型自己的旋转。目前我正在使用 BasicEffect 来绘制所有模型。我可以设置它的旋转,但是所有对象都将具有相同的旋转。有没有办法为每个对象设置不同的旋转?我目前提出了几个可以使用的解决方案,但我对其中任何一个都不满意:

  • 为每个具有自己的世界的对象创建一个新的 BasicEffect,然后遍历所有对象以获得它们的基本效果并绘制它 - 我想所有这些 BasicEffects 都会产生很多开销,我想将效果与楷模。
  • 自己计算点(即计算旋转并将这些值传递给 DrawUserIndexedPrimitives 方法) - 这是一个相当昂贵的计算,大大降低了性能。

有什么建议的路线可以到这里吗?

我不知道 DrawUserIndexedPrimitives 是否是最好的使用方法,我只想能够画线并给它们一个旋转。如果有更好的方法来做到这一点,请告诉我:)

我目前的解决方案:

protected override void Draw(GameTime gameTime)
{
    GraphicsDevice.Clear(Color.Black);

    foreach (var model in _models)
    {

        foreach (var pass in model.Effect.CurrentTechnique.Passes)
        {
            pass.Apply();
            model.Effect.World = _model.GetWorld();

            var points = model.GetPoints();
            GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.LineList, points, 0, points.Length, model.Lines, 0, model.Lines.Length / 2);

            _models[0].Draw(GraphicsDevice);
        }
    }

    base.Draw(gameTime);
}

model.GetWorld() 返回一个包含对象旋转、平移和缩放的矩阵,model.GetPoints() 一个包含点的列表,model.Lines 是一个包含连接点索引的列表

4

2 回答 2

2

您通常只需要任何类型的效果中的一种(例如 BasicEffect)。原因是效果包含两个主要内容:为 GPU 编写的代码(照明等)和它公开的参数(例如 Effect.World,世界矩阵)。多次编译 GPU 代码没有多大意义,因为每次都相同,所以我们唯一需要考虑的另一件事是参数。

注意对 pass.Apply() 的调用。这实际上是在每次绘制之前将您在效果上设置的所有参数上传到 GPU。希望应该告诉您的是,您应该能够在每次绘制之前在单个效果上设置旋转并调用 Apply,而不是使用单独设置的旋转创建一堆效果。此外,设置 Effect.World 实际上应该在 pass.Apply() 之前。

要回答第二个要点,您是完全正确的。GPU 用于对具有大量并行性的点进行转换,因此最好不要自己尝试,因为它会很慢。

至于DrawUserIndexedPrimitives,我不是图形爱好者,但通常该调用保留用于顶点不断变化的情况(如软体斑点或布料),基本上你无法通过翻译来描述网格,旋转和缩放。GPU 公开了称为 VertexBuffer 的特殊原语,其全部目标是在 GPU 内存中存储一​​堆点(这使得它们可以非常快速地访问)。从那里开始,如果您想移动它,GPU 将转换每个点(但请注意,您需要传递它的只是平移、旋转和缩放,一切顺利)。使用 DrawUserIndexedPrimitives 实际上必须每帧将所有点发送到 GPU,这更慢(多少,谁知道这些天没有测试)。

幸运的是,显卡实际上实现了一种特殊的绘制模式,称为“线框”,它不是绘制三角形,而是将三角形的边缘绘制为线条。要设置线框模式,请在调用 Draw 之前执行此操作:

this.GraphicsDevice.RasterizerState.FillMode = FillMode.WireFrame;

现在,在应用您自己的旋转方面,您实际上需要做的就是将世界矩阵乘以一个旋转矩阵(使用类似 Matrix.CreateRotationX(yourAngle) 的东西)。

于 2012-05-13T04:24:04.023 回答
0

您当前的解决方案很好,尽管我会在 pass.Apply() 之前进行世界分配

如果您的模型很少,您可以使用变换传递给着色器和数组,并在您的顶点结构中添加该数组的索引。

这样,您可以一次绘制所有模型。

于 2012-05-13T04:26:36.987 回答