2016-09-19 81 views
0

晚上好,以下場景:目前用OpenGL ES 3.1繪製大量四邊形的最快方法是?

我正在實現一個標籤渲染算法。輸入數據由許多字符串和紋理圖集組成,每個字符串都有紋理數據。每個字符串都應該生成許多四邊形,每個字形的每個實例都有一個,其紋理座標參考紋理圖集。

幀之間唯一可以改變的地方是標籤和它們的字形在屏幕上的位置。所以,我的第一個想法是創建一個巨大的四邊形緩衝區,組成本地座標中的字形,然後從單獨的緩衝區中讀取位置,以更新每一幀。

現在我的問題:目前最快的方法是在OpenGL ES 3.1中做什麼?我的第一個想法是使用glDrawElements和GL_TRIANGLE_STRIP使用原始重啓索引,然後將索引轉換爲頂點着色器中緩衝區中的某個條目並從中讀取位置。

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

預先感謝您!

回答

0

基於OpenGL ES的設備大多限制每幀的繪製調用次數。所以你需要將每個角色的所有三角形分成一個網格並繪製一次。這將在大多數情況下爲您提供最佳性能。

  • 配料所有頂點到一個網
  • 構造帶索引的三角形網格,並使用VAO
  • 在頂點屬性添加一個額外的指數來表示一個字符的索引。
  • 將每個字符的模型矩陣傳遞爲均勻陣列。
  • 在頂點着色器中,將頂點位置與該索引的模型矩陣相乘。

這種方法有一些限制。

  • 可批量處理的字符數取決於硬件。 (一次允許一個着色器的緩衝區大小爲 。)
  • 如果頂點數量非常大,則您可能很容易在頂點着色器中遇到瓶頸。
1

我寫了一個小精靈着色器是精靈着色器從這裏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上的代碼非常廣泛,並且很難在此處完整粘貼。 –