我一直在玩我的函数中的glDrawArrays。
由于某些原因,当使用glDrawArrays进行绘制时,我会下降大约400fps。
我打电话给我的打印功能2000次进行测试。
不确定为什么,因为我认为glDrawArrays可以做到这一点?
这是打印功能:
void Font::Print(const char* Text, int x, int y)
{
int sLen, Loop;
int Row, Col;
float U, V, U1, V1;
CurX = x;
CurY = y;
sLen = (int)strnlen(Text, BFG_MAXSTRING);
#ifdef ARRAYDRAW
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
#else
glBegin(GL_QUADS);
#endif
for (Loop = 0; Loop != sLen; ++Loop)
{
Row = (Text[Loop] - Base) / RowPitch;
Col = (Text[Loop] - Base) - Row * RowPitch;
U = Col * ColFactor;
V = Row * RowFactor;
U1 = U + ColFactor;
V1 = V + RowFactor;
#ifdef ARRAYDRAW
Vertex vert[] = {
CurX, CurY,
U, V1,
CurX + CellX, CurY,
U1, V1,
CurX + CellX, CurY + CellY,
U1, V,
CurX, CurY + CellY,
U, V
};
glVertexPointer(2, GL_INT, sizeof(Vertex), &vert[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vert[0].u);
glDrawArrays(GL_QUADS, 0, 4);
#else
glTexCoord2f(U, V1); glVertex2i(CurX, CurY);
glTexCoord2f(U1, V1); glVertex2i(CurX + CellX, CurY);
glTexCoord2f(U1, V); glVertex2i(CurX + CellX, CurY + CellY);
glTexCoord2f(U, V); glVertex2i(CurX, CurY + CellY);
#endif
CurX += Width[Text[Loop]];
}
#ifdef ARRAYDRAW
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
#else
glEnd();
#endi
答案 0 :(得分:4)
使用OpenGL的主要性能问题之一是OpenGL调用的数量。这就是glDrawArrays
变得方便的地方:如果你渲染一百万个三角形,那么大约有一百万个glVertex
和类似的调用,但仍然只有几个使用glDrawArrays
的调用
现在,在你的情况下,在循环中你只渲染一个四元组,并且两种方法的OpenGL调用数大致相同。这就是为什么你没有看到性能提升。
似乎你可以在没有任何循环的情况下做到这一点:
glVertexPointer(2, GL_INT, sizeof(Vertex), &vert[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vert[0].u);
glDrawArrays(GL_QUADS, 0, 4 * sLen); // <-- note
因此一次渲染所有四边形。我希望这会更高效。
更好的方法(在实践中实际使用的方法)是使用VBO's,因此只在GPU上复制顶点数据一次然后使用它。
答案 1 :(得分:1)
@lisyarus是对的。您的问题是您正在使用旨在使用缓冲区对象的接口,但您正在使用立即模式方法。
我在你对@lisyarus的评论中看到你说你不能使用缓冲区对象,因为你事先并不知道你的字符串。但是,这并非完全正确。我将在下面做出一些假设,这可能是也可能不正确,但它们应该指向正确的方向。
在您当前的示例中,您将为每个四边形发送一个绘图,表示字符串中的字符。基于此,我们至少知道这个字符串有多长。相反,让我们构建一个内存表示,然后批量绘制命令来处理字符串中的所有字符。
所以在开始时创建你的内存表示
Vertex* v = (Vertex*)malloc(sizeof(Vertex) * numOfVertexForString);
然后在你的循环中不发出任何GL
函数调用。而是构建上面的内存缓冲区。然后在你的循环之后创建一个VBO并在一次调用中绘制所有的四边形。
GLuint vbo;
GLGenBuffers(1, &vbo);
GLBindBuffer(GL_VERTEX_ARRAY, vbo);
GLBufferData(GL_VERTEX_ARRAY, sizeof(Vertex) * numOfVertexInString, v, GL_STATIC_DRAW);
然后,最后绘制缓冲区对象的内容。
glDrawArray(GL_QUADS, 0, 4 * sLen);
使用任何图形库时,重点是减少您拨打的电话数量。因为这些呼叫通过驱动程序路由它们很慢。更糟糕的是,如果您的数据不是图形库需要驱动程序的格式,如果被迫翻译它。你无法避免驱动程序中发生的事情,但你可以避免你发送的电话数量。