5.5 将经常更新的顶点数据存储在DynamicVertexBuffer

问题

你需要频繁更新顶点数据,如果使用VertexBuffer的SetData方法会拖慢程序。

解决方案

如果你计划频繁更新顶点数据,应该使用DynamicVertexBuffer而不是VertexBuffer。

这会让数据不是存储在最快的显存中,而是更容易处理的某些内存中。所以,这样做会让性能有一点降低,但在VertexBuffer中频繁地改变数据会让性能得到极大地提高。

对于VertexBuffer,只要显卡被要求切换任务(例如,使用Alt+Tab切换程序),DynamicVertexBuffer中的内容必须被重载,你可以通过订阅到DynamicVertexBuffer的ContentLost事件上实现这个功能。

工作原理

DynamicVertexBuffer的工作原理与VertexBuffer很像。首先需要一个顶点数组,如下所示:

private void InitVertices()
{
    myVertexDeclaration = new VertexDeclaration(device, VertexPositionTexture.VertexElements); 
    vertices = new VertexPositionTexture[6]; 
    int i = 0; 
    
    vertices[i++] = new VertexPositionTexture(new Vector3(-5.0f, -3, -1), new Vector2(-0.5f, 1.5f)); 
    vertices[i++] = new VertexPositionTexture(new Vector3(-2.5f, 5, -1), new Vector2(0.5f, -1.5f)); 
    vertices[i++] = new VertexPositionTexture(new Vector3(0, -3, -1), new Vector2(1.5f, 1.5f)); 
    vertices[i++] = new VertexPositionTexture(new Vector3(0, -3, -1), new Vector2(-0.5f, 1.5f)); 
    vertices[i++] = new VertexPositionTexture(new Vector3(2.5f, 5, -1), new Vector2(0.5f, -1.5f)); 
    vertices[i++] = new VertexPositionTexture(new Vector3(5.0f, -3, -1), new Vector2(1.5f, 1.5f)); 
    
    dynVertBuffer = new DynamicVertexBuffer(device, VertexPositionTexture.SizeInBytes * vertices.Length, BufferUsage.WriteOnly); 
    dynVertBuffer.SetData(vertices, 0, vertices.Length, SetDataOptions.NoOverwrite); 
    dynVertBuffer.ContentLost +=new EventHandler(dynVertBuffer_ContentLost); 
} 

创建DynamicVertexBuffer接受和创建VertexBuffer一样的参数,但SetData方法接受一个新的加强的参数,我会在下面讲到。最后一行代码是新的,如果显卡被要求处理另一个程序,设备会丢失,DynamicVertexBuffer的内容也会丢失。所以你要在DynamicVertexBuffer 的ContentLost事件上订阅一个方法。只要DynamicVertexBuffer丢失了内容就会引发ContentLost 事件,对应的方法就会被调用,这个方法会重载DynamicVertexBuffer中的内容。本例中,你将dynVertBuffer_ContentLost方法订阅到事件。

当然你还要定义这个方法,在这个方法中重载缓冲的内容:

private void dynVertBuffer_ContentLost(object sender, EventArgs e) 
{
    dynVertBuffer.SetData(vertices, 0, vertices.Length, SetDataOptions.NoOverwrite); 
} 

注意:这需要本地处理顶点数据。因为只有当顶点数据变化地很频繁时才使用DynamixVertexBuffer,所以首先要保证数据没有问题,记住你永远不会从(Dynamic)VertexBuffer中读取数据。

当进行到绘制这步时,DynamicVertexBuffer的工作方式与VertexBuffer是相同的。

性能考虑:DynamicVertexBuffer.SetData方法

因为当你想频繁更新数据时才会使用DynamicVertexBuffer,所以你会经常使用SetData 方法。因此DynamicVertexBuffer的SetData方法还接受一个额外的参数SetDataOptions。

这个参数让你可以指定一些选项可以提高程序的速度。默认情况下,当你想覆盖显存中的内容时,因为不支持同时读写,显卡无法从显存中读取数据。当你把大量数据写至内存时会导致显卡的绘制过程中止,这是因为显卡要等待你的复制过程结束。但是,有两个方法可以让你确保显卡不会等待复制操作结束。你可以使用SetDataOptions 参数,下面是可选项:


发布时间:2009/5/30 上午11:43:27  阅读次数:5528

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号