在OpenGL中快速绘制许多相同的对象

时间:2012-02-19 19:18:49

标签: c++ opengl

所以我正在开发一款游戏,我需要绘制很多相同的对象。相同的形状,相同的尺寸,相同的颜色,只是不同的位置。

现在我的设置是这样的。

我有一些类Renderer,其中想要在屏幕上绘制的对象可以调用static void addVertex(float x, float y, float z);,它将顶点存储到std::vector。当每个人都完成时,static void draw();中的Renderer被调用,其中所有内容都被填充到VBO中并被绘制到屏幕上。

绘制看起来像这样:

void Renderer::draw() {
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, _quadID);
    glBufferSubDataARB(GL_QUADS, 0, _vertexBuffer.dataSize(), _vertexBuffer.toArray());

    glColorPointer(4, GL_FLOAT, 0, _colorBuffer.toArray());

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    glVertexPointer(3, GL_FLOAT, 0, _vertexBuffer.toArray());

    glDrawArrays(GL_QUADS, 0, (_vertexBuffer.size() / 3));
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);

    glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);

    _vertexBuffer.clear();
    _colorBuffer.clear();
}

其中_vertexBuffer_colorBuffer属于template <class T> Buffer类,而我的目的或多或少是托管std::vector<T>

通过这种设置,我可以在开始放慢速度之前在屏幕上获得大约300个内容。现在一切都是GL_QUAD。请记住,我对OpenGL有点新鲜,如果上述内容令人尴尬,我很抱歉。

如何根据类似的多边形进行改进?

2 个答案:

答案 0 :(得分:21)

在〜现代硬件上,instancing是可行的方法。

您的想法是将几何体发送到GPU一次(一次绘制调用),指定要绘制的实例数(primCount参数)。

然后在顶点着色器中,您可以使用内部输入变量gl_InstanceID来了解正在渲染的实例,然后对其使用适当的变换。这种方法意味着您应该在顶点着色器中为所有实例提供转换,例如在Uniform Buffer Object中。

编辑:glVertexAttribDivisor功能与实例化非常有用;它基本上允许一些每顶点属性和一些每个实例属性。

答案 1 :(得分:1)

OpenGL中有一些很棒的东西,名为Display list。 NeHe的制作有tutorial,应提供所有必要的信息和示例。但基本上是:

GLuint displayList; // This should be class attribute
displayList = glGenLists(1);    
glNewList(displayList,GL_COMPILE);
Renderer::draw();
glEndList();

在真正的抽奖方法中:

glCallList( displayList);

每次添加/删除某些内容时,请不要忘记实现预编译的显示列表。