我有一组简单的二维对象,主要由两个三角形组成。尽管对象非常简单,但每个对象都是使用模板操作绘制的,因此每个对象都需要自己drawTriangles()
调用。
存储和处理这些对象及其顶点和索引缓冲区的最佳方法是什么?
我可以想到几种不同的方法:
在启动时创建一个大的顶点和索引缓冲区并将每个对象添加到其中,例如:
public function initialize():void{ for each(object in objectList){ vertexData.push(object.vertices); indexData.push(triangle1, triangle2); } indices = context3D.createIndexBuffer( numTriangles * 3 ); vertices = context3D.createVertexBuffer( numVertices, dataPerVertex ); indices.uploadFromVector( indexData, 0, numIndices ); vertices.uploadFromVector( vertexData, 0, numVertices ); }
在所有对象的渲染循环期间,检查哪些对象在屏幕上可见并更新它们的顶点。然后重新上传整个顶点缓冲区。然后循环遍历可见对象并使用单独调用绘制每个对象的三角形
drawTriangles()
public function onRender():void{ for each(object in objectList){ if(object.visibleOnScreen) object.updateVertexData(); } vertices.uploadFromVector( vertexData, 0, numVertices ); for each(object in objectsOnScreen){ drawTriangles(indices, object.vertexDataOffset, object.numTriangles); } }
除了仅在需要时重新上传每个对象的顶点数据之外,您还可以执行类似于数字 1 的操作:
public function onRender():void{ for each(object in objectList){ if(object.visibleOnScreen){ if(object.hasChanged) vertices.uploadFromVector( vertexData, object.vertexDataOffset, object.numTriangles ); drawTriangles(indices, object.vertexDataOffset, object.numTriangles); } } }
您还可以创建一个新的顶点缓冲区,该缓冲区仅包含每帧上的可见对象:
public function onRender():void{ for each(object in objectList){ if(object.visibleOnScreen){ vertexData.push(object.vertices); indexData.push(triangle1, triangle2); } } indices = context3D.createIndexBuffer( numTriangles * 3 ); vertices = context3D.createVertexBuffer( numVertices, dataPerVertex ); indices.uploadFromVector( indexData, 0, numIndices ); vertices.uploadFromVector( vertexData, 0, numVertices ); for each(object in objectsOnScreen){ drawTriangles(indices, object.vertexDataOffset, object.numTriangles); } }
另一种选择是为每个对象创建单独的顶点缓冲区:
public function initialize():void{ for each(object in objectList){ object.indices = context3D.createIndexBuffer( object.numTriangles * 3 ); object.vertices = context3D.createVertexBuffer( object.numVertices, dataPerVertex ); } } public function onRender():void{ for each(object in objectList){ if(object.visibleOnScreen){ if(object.hasChanged) object.vertices.uploadFromVector( object.vertexData, 0, object.numTriangles ); drawTriangles(indices, 0, object.numTriangles); } } }
我可以想象选项 1 会很慢,因为每个帧都需要上传整个顶点缓冲区。
选项 2 的优点是它只需要上传已更改但可能会遭受多次调用的顶点数据uploadFromVector
。
更新
我看过 Starling 框架源代码,特别是QuadBatch
类: http:
//gamua.com/starling/
https://github.com/PrimaryFeather/Starling-Framework
似乎所有顶点都是事先手动转换的,并且每帧都会重建和上传整个顶点缓冲区。