C++ 如何更快地绘制多个纹理四边形,并保留glScissor(或类似的东西)?

C++ 如何更快地绘制多个纹理四边形,并保留glScissor(或类似的东西)?,c++,performance,opengl,C++,Performance,Opengl,我正在使用OpenGL4和C++11 目前,我使用带有独立VBO和IBO的独立VAO对GLDrawerElements进行了大量单独调用 我这样做是因为纹理坐标会随着每个坐标的变化而变化,而我的顶点数据以纹理坐标为特征。我知道在这个顶点数据中有一些冗余的位置信息;但是,它总是-1,-1,1,1,因为我在顶点着色器中使用平移和缩放矩阵来定位和缩放顶点数据 VAO、VBO、IBO、位置和比例矩阵以及纹理ID存储在对象中。它是每个四边形一个对象 当前,某些图形将如下所示: 通过(glpaurement

我正在使用OpenGL4和C++11

目前,我使用带有独立VBO和IBO的独立VAO对
GLDrawerElements
进行了大量单独调用

我这样做是因为纹理坐标会随着每个坐标的变化而变化,而我的顶点数据以纹理坐标为特征。我知道在这个顶点数据中有一些冗余的位置信息;但是,它总是-1,-1,1,1,因为我在顶点着色器中使用平移和缩放矩阵来定位和缩放顶点数据

VAO、VBO、IBO、位置和比例矩阵以及纹理ID存储在对象中。它是每个四边形一个对象

当前,某些图形将如下所示:

  • 通过(
    glpaurements(GL\u三角形,6,GL\u UNSIGNED\u INT,0)
    )绘制四元对象。绑定的VBO仅为-1,-1,1,1,IBO为我绘制了一个四边形。绑定的VBO包含公共纹理的纹理坐标(用于对所有绘制的四边形进行纹理处理的相同纹理)。着色器上的矩阵变换将其定位
  • 对另一个四边形对象重复此操作
  • glEnable(GL\u-SCISSOR\u测试)
    被调用,预览四元组的位置信息用于调用
    glScissor
  • 绘制下一个四边形对象;实际上只显示从上一个四边形中可见的部分
  • 绘制另一个四边形对象
  • 我现在的表现是可以接受的,但我希望它更快,因为我只是触及了我的想法的表面。所以我在考虑优化。到目前为止,我已经读到我应该:

  • 从顶点数据中删除位置信息,并保持纹理坐标。而是在绘制四边形的开始处绑定一个位置VBO,以便所有四边形都使用它

    但我不确定这是怎么回事?因为我一次只能激活一个VBO

    然后我是否需要调用
    glBufferSubData
    并在绘制每个四边形之前更新纹理坐标?这是性能更好还是更差(为每个对象调用
    glbinvertexarray
    ,还是调用
    glBufferSubData

    如果我仍然将位置和比例作为矩阵传递给着色器,我会利用这个机会更新顶点的位置信息以及纹理坐标吗?哪个更快

  • 创建一个带或不带IBO的大型VBO,并更新其中每个四边形的位置(而不是使用变换和缩放矩阵)的顶点数据。这似乎很难管理

    即使我做到了这一点;我只需要一个
    glDraw
    呼叫;听起来很快。这是真的吗?单个
    glBindVertexArray
    调用对多个调用有什么样的性能影响

    我不认为有任何方法可以使用这种方法来实现像我现在正在进行的
    glScissor
    调用这样的东西

  • 我读过的另一个选项是实例化。因此,无论我需要多少次,我都会画四边形;这意味着我将向着色器传递一组平移矩阵和一组纹理坐标

    这会快很多吗

    我想我可以通过传递一个额外的布尔数组来做一些类似于
    glScissor
    测试的事情,这个布尔数组定义了当前四元组是否应该只在前一个四元组的边界内绘制。然而,我认为这意味着,对于每个
    gl_InstanceID
    ,我必须遍历所有以前的实例,寻找真值和假值,而且速度似乎很慢

  • 我试图通过不单独实现所有这些来节省时间。希望专家能告诉我哪一种可能更好。如果有人有更好的主意,请告诉我

  • 您可以将多个VBO附加到不同的属性 以下顺序将2个VBO绑定到属性0和1,请注意glBindBuffer()临时绑定缓冲区,并且在glVertexAttribPointer()期间将实际VBO分配到属性

    提供四边形位置和大小的最快方法是使用纹理并在顶点着色器中对其进行采样。当然,您至少需要RGBA(x,y,宽度,高度)16位/通道纹理。但是,您可以使用glTexSubImage2D()更新四边形位置,甚至可以通过FBO渲染它们

    除此之外的所有操作都会执行较慢,当然,如果您愿意,我们可以详细介绍如何在vbos中使用制服、属性库,或者在没有启用阵列的情况下使用属性库

    综合起来:

    • 使用单个vbo,在其中存储四元id(int)+纹理数据
    • 准备x、y、w、h纹理,定义从四边形id到该纹理texcoord的映射,即:u=四边形id&0xFF,v=(四边形id>>8)(对于纹理256x256最大65536四边形)
    • 使用顶点着色器从该纹理采样置换和大小(对于存储在属性中的给定四边形id(或使用顶点id/4或顶点id/6))
    • 填充vbo和纹理
    • 使用绘图元素的单个绘图数组绘制所有内容

    首先,你是怎么得到这个用户名的?第二,请详细说明。事实上,我知道如何使用纹理信息最快。你还可以使用纹理做什么?我认为它是默认用户名,从来没有想过要更改它:)请注意,在使用vbo的情况下,你需要为每个顶点提供位置和大小(每个四边形4个甚至6个)。使用纹理时,您需要将这些信息存储在vbo texel地址(quad id)中,以便从纹理中获取这些信息。感谢您扩展您的建议。使用这种方法,我不能使用实例绘制,所以我只需要6个顶点,或者4个顶点和一个IBO,然后使用
    gl\u InstanceID
    作为我的QuadID?这会使它更快吗?因为这样就不需要通过任何东西;我可以使用两种纹理,一种带有位置,另一种带有我实际可见纹理的UV坐标?是的,实际上你不需要传递任何东西。但是许多GL实现者不喜欢我
    glBindBuffer(GL_ARRAY_BUFFER,buf1);
    glVertexAttribPointer(0, ...);
    glEnableVertexAttribArray(0);
    
    glBindBuffer(GL_ARRAY_BUFFER,buf2);
    glVertexAttribPointer(1, ...);
    glEnableVertexAttribArray(1);