OpenGL離線渲染和緩衝區對象

理論

OpenGLl離線渲染就是通過OpenGL將繪製結果渲染到顯存中的一張圖片上,通過gl接口函數可以從顯存讀取到內存中。基於OpenGL的離線渲染機制,可以快速實現一個渲染器:

輸入:圖像,點,線。。。

輸出:圖像

實現方案

從一般到特殊:

1. 不支持FBO

主要介紹PC上,移動設備如果不支持FBO要實現離線渲染那就實在沒轍了
glDrawBuffer(GL_BACK); glReadBuffer(GL_BACK); 設置讀寫時後緩存區。  一般pc都支持雙緩衝機制,如果沒有GL_BACK就沒轍了
glDrawPixels 更新顏色緩衝區。
調用opengl繪製函數在GL_BACK繪製。
完成後glReadPixels將顏色緩衝區以從顯存調入內存。  該函數會導致gpu阻塞,效率不高。

2. PC支持FBO

opengl支持多種緩衝區對象
緩衝區對象說白了就是 顯存中一塊緩存區。OpenGL是業界渲染標準,具體接口功能由顯卡驅動實現,OpenGL客戶端是使用OpeGL的應用程序,OpenGL服務器可以理解成GPU,如果沒有GPU就是OS內核中的一個模塊,緩衝區對象定義在服務器端,減少客戶端每次渲染時數據傳輸開銷。每個緩衝區對象有唯一的ID,類似handle概念,客戶端通過BufferId管理緩衝區對象。

1)紋理對象,最常見的從gl1.0就開始支持,基本操作指令:glGenTextures, glBindTextures, glDeleteTextures,後續有多重紋理增加新的指令。
服務器端的紋理數據,客戶端只有寫權限:glTexSubImage2D函數局部或者全部更新紋理緩衝區內容。

2)VBO(vertex buffer object)和PBO(pixel buffer object) 原理完全一樣使用相同的gl指令:glGenBuffers,glBindBuffers,glDeleteBuffers。。。
只不過buffer中存的數據內容不一致,前者存頂點後者存像素。VBO的出現 頂點列表逐漸淡出了人們的視野。
服務器端的VBO,PBO,客戶端有讀寫權限:glMapBuffer 將服務器端內存地址映射爲客戶端地址,操作完成調用glUnMapBuffer;或者直接通過glBufferSubData 更新數據。

3)VBO後又出現VAO(vertex array buffer),VAO的是GL3.0出來的東東,有點高處不甚寒 考慮移動設備 考慮android行情木有研究,有志者請猛擊此處:

4)RBO(render buffer object),rbo並不能單獨使用,必須配合fbo,與opengl緩衝區對應,RBO可以存放顏色、深度、模板數據。指令集合:glGenRenderbuffers,glBindRenderbuffer,glDeleteRenderbuffers。

5)FBO(frame buffer object) 有一套專門的指令集合:glGenFramebuffers, glBindFramebuffer, glDeleteFramebuffers.。
FBO創建以後必須綁定緩衝區:顏色、深度必須,模板緩衝區看需求而定。
緩衝區對象並不侷限於RBO,紋理對象也可以充當緩衝區對象:創建紋理是glTexImage2D最後一個參數爲NULL,在顯存中只需要創建紋理對象,而並不需要傳紋理數據。
紋理對象作爲緩衝區對象的例子:http://www.songho.ca/opengl/gl_fbo.html

回到主題,通過fbo實現離線渲染流程如下:
主渲染流程,使用系統默認的緩衝區對象
保存OpenGL現場
              —————————>>  bind FBO
             a)  glClear 清空FBO對應的各種緩衝區內容
             b)  在離線渲染之前,往顏色緩衝區中添加內容,如背景圖片
             c)  set projectionMatrix
             d)  set modelviewMatrix
             e)  all draw calls  // draw some stuff
             f)  glReadPixels // 如果需要,渲染結果圖片從顯存調入內存,在後續主渲染流程中創建紋理對象使用
                 glCopyTexImage2D使用幀緩衝區的數據定義紋理單元,像素直接從顏色緩衝區讀取,功能類似glCopyPixels
                 如果顏色緩衝區採用 紋理對象,後續在主渲染流程中 可以直接使用該紋理進行繪製
              <<—————————  unbind FBO
回到主渲染流程

3.  Mobile 上離線渲染

移動設備,明顯特點是受限,gles是opengl的縮減版,gles沒有glDrawBuffer和glReadBuffer接口,沒法直接操縱前後緩衝區,所以方案1失效 只能轉向FBO。
gles1.1開始支持FBO,gl變量和指令加OES後綴。

手機上fbo離線渲染流程跟PC上基本類似,在此主要說兩點主要差別:
1)關於離線渲染的步驟b,pc上最常見的做法glDrawPixels直接往顏色緩衝區拷貝數據,但是gles不支持glDrawPixels。
想到的第一種替代方案:正交投影模式下直接drawTextureQuad,走OpenGL標準流水線:紋理對象創建、數據傳輸,頂點傳輸、幾何變換流程,光柵化、紋理座標尋址取紋理單元,最終通過緩衝區各種測試將結果寫到顏色緩衝區中。
優化後的方案:紋理對象作爲FBO的顏色緩衝區,可以通過glTexSubImage2D函數直接將圖像數據更新到顏色緩衝區中,全部或者局部,功能跟glDrawPixels完全一致,避免走OpenGL流水線。

2)在手機上效率優先,建議不要直接使用glReadPixels函數,可以參考ogl_fbo_pbo_readback示例。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章