在之前的實踐中我們都是在當前的窗口中渲染,即使用的緩存都是由glutCreateWindow時創建的緩存,我們可稱之為默認緩存。它是唯一一個可以被圖形服務器的顯示系統識別的幀緩存,我們在屏幕上看到的只能是這個緩存。
雖然我們可以對這個緩存作非常多的操作,應用不同的技術,但在不同的緩存間遷移大量的數據,我們還需要很多的操作,而幀緩存對象(framebuffer object)就是為此存在的。幀緩存可以實現理屏渲染技術、紋理貼圖的更新、以及緩存乒乓技術(GPGPU用到的一種數據傳輸技術)的實現非常的有意義,但需要注意的是,應用程序創建的幀緩存是不能與窗口系統的緩存關聯的,窗口系統有一套自己的緩存對象。
下面我們將實現離屏渲染,並把渲染的結果拷貝回默認緩存顯示。
創建幀緩存
創建緩存對象的過程和OpenGL創建其它對象的過程非常類似,使用glGenFramebuffers和glBindFramebuffer,同時使用glFramebufferParameteri設置幀緩存對象的參數。
glGenFramebuffers(1,&fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER,fbo);
創建渲染緩存
渲染緩存(renderbuffer)是OpenGL管理的一處高效的內存區域,它可以存儲格式花的圖像數據。渲染緩存的數據必須關聯到幀緩存對象才有意義,並且要保證圖像緩存的格式必須與OpenGL要求的渲染格式相符。
創建渲染緩存和創建幀緩存的步驟類似,分別使用glGenRenderbuffers和glBindRenderbuffer,使用glRenderbufferStorage分配存儲空間和設置圖像格式。
glGenRenderbuffers(1,&rbo); glBindRenderbuffer(GL_RENDERBUFFER,rbo);
glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA,width,height);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER,rbo); //把渲染緩存關聯到幀緩存
拷貝到默認緩存
創建好幀緩存和默認緩存后,我們就可以開始繪制了,首先我們設置繪制的目標為我們創建的幀緩存,不再繪制到默認緩存中。
glBindFramebuffer(GL_DRAW_FRAMEBUFFER,fbo);
然后正常繪制場景,這個時候圖像的數據都會存儲到fbo的存儲空間中。
接着我們以這個幀緩存為源,以默認幀緩存為目標開始拷貝。
//指定繪制到創建的幀緩存中 glBindFramebuffer(GL_DRAW_FRAMEBUFFER,fbo); glViewport(0,0,width,height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //渲染 tShader->Use(); glBindVertexArray(vao); glDrawArrays(GL_TRIANGLES,0,3); //指定緩存操作的源和目的 glBindFramebuffer(GL_READ_FRAMEBUFFER,fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER,0); glViewport(0,0,width,height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //拷貝 glBlitFramebuffer(0,0,width,height,0,0,width,height,GL_COLOR_BUFFER_BIT,GL_NEAREST); glBlitFramebuffer(0,0,width,height,0,0,128,128,GL_COLOR_BUFFER_BIT,GL_NEAREST); glFlush();
最終效果: