有效地绘制动态对象

Efficiently draw dynamic objects

本文关键字:对象 动态 绘制 有效地      更新时间:2023-10-16

在OpenGL上绘制动态移动对象的最佳方法是什么?

目前,我是这样做的:我有一个类Actor,在其中构造函数我生成一个缓冲区:

Actor::Actor(float x, float y): xpos(x),
                                ypos(y),
                                width(1),
                                height(1) {
    glGenBuffers(1, &buffer);
}

所有其他处理都在每一帧:

中完成
for(auto const &a: actors) {
    float x =  (a.xpos / tiles_x) * 2 - 1.0f + (1 / tiles_x);
    float y = -((a.ypos / tiles_y) * 2 - 1.0f + (1 / tiles_y));
    float w = a.width / (tiles_x);
    float h = a.height / (tiles_y);
    const GLfloat vertex[] {
        x - w, y - h, 1.0f,
        x - w, y + h, 1.0f,
        x + w, y + h, 1.0f,
        x - w, y - h, 1.0f,
        x + w, y - h, 1.0f,
        x + w, y + h, 1.0f,
    };
    glBindBuffer(GL_ARRAY_BUFFER, a.buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertex), vertex, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0,
                          3,
                          GL_FLOAT,
                          GL_FALSE,
                          0,
                          (void*)0);
    glDrawArrays(GL_TRIANGLES, 0, 6);
    glDisableVertexAttribArray(0);
}

我不是OpenGL专家,但对我来说它似乎相当低效。难道没有其他更有效的方法吗?

不推荐使用glTransform。更好的方法是使用着色器。

你真的不需要每帧发送所有的顶点到gpu。你的假设是正确的,它是低效的。当你创建你的演员,你创建网格一次,并发送所有的顶点到显卡。然后每个绘制帧,你所要做的就是绑定缓冲区并调用glDrawArrays。像这样。

要应用转换,你发送x,y,z偏移到顶点着色器,并将其与顶点相乘。这个网站提供了一些关于如何使用未被弃用的opengl功能来做到这一点的优秀教程。

如果你以相同的方式变换顶点,你只传递4x4变换矩阵的统一变量,这是每帧重新计算。

如果你需要独立地改变顶点,那么你必须改变属性数组并在每一帧中上传它,但是你应该考虑使用选项GL_DYNAMIC_DRAW。请参阅bufferData -用法参数差异了解更多信息。