OpenGL - Drawing Large Amounts of Information stored in VBO's ...

Saturday, May 3, 2014

I have fairly large C++ objects which load mesh data into memory and then draws based on an OnDisplay callback.


The problem is that the refresh rate is really slow which I suspect is because my code is poorly written.


Anyway; here is what my class looks like (function prototypes shown to give you an idea of how my class is set up).


What I want to know is if it is possible to just call the "glDrawElements" function somehow on what is in memory if most of my VBOs haven't changed and skip my Begin and end draw functions as shown below.


OR, even better,


If there is a magic OpenGL function I can call that, with one pass, OpenGL can render all of my unchanged Buffer IDs and I can simply focus on drawing the ones that have changed and the camera?


Mostly I will just have the camera moving through the scene.


I set these functions up based on tutorials and documentation so I know they work; I just want to speed up the drawing, especially when the meshes I am loading in are 100MB + in size.


Thank you so much for your time and any assistance you can provide.


First, here is my class prototype:



class MyMeshData
{
public:
MyMeshData();
~MyMeshData();
// Save up data into GPU buffers.
bool Initialize(const MeshDataFromFileClass * StaticMeshData);
// Update vertex positions for deformed
meshes. void UpdateVertexPosition(const
MeshDataFromFileClass * StaticMeshData, const MyVector4Class * pVertices)
const;
// Bind buffers, set vertex arrays, turn on lighting and
texture. void BeginDraw(ShadingMode
pShadingMode) const;
// Draw all the faces with
specific material with given shading mode. void
Draw(int pMaterialIndex, ShadingMode pShadingMode)
const;
// Unbind buffers, reset vertex arrays,
turn off lighting and texture. void EndDraw() const;
// Get the count of material groups
int GetSubMeshCount() const {
return mSubMeshes.GetCount();
}
private: enum
{
VERTEX_VBO,
NORMAL_VBO,
UV_VBO,
INDEX_VBO,
VBO_COUNT,
}
;
// For every material, record the offsets in every VBO and
triangle counts struct SubMesh
{
SubMesh() : IndexOffset(0),
TriangleCount(0) {
}
int
IndexOffset;
int
TriangleCount;
}
;
GLuint
mVBONames[VBO_COUNT];
MyMeshArray<
SubMesh*>
mSubMeshes;
bool
mHasNormal;
bool mHasUV;
bool
mAllByControlPoint;
// Save data in VBO by control point or by polygon
vertex.
}
;


And here is my Initialize Function:



bool Initialize(const MeshDataFromFileClass *StaticMeshData)
{
[...] /* Earlier
code that retrieves data from file removed. Only
the point where the data is transferred to the GPU is
shown. */ // Create
VBOs glGenBuffers(VBO_COUNT, mVBONames);
// Save vertex attributes into
GPU glBindBuffer(GL_ARRAY_BUFFER,
mVBONames[VERTEX_VBO]);
glBufferData(GL_ARRAY_BUFFER,
lPolygonVertexCount * VERTEX_STRIDE * sizeof(float), lVertices,
GL_STATIC_DRAW);
delete [] lVertices;
if
(mHasNormal) {
glBindBuffer(GL_ARRAY_BUFFER,
mVBONames[NORMAL_VBO]);
glBufferData(GL_ARRAY_BUFFER,
lPolygonVertexCount * NORMAL_STRIDE * sizeof(float), lNormals,
GL_STATIC_DRAW);
delete []
lNormals;
}
if
(mHasUV) {
glBindBuffer(GL_ARRAY_BUFFER,
mVBONames[UV_VBO]);
glBufferData(GL_ARRAY_BUFFER,
lPolygonVertexCount * UV_STRIDE * sizeof(float), lUVs,
GL_STATIC_DRAW);
delete []
lUVs;
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
mVBONames[INDEX_VBO]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
lPolygonCount * TRIANGLE_VERTEX_COUNT * sizeof(unsigned int), lIndices,
GL_STATIC_DRAW);
delete [] lIndices;
}


Here is my BeginDraw Function:



void MyMeshData::BeginDraw(ShadingMode pShadingMode) const{
glBindBuffer(GL_ARRAY_BUFFER,
mVBONames[VERTEX_VBO]);
/* glVertexPointer(VERTEX_STRIDE,
GL_FLOAT, 0,
0);
glEnableClientState(GL_VERTEX_ARRAY);
*/ glEnableVertexAttribArray(0);
glVertexAttribPointer(0,
VERTEX_STRIDE, GL_FLOAT, GL_FALSE, 0, 0);
// Set normal array. if
(mHasNormal && pShadingMode ==
SHADING_MODE_SHADED) {
glBindBuffer(GL_ARRAY_BUFFER,
mVBONames[NORMAL_VBO]);
glNormalPointer(GL_FLOAT, 0, 0);
glEnableClientState(GL_NORMAL_ARRAY);
}
// Set UV
array. if (mHasUV && pShadingMode ==
SHADING_MODE_SHADED)
{
glBindBuffer(GL_ARRAY_BUFFER,
mVBONames[UV_VBO]);
glTexCoordPointer(UV_STRIDE, GL_FLOAT, 0,
0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,
mVBONames[INDEX_VBO]);
if (pShadingMode !=
SHADING_MODE_SHADED)
{
glColor4fv(DEFAULT_WIREFRAME_COLOR);
}
}


My Draw function ...



void MyMeshData::Draw(int pMaterialIndex, ShadingMode pShadingMode)
const{
// Where to start.
GLsizei lOffset = mSubMeshes[pMaterialIndex]->
IndexOffset * sizeof(unsigned
int);
if ( pShadingMode ==
SHADING_MODE_SHADED) {
const GLsizei
lElementCount = mSubMeshes[pMaterialIndex]->
TriangleCount *
3;
glDrawElements(GL_TRIANGLES, lElementCount, GL_UNSIGNED_INT,
reinterpret_cast<
const GLvoid *>
(lOffset));
}
else
{
for (int lIndex = 0;
lIndex <
mSubMeshes[pMaterialIndex]->
TriangleCount;
++lIndex) {
glDrawElements(GL_LINE_LOOP, TRIANGLE_VERTEX_COUNT, GL_UNSIGNED_INT,
reinterpret_cast<
const GLvoid
*>
(lOffset));
lOffset += sizeof(unsigned int) *
TRIANGLE_VERTEX_COUNT;
}
}
}


And finally my End Draw Function....



void VBOMesh::EndDraw() const{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}






http://ift.tt/1fGRyB2