【发布时间】:2014-05-04 06:27:34
【问题描述】:
我有相当大的 C++ 对象,它们将网格数据加载到内存中,然后根据 OnDisplay 回调进行绘制。
问题是刷新率真的很慢,我怀疑是因为我的代码写得不好。
无论如何;这是我的类的样子(显示的函数原型让您了解我的类是如何设置的)。
我想知道的是,如果我的大多数 VBO 没有改变并跳过我的开始和结束绘制函数,是否可以在内存中以某种方式调用“glDrawElements”函数,如下所示.
或者,甚至更好,
如果有一个神奇的 OpenGL 函数,我可以调用它,通过一次,OpenGL 可以渲染我所有未更改的缓冲区 ID,我可以专注于绘制已更改的缓冲区 ID 和相机?
大多数情况下,我只会让相机在场景中移动。
我根据教程和文档设置了这些功能,因此我知道它们可以工作;我只是想加快绘图速度,尤其是当我加载的网格大小为 100MB 以上时。
首先,这是我的类原型:
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.
};
这是我的初始化函数:
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;
}
这是我的 BeginDraw 函数:
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);
}
}
我的绘图功能 ...
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;
}
}
}
最后是我的结束绘制函数......
void VBOMesh::EndDraw() const
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
【问题讨论】:
-
您的代码几乎无法阅读。在某个地方, 被 HTML
&lt;和&gt;取代。我建议重新粘贴它,因为您的模板代码现在是乱码。 -
@AndonM.Coleman 谢谢;我什至没有注意到这一点。进行了修改。