理論
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
采用RBO的例子:
免費下載地址在 http://linux.linuxidc.com/
用戶名與密碼都是www.linuxidc.com
具體下載目錄在 /2014年資料/3月/25日/OpenGL離線渲染和緩沖區對象
下載方法見 http://www.linuxidc.com/Linux/2013-07/87684.htm
回到主題,
通過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示例。