[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [23112] branches/bb_dev_25/source/ gameengine/Rasterizer: BGE VBO - port to 2.5

Dalai Felinto dfelinto at gmail.com
Thu Sep 10 20:33:49 CEST 2009


Revision: 23112
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=23112
Author:   dfelinto
Date:     2009-09-10 20:33:49 +0200 (Thu, 10 Sep 2009)

Log Message:
-----------
BGE VBO - port to 2.5

20409 - Patch:[#17523] BGE VBO patch by Samuel Anjam (toonist) 
20411 - Missing files from last commit (Patch:[ #17523] BGE VBO patch by Samuel Anjam (toonist))
20549 - Don' t create VBO at the same time as Display list.
20662 - Fix for: Normals are not being updated in VBO.  
20663 - BGE VBO updates

To do:
1) check if we need to update the tangent matrix as well
2) create the buffers only when necessary

"The buffers for all the texture coordinates are [currently] created unconditionally even if some are not used during the render. Which buffer is used depends on the wireframe, GLSL/multitexture and the texture coordinate used by the material. RAS_VAOpenGLRasterizer::TexCoordPtr(), RAS_VAOpenGLRasterizer::IndexPrimitivesMulti() and RAS_VAOpenGLRasterizer::IndexPrimitives() show the buffers that are actually bound to. Only those buffers should be created."

Note:
VBO doesn't necessarly means better performance than Display List. They can perform faster in Skinned objects (where DisplayList is not being used). But it uses less memory than DisplayList and is a more modern Game Engine technology.

Thanks again to Samuel Anjam (toonist) for the original patch.

Modified Paths:
--------------
    branches/bb_dev_25/source/gameengine/Rasterizer/RAS_IRasterizer.h
    branches/bb_dev_25/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
    branches/bb_dev_25/source/gameengine/Rasterizer/RAS_MaterialBucket.h
    branches/bb_dev_25/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
    branches/bb_dev_25/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
    branches/bb_dev_25/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h

Modified: branches/bb_dev_25/source/gameengine/Rasterizer/RAS_IRasterizer.h
===================================================================
--- branches/bb_dev_25/source/gameengine/Rasterizer/RAS_IRasterizer.h	2009-09-10 17:21:36 UTC (rev 23111)
+++ branches/bb_dev_25/source/gameengine/Rasterizer/RAS_IRasterizer.h	2009-09-10 18:33:49 UTC (rev 23112)
@@ -49,6 +49,7 @@
 
 class RAS_ICanvas;
 class RAS_IPolyMaterial;
+class RAS_MeshSlot;
 
 typedef vector<unsigned short> KX_IndexArray;
 typedef vector<RAS_TexVert> KX_VertexArray;
@@ -410,6 +411,10 @@
 
 	virtual void	SetBlendingMode(int blendmode)=0;
 	virtual void	SetFrontFace(bool ccw)=0;
+
+	// updates mesh data (vbo addition)
+	virtual void UpdateMeshSlotData(class RAS_MeshSlot *ms,
+		const bool &anim, const bool &zsort)=0;
 	
 	
 #ifdef WITH_CXX_GUARDEDALLOC
@@ -421,4 +426,3 @@
 
 #endif //__RAS_IRASTERIZER
 
-

Modified: branches/bb_dev_25/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp
===================================================================
--- branches/bb_dev_25/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp	2009-09-10 17:21:36 UTC (rev 23111)
+++ branches/bb_dev_25/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp	2009-09-10 18:33:49 UTC (rev 23112)
@@ -40,6 +40,29 @@
 #include "RAS_MeshObject.h"
 #include "RAS_Deformer.h"	// __NLA
 
+/* vertex buffer object slot */
+
+#include "RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.h"
+
+RAS_VboSlot::RAS_VboSlot(RAS_VAOpenGLRasterizer *rasty)
+{
+	m_rasty = rasty;
+	m_vertVbo = 0;
+	m_indexVbo = 0;
+	m_normalVbo = 0;
+	m_tangentVbo = 0;
+	m_colorVbo = 0;
+	m_verts = 0;
+	m_texCoordVbo[0] = 0;
+	m_texCoordVbo[1] = 0;
+};
+
+RAS_VboSlot::~RAS_VboSlot()
+{
+	m_rasty->ClearVboSlot(this);
+	if(m_verts) delete []m_verts;
+}
+
 /* mesh slot */
 
 RAS_MeshSlot::RAS_MeshSlot() : SG_QList()
@@ -158,6 +181,7 @@
 
 		it.vertex = &it.array->m_vertex[0];
 		it.index = &it.array->m_index[startindex];
+		it.vboslot = it.array->m_vboSlot;
 		it.startvertex = startvertex;
 		it.endvertex = endvertex;
 		it.totindex = endindex-startindex;
@@ -189,6 +213,7 @@
 
 		it.vertex = &it.array->m_vertex[0];
 		it.index = &it.array->m_index[startindex];
+		it.vboslot = it.array->m_vboSlot;
 		it.startvertex = startvertex;
 		it.endvertex = endvertex;
 		it.totindex = endindex-startindex;
@@ -210,6 +235,7 @@
 	RAS_DisplayArrayList::iterator it;
 	RAS_DisplayArray *darray = NULL;
 	
+	// find an array which doesn't contain the max amount of indices/vertices
 	for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) {
 		darray = *it;
 
@@ -602,6 +628,9 @@
 	if(IsZSort() && rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID)
 		ms.m_mesh->SortPolygons(ms, cameratrans*MT_Transform(ms.m_OpenGLMatrix));
 
+	rasty->UpdateMeshSlotData(&ms, (ms.m_pDeformer != 0),
+		(IsZSort() && rasty->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID));
+
 	rendertools->PushMatrix();
 	if (!ms.m_pDeformer || !ms.m_pDeformer->SkipVertexTransform())
 	{

Modified: branches/bb_dev_25/source/gameengine/Rasterizer/RAS_MaterialBucket.h
===================================================================
--- branches/bb_dev_25/source/gameengine/Rasterizer/RAS_MaterialBucket.h	2009-09-10 17:21:36 UTC (rev 23111)
+++ branches/bb_dev_25/source/gameengine/Rasterizer/RAS_MaterialBucket.h	2009-09-10 18:33:49 UTC (rev 23112)
@@ -72,6 +72,35 @@
 class RAS_MaterialBucket;
 struct DerivedMesh;
 
+/* Vertex Buffer Object data used for OpenGL drawing */
+
+class RAS_VAOpenGLRasterizer;
+
+class RAS_VboSlot
+{
+public:
+	RAS_VAOpenGLRasterizer *m_rasty;
+	/* vertex buffer object handles for drawing */
+	unsigned int m_vertVbo;
+	unsigned int m_indexVbo;
+	unsigned int m_normalVbo;
+	unsigned int m_tangentVbo;
+	unsigned int m_colorVbo;
+	/* allow up to four texture coordinate sets */
+	unsigned int m_texCoordVbo[2];
+	/* m_verts only exists if the mesh is deformable.
+	glBufferSubDataARB is used for updating the vertices
+	and this function doesn't take stride parameter, so all of
+	the vertice data has to be passed to an new array and THEN
+	uploaded to the vbo. glMapBuffer could be an alternative,
+	but it doesn't return untill the GPU has processed the previous
+	data, so this might be the fastes way. */
+	float *m_verts;
+
+	RAS_VboSlot(RAS_VAOpenGLRasterizer *rasty);
+	~RAS_VboSlot();
+};
+
 /* An array with data used for OpenGL drawing */
 
 class RAS_DisplayArray
@@ -82,12 +111,16 @@
 	/* LINE currently isnt used */
 	enum { LINE = 2, TRIANGLE = 3, QUAD = 4 } m_type;
 	//RAS_MeshSlot *m_origSlot;
+	RAS_VboSlot *m_vboSlot;
 	
 	/* Number of RAS_MeshSlot using this array */
 	int m_users;
 
 	enum { BUCKET_MAX_INDEX = 65535 };
 	enum { BUCKET_MAX_VERTEX = 65535 };
+
+	RAS_DisplayArray() : m_vboSlot(0) {};
+	~RAS_DisplayArray() {if(m_vboSlot) delete m_vboSlot;}
 };
 
 /* Entry of a RAS_MeshObject into RAS_MaterialBucket */
@@ -142,6 +175,7 @@
 	struct iterator {
 		RAS_DisplayArray *array;
 		RAS_TexVert *vertex;
+		RAS_VboSlot *vboslot;
 		unsigned short *index;
 		size_t startvertex;
 		size_t endvertex;

Modified: branches/bb_dev_25/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h
===================================================================
--- branches/bb_dev_25/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h	2009-09-10 17:21:36 UTC (rev 23111)
+++ branches/bb_dev_25/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h	2009-09-10 18:33:49 UTC (rev 23112)
@@ -296,6 +296,10 @@
 	void *operator new( unsigned int num_bytes) { return MEM_mallocN(num_bytes, "GE:RAS_OpenGLRasterizer"); }
 	void operator delete( void *mem ) { MEM_freeN(mem); }
 #endif
+
+	// updates mesh data (vbo addition)
+	virtual void	UpdateMeshSlotData(class RAS_MeshSlot *ms,
+		const bool &anim, const bool &zsort) {};
 };
 
 #endif //__RAS_OPENGLRASTERIZER

Modified: branches/bb_dev_25/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp
===================================================================
--- branches/bb_dev_25/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp	2009-09-10 17:21:36 UTC (rev 23111)
+++ branches/bb_dev_25/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp	2009-09-10 18:33:49 UTC (rev 23112)
@@ -103,6 +103,178 @@
 	RAS_OpenGLRasterizer::Exit();
 }
 
+void RAS_VAOpenGLRasterizer::ClearVboSlot(class RAS_VboSlot *slot)
+{
+	if(!GLEW_ARB_vertex_buffer_object) return;
+	if(slot->m_verts) delete slot->m_verts;
+	if(slot->m_vertVbo) glDeleteBuffers(1, &slot->m_vertVbo);
+	if(slot->m_indexVbo) glDeleteBuffers(1, &slot->m_indexVbo);
+	if(slot->m_normalVbo) glDeleteBuffers(1, &slot->m_normalVbo);
+	if(slot->m_tangentVbo) glDeleteBuffers(1, &slot->m_tangentVbo);
+	if(slot->m_colorVbo) glDeleteBuffers(1, &slot->m_colorVbo);
+	if(slot->m_texCoordVbo[0]) glDeleteBuffers(1, &slot->m_texCoordVbo[0]);
+	if(slot->m_texCoordVbo[1]) glDeleteBuffers(1, &slot->m_texCoordVbo[1]);
+
+	slot->m_verts = 0;
+	slot->m_vertVbo = 0;
+	slot->m_indexVbo = 0;
+	slot->m_normalVbo = 0;
+	slot->m_tangentVbo = 0;
+	slot->m_colorVbo = 0;
+	slot->m_texCoordVbo[0] = 0;
+	slot->m_texCoordVbo[1] = 0;
+}
+
+void RAS_VAOpenGLRasterizer::InitVboSlot(class RAS_DisplayArray* array, class RAS_MeshSlot *ms)
+{
+	if(array->m_vertex.size() == 0 || array->m_index.size() == 0
+		|| !GLEW_ARB_vertex_buffer_object) return;
+	// clean up any previous data before creating a new slot
+	if(array->m_vboSlot) delete array->m_vboSlot;
+	array->m_vboSlot = new RAS_VboSlot(this);
+	/* uploading data to vertex buffer objects doesn't allow
+	stride so we have to grab the data from RAS_TexVert and
+	initialize new arrays which we then use to upload the
+	data to the vbos*/
+	float *normals = 0;
+	float *tangents = 0;
+	float *texCoords0 = 0;
+	float *texCoords1 = 0;
+	unsigned char *colors = 0;
+	bool isColors = glIsEnabled(GL_COLOR_ARRAY);
+	array->m_vboSlot->m_verts = new float[array->m_vertex.size()*3];
+	normals = new float[array->m_vertex.size()*3];
+	tangents = new float[array->m_vertex.size()*4];
+	texCoords0 = new float[array->m_vertex.size()*2];
+	texCoords1 = new float[array->m_vertex.size()*2];
+	colors = new unsigned char[array->m_vertex.size()*4];
+	// upload the data
+	unsigned int num0 = 0;
+	unsigned int num1 = 0;
+	unsigned int num2 = 0;
+	unsigned int vertnum = 0;
+	for(vertnum = 0; vertnum < array->m_vertex.size(); vertnum++)
+	{
+		memcpy(&array->m_vboSlot->m_verts[num0], array->m_vertex[vertnum].getXYZ(), sizeof(float)*3);
+		memcpy(&normals[num0], array->m_vertex[vertnum].getNormal(), sizeof(float)*3);
+		memcpy(&texCoords0[num1], array->m_vertex[vertnum].getUV1(), sizeof(float)*2);
+		memcpy(&texCoords1[num1], array->m_vertex[vertnum].getUV2(), sizeof(float)*2);
+		memcpy(&tangents[num2], array->m_vertex[vertnum].getTangent(), sizeof(float)*4);
+		memcpy(&colors[num2], array->m_vertex[vertnum].getRGBA(), sizeof(int));
+		num0+=3;
+		num1+=2;
+		num2+=4;
+	}
+	// create the vertex buffer objects
+	glGenBuffersARB(1, &array->m_vboSlot->m_vertVbo);
+	glBindBufferARB(GL_ARRAY_BUFFER_ARB, array->m_vboSlot->m_vertVbo);
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(float)*array->m_vertex.size()*3,
+		array->m_vboSlot->m_verts, GL_DYNAMIC_DRAW_ARB);
+//	glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+	glGenBuffersARB(1, &array->m_vboSlot->m_normalVbo);
+	glBindBufferARB(GL_ARRAY_BUFFER_ARB, array->m_vboSlot->m_normalVbo);
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(float)*array->m_vertex.size()*3,
+		normals, GL_DYNAMIC_DRAW_ARB);
+//	glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+	glGenBuffersARB(1, &array->m_vboSlot->m_tangentVbo);
+	glBindBufferARB(GL_ARRAY_BUFFER_ARB, array->m_vboSlot->m_tangentVbo);
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(float)*array->m_vertex.size()*4,
+		tangents, GL_STATIC_DRAW_ARB);
+//	glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+	glGenBuffersARB(1, &array->m_vboSlot->m_texCoordVbo[0]);
+	glBindBufferARB(GL_ARRAY_BUFFER_ARB, array->m_vboSlot->m_texCoordVbo[0]);
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(float)*array->m_vertex.size()*2,
+		texCoords0, GL_STATIC_DRAW_ARB);
+//	glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+	glGenBuffersARB(1, &array->m_vboSlot->m_texCoordVbo[1]);
+	glBindBufferARB(GL_ARRAY_BUFFER_ARB, array->m_vboSlot->m_texCoordVbo[1]);
+	glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(float)*array->m_vertex.size()*2,
+		texCoords1, GL_STATIC_DRAW_ARB);
+//	glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+	if(isColors)
+	{

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list