关于c#:WP7绘制大量原始多维数据集时出现滞后

WP7 Lagging when drawing lots of primitive cubes

我目前正在处理3D Arkanoid克隆,并且正在使用图元绘制立方体。

我有6行,每行49块,所以总共294块。
通常我不会为优化而烦恼,但是在低端手机上,游戏速度却慢得离谱。我知道问题出在块的绘制上,因为删除了该代码,游戏运行正常。

我用于设置原语的代码是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
VertexPositionNormalTexture[] vertices1 = new VertexPositionNormalTexture[4];
VertexPositionNormalTexture[] vertices2 = new VertexPositionNormalTexture[4];
VertexPositionNormalTexture[] vertices3 = new VertexPositionNormalTexture[4];
VertexPositionNormalTexture[] vertices4 = new VertexPositionNormalTexture[4];
VertexPositionNormalTexture[] vertices5 = new VertexPositionNormalTexture[4];
VertexPositionNormalTexture[] vertices6 = new VertexPositionNormalTexture[4];

public void SetupVertices(){
 vertices1[0].Position = new Vector3(position.X, position.Y, position.Z);
        vertices1[0].TextureCoordinate = new Vector2(1, 1);
        vertices1[1].Position = new Vector3(position.X, position.Y + size.Y, position.Z);
        vertices1[1].TextureCoordinate = new Vector2(1, 0);
        vertices1[2].Position = new Vector3(position.X + size.X, position.Y + size.Y, position.Z);
        vertices1[2].TextureCoordinate = new Vector2(0, 0);
        vertices1[3].Position = new Vector3(position.X + size.X, position.Y, position.Z);
        vertices1[3].TextureCoordinate = new Vector2(0, 1);
        //Another side

        vertices2[0].Position = new Vector3(position.X, position.Y, position.Z);
        vertices2[0].TextureCoordinate = new Vector2(0, 1);
        vertices2[1].Position = new Vector3(position.X, position.Y + size.Y, position.Z);
        vertices2[1].TextureCoordinate = new Vector2(0, 0);
        vertices2[2].Position = new Vector3(position.X, position.Y + size.Y, position.Z + size.Z);
        vertices2[2].TextureCoordinate = new Vector2(1, 0);
        vertices2[3].Position = new Vector3(position.X, position.Y, position.Z + size.Z);
        vertices2[3].TextureCoordinate = new Vector2(1, 1);
        //ANOTHER SIDE
        vertices3[0].Position = new Vector3(position.X + size.X, position.Y, position.Z + size.Z);
        vertices3[0].TextureCoordinate = new Vector2(0, 1);
        vertices3[1].Position = new Vector3(position.X + size.X, position.Y + size.Y, position.Z + size.Z);
        vertices3[1].TextureCoordinate = new Vector2(0, 0);
        vertices3[2].Position = new Vector3(position.X + size.X, position.Y + size.Y, position.Z);
        vertices3[2].TextureCoordinate = new Vector2(1, 0);
        vertices3[3].Position = new Vector3(position.X + size.X, position.Y, position.Z);
        vertices3[3].TextureCoordinate = new Vector2(1, 1);

        vertices4[0].Position = new Vector3(position.X, position.Y, position.Z + size.Z);
        vertices4[0].TextureCoordinate = new Vector2(0, 1);
        vertices4[1].Position = new Vector3(position.X, position.Y + size.Y, position.Z + size.Z);
        vertices4[1].TextureCoordinate = new Vector2(0, 0);
        vertices4[2].Position = new Vector3(position.X + size.X, position.Y + size.Y, position.Z + size.Z);
        vertices4[2].TextureCoordinate = new Vector2(1, 0);
        vertices4[3].Position = new Vector3(position.X + size.X, position.Y, position.Z + size.Z);
        vertices4[3].TextureCoordinate = new Vector2(1, 1);


        vertices5[0].Position = new Vector3(position.X, position.Y + size.Y, position.Z);
        vertices5[0].TextureCoordinate = new Vector2(0, 0);
        vertices5[1].Position = new Vector3(position.X + size.X, position.Y + size.Y, position.Z);
        vertices5[1].TextureCoordinate = new Vector2(1, 0);
        vertices5[2].Position = new Vector3(position.X + size.X, position.Y + size.Y, position.Z + size.Z);
        vertices5[2].TextureCoordinate = new Vector2(1, 1);
        vertices5[3].Position = new Vector3(position.X, position.Y + size.Y, position.Z + size.Z);
        vertices5[3].TextureCoordinate = new Vector2(0, 1);

        //bottom
        vertices6[0].Position = new Vector3(position.X, position.Y, position.Z);
        vertices6[0].TextureCoordinate = new Vector2(0, 0);
        vertices6[1].Position = new Vector3(position.X + size.X, position.Y, position.Z);
        vertices6[1].TextureCoordinate = new Vector2(1, 0);
        vertices6[2].Position = new Vector3(position.X + size.X, position.Y, position.Z + size.Z);
        vertices6[2].TextureCoordinate = new Vector2(1, 1);
        vertices6[3].Position = new Vector3(position.X, position.Y, position.Z + size.Z);
        vertices6[3].TextureCoordinate = new Vector2(0, 1);
        numTriangles = 4;
        indices = new short[numTriangles + 2];

        int i = 0;
        indices[i++] = 0;
        indices[i++] = 1;
        indices[i++] = 3;
        indices[i++] = 2;
}

我用于绘制块的代码是基本代码,但我不知道如何对其进行优化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//Game1.CS Code
GraphicsDevice.SamplerStates[0] = SamplerState.LinearCl // need to do this on reach     devices to allow non 2^n textures


        #region GamePlaying
        if (gameState == State.BREAKOUT || gameState == State.GAMEOVERBREAKOUT)
        {
            foreach (Block block in lastBlocks)
            {
                block.Draw(camera);
            }
            foreach (Block block in fourthBlocks)
            {
                block.Draw(camera);
            }
            foreach (Block block in thirdBlocks)
            {
                block.Draw(camera);
            }
            foreach (Block block in secondBlocks)
            {
                block.Draw(camera);
            }
            foreach (Block block in firstBlocks)
            {
                block.Draw(camera);
            }
            foreach (Block block in fifthBlocks)
            {
                block.Draw(camera);
            }
}

Block.CS绘图代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void Draw(Camera camera)
    {
        effect.View = camera.View;
        effect.Projection = camera.Projection;
        effect.World = rotationMatrix;


        foreach (EffectPass pass in effect.CurrentTechnique.Passes)
        {
            pass.Apply();
            graphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleStrip, vertices1, 0, 4, indices, 0, numTriangles);
            graphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleStrip, vertices2, 0, 4, indices, 0, numTriangles);
            graphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleStrip, vertices3, 0, 4, indices, 0, numTriangles);
            graphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleStrip, vertices4, 0, 4, indices, 0, numTriangles);
            graphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleStrip, vertices5, 0, 4, indices, 0, numTriangles);
            graphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleStrip, vertices6, 0, 4, indices, 0, numTriangles);
        }

    }

每个块调用DrawUserIndexedPrimitives是问题。这种绘制调用的原理是让您以很少的调用来绘制大量基元,而不是进行很多绘制得很少的调用。

您有两个选择:

  • 使用SpriteBatch绘制四边形(这将在内部为您执行批处理,因此您不必进行处理)。
  • 不必在每个Draw调用中直接调用DrawUserIndexedPrimitives,而是将顶点(和重新编号的索引)累积在一个临时缓冲区中,并在所有对象都累积后提交一次(针对一组索引,按效果)。
  • 希望这会有所帮助。