不深入理解OpenGL: UBO (Uniform Block Object)


最近剛剛開始研究圖形方面的東西,如果理解有誤請務必指正。在OpenGL 4.5已經有更好的解法了,奈何我辣雞I卡只支持4.4。

UBO是OpenGL 3.1 Core中引入的概念。通過到緩存的通信,修改Uniform變量(=運行時常量)造成的開銷更低,不同的Shader間還可以共享同一UBO的內容。具體就不扯那么多了,有興趣可以閱讀ARB原文了解更多。

因為OpenGL的狀態機模型,有的時候調用相關API會發生意料之外的結果。一般也就是畫不出東西,再慘就是報錯了。這里記錄一下UBO的緩沖區生成與綁定流程:

GLuint buf;
glGenBuffers(1, &buf); // 創建緩存,此時僅僅創建了緩存句柄(name、handle、id,就那個意思),對象並沒有被創建。
auto index = glGetUniformBlockIndex(prog, "UBOName"); // 通過UBO名查詢索引。
glUniformBlockBinding(prog, index, bindingPoint); // 綁定着色器程序$prog的UBO到$bindingPoint。bindingPoint不和同一程序其他UBO重復即可。

glBindBuffer(GL_UNIFORM_BUFFER, buf); // 在首次綁定時會通過句柄構造對象。
glBufferData(GL_UNIFORM_BUFFER, GetUniformBlockSize(index), nullptr, GL_STATIC_DRAW); // 注意顯存中內容是未定義的,在指定數據前不可使用。
glBindBuffer(GL_UNIFORM_BUFFER, 0); // 為了安全解除綁定。

這里通過buf就可以修改相應UBO的內容了。

繪圖時再完成另一半的綁定:

glBindBufferBase(GL_UNIFORM_BUFFER, bindingPoint, buf); // 綁定緩存$buf到$bindingPoint。也可以使用glBindBufferRange()。

需要注意的地方:

  1. glBindBufferBase()被調用時雖然也會將buf綁定到GL_UNIFORM_BUFFER,但在緩存對象沒有被構造的時候調用glBindBuffer{Base, Range}會造成GL_INVALID_VALUE錯誤,參見這里。所以在構建UBO緩存的時候並沒有使用這兩個方法。
  2. 從UBO到Binding Point的綁定是對着色器程序的操作;而從緩存到Binding Point的綁定是對OpenGL狀態機進行的操作。所以,在每次draw的時候不需要重新定義UBO到Binding Point的綁定,但需要重新定義對緩存的綁定。參見這里


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM