目前用OpenGL ES 3.1绘制大量四边形的最快方法是?

问题描述:

晚上好,以下场景:目前用OpenGL ES 3.1绘制大量四边形的最快方法是?

我正在实现一个标签渲染算法。输入数据由许多字符串和纹理图集组成,每个字符串都有纹理数据。每个字符串都应该生成许多四边形,每个字形的每个实例都有一个,其纹理坐标参考纹理图集。

帧之间唯一可以改变的地方是标签和它们的字形在屏幕上的位置。所以,我的第一个想法是创建一个巨大的四边形缓冲区,组成本地坐标中的字形,然后从单独的缓冲区中读取位置,以更新每一帧。

现在我的问题:目前最快的方法是在OpenGL ES 3.1中做什么?我的第一个想法是使用glDrawElements和GL_TRIANGLE_STRIP使用原始重启索引,然后将索引转换为顶点着色器中缓冲区中的某个条目并从中读取位置。

但是,我想知道在此期间是否出现了更快的方法。

预先感谢您!

基于OpenGL ES的设备大多限制每帧的绘制调用次数。所以你需要将每个角色的所有三角形分成一个网格并绘制一次。这将在大多数情况下为您提供最佳性能。

  • 配料所有顶点到一个网
  • 构造带索引的三角形网格,并使用VAO
  • 在顶点属性添加一个额外的指数来表示一个字符的索引。
  • 将每个字符的模型矩阵传递为均匀阵列。
  • 在顶点着色器中,将顶点位置与该索引的模型矩阵相乘。

这种方法有一些限制。

  • 可批量处理的字符数取决于硬件。 (一次允许一个着色器的缓冲区大小为 。)
  • 如果顶点数量非常大,则您可能很容易在顶点着色器中遇到瓶颈。

我写了一个小精灵着色器是精灵着色器从这里http://learnopengl.com/#!In-Practice/2D-Game/Rendering-Sprites

的唯一区别简单的OpenGL和OpenGL ES 3.1之间的克隆将在着色器的几行。你需要从两个着色器来更改版本:

#version 330 core 

#version 300 es 

而且,在片段着色器,添加行

precision mediump float; 

某处接近顶部。

然后,假设你的着色器模型和投影矩阵制服,你只需要使用一个2D向量位置创建一个4D向量,代替你的顶点着色器的最后两个参数在0.0和1.0:

gl_Position = projection * model * vec4(vertex.xy, 0.0, 1.0); 

我觉得这在Joey的LearnOpenGL教程中解释得比在这里详细解释的更好。


你绘制函数可能看起来像这样(如果你使用C++ 11):

mShader([ & ] () // Same as glUseProgram(shaderID) but automatically un-Uses it when it goes out of scope 
{ 
    glm::mat4 model; 
    model = glm::translate(model, glm::vec3(xPosition, 0.0f)); 
    model = glm::translate(model, glm::vec3(0.5f * xSize.x, 0.5f * xSize.y, 0.0f)); 
    model = glm::rotate( model, xRotate, glm::vec3(0.0f, 0.0f, 1.0f)); 
    model = glm::translate(model, glm::vec3(-0.5f * xSize.x, -0.5f * xSize.y, 0.0f)); 
    model = glm::scale( model, glm::vec3(xSize, 1.0f)); 

    mShader.getUniforms().setUniformMatrix4fv("model", model); 
    mShader.getUniforms().setUniformVector3f("spriteColor", xColor); 
    glActiveTexture(GL_TEXTURE0); 

    xTexture([ & ]() // Does the same as glBindTexture but automatically unbinds when out of scope 
    { 
     glBindVertexArrayOES(mQuadVAO); 
     glDrawArrays(GL_TRIANGLES, 0, 6); 
     glBindVertexArrayOES(0); 
    }); 
}); 

我在执行从是我使用SDL获得一个OpenGL教程唯一的区别ES 3.0上下文(用于可移植性和其他功能,例如键盘,鼠标)。我可以确认,Joey的教程仅在我上面提到的一些小改动的情况下在Android,嵌入式Linux Intel集成显卡和Windows上运行AMD GLES3 SDK。

您可能想要通过使用PBO来增强实施;一个OpenGL版本是在相同的回购。

它使用PBOs。这可以用来更新四维纹理,比glTexImage2D更快。我不知道在OpenGL ES中是否支持PBO,但它们可能是扩展的。如果您只需提前加载一堆四边形并渲染它们,则无需走得太远。

要更新直截了当的方式四,它只是:

glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); 
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mW, mH, GL_RGBA, GL_UNSIGNED_BYTE, xData); 

使用公益组织,您可以使用两个公益组织,以使“双缓冲功能,”在那里你清除PBO和映射等PBO每转。有关更多信息,请参阅glBindBufferARBglBufferDataARB,glMapBufferARB,glUnmapBufferARB的OpenGL ES规范。显然,从3.0开始,OpenGL ES确实支持PBO,所以如果您需要快速更新纹理,这就是要走的路。

+0

根据要求添加了更详细的信息。 LearnOpenGL上的代码非常广泛,并且很难在此处完整粘贴。 –