从教程上看,XNA一开始没有使用顶点缓存,不像D3D,一开始用的就是VertexBuffer。不过网上也有人说,D3D也可以不用VertexBuffer,有待学习。在XNA中如果不用VertexBuffer,就如上一个笔记中直接定义顶点,如VertexPositionColor,最后用GraphicsDevice的DrawUserPrimitive方法进行绘制。但是可以使用索引数组(还没到索引缓存出场)。
1: private void InitVertices()
2: {
3: vertices3 = new VertexPositionColor[9];
4:
5: vertices3[0] = new VertexPositionColor(new Vector3(0, 0, 0), Color.Red);
6: vertices3[1] = new VertexPositionColor(new Vector3(1, 0, 0), Color.Green);
7: vertices3[2] = new VertexPositionColor(new Vector3(2, 0, 1), Color.Blue);
8: vertices3[3] = new VertexPositionColor(new Vector3(0, 1, -1), Color.Orange);
9: vertices3[4] = new VertexPositionColor(new Vector3(1, 1, 0), Color.Olive);
10: vertices3[5] = new VertexPositionColor(new Vector3(2, 1, 0), Color.Magenta);
11: vertices3[6] = new VertexPositionColor(new Vector3(0, 2, 0), Color.Yellow);
12: vertices3[7] = new VertexPositionColor(new Vector3(1, 2, 1), Color.Tomato);
13: vertices3[8] = new VertexPositionColor(new Vector3(2, 2, -1), Color.Plum);
14:
15: }
上面定义了9个顶点,但要绘制8个三角形
1: private void InitIndices()
2: {
3: indices = new int[24];
4:
5: indices[0] = 0;
6: indices[1] = 3;
7: indices[2] = 1;
8:
9: indices[3] = 1;
10: indices[4] = 3;
11: indices[5] = 4;
12:
13: indices[6] = 1;
14: indices[7] = 4;
15: indices[8] = 5;
16:
17: indices[9] = 1;
18: indices[10] = 5;
19: indices[11] = 2;
20:
21: indices[12] = 3;
22: indices[13] = 6;
23: indices[14] = 7;
24:
25: indices[15] = 3;
26: indices[16] = 7;
27: indices[17] = 4;
28:
29: indices[18] = 4;
30: indices[19] = 7;
31: indices[20] = 5;
32:
33: indices[21] = 5;
34: indices[22] = 7;
35: indices[23] = 8;
36: }
最后
1: device.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, 9, indices, 0, 8);
------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------
尽管使用索引数组提高了效率,但每次调用Draw函数,顶点都会从系统内存传递到显卡中。通常,大部分数据没有变化,这意味着每帧重复传递了相同的数据。所以可以将顶点数据存储在显存中加速程序。从显存中将顶点数据传递到显卡速度要快得多。
通过创建顶点数组的VertexBuffer,可以将顶点数据复制到显存中。将顶点存储到显存后,就可以调用DrawPrimitives方法 (代替DrawUserPrimitives方法),这个方法从更快的显存中获取顶点。
注意:如果顶点几乎无需更新,那么这个方法可以极大地提高性能。但当处理被称为动态顶点数据(dynamic vertex data)时,这意味着顶点数据更新频繁,就应使用DynamicVertexBuffer
如果你还想将索引存储在显卡中,你应在创建VertexBuffer之后再创建一个IndexBuffer 。
1: private VertexBuffer vertexBuffer;
2: private IndexBuffer indexBuffer;
1: vertexBuffer = new VertexBuffer(device, VertexPositionColor.SizeInBytes * vertices3.Length, BufferUsage.WriteOnly);
2: vertexBuffer.SetData(vertices3, 0, vertices3.Length);
对于第一行的第三个参数,不是特别清楚。第二行就是将顶点数据加入到顶点缓存中
在在InitIndices中添加
1: indexBuffer = new IndexBuffer(device, typeof(int), indices.Length, BufferUsage.WriteOnly);
2: indexBuffer.SetData<int>(indices);
同样第二行将索引数组加入到索引缓存中
1: public void DrawUsingPresetEffect()
2: {
3: device.VertexDeclaration = vertDeclaration;
4: device.Vertices[0].SetSource(vertexBuffer[1], 0, VertexPositionColor.SizeInBytes);
5: device.Indices = indexBuffer;
6: device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, 9, 0, 8);
7: }
device.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionColor.SizeInBytes);就如同D3D中的SetStreamSource。对于Vertices[0]不是很理解。GraphicsDevice的Vertices属性,在SDK中是这样定义的:Gets the vertex stream collection
1: public VertexStreamCollection Vertices { get; }
Vertices[0]表示vertex stream 0 (zero) of the graphics device
之后就是设置索引数组device.Indices = indexBuffer