OpenGL-非實時渲染與實時混合使用(有圖有真相)


 視頻教程請關注 http://edu.csdn.net/lecturer/lecturer_detail?lecturer_id=440

一個朋友在問(我也曾經遇到過這樣的事情),尤其是在地理信息上面,地圖上的一些矢量數據,以及

影像數據,在地圖沒有變化(比如,縮放,平移,編輯)都是不需要繪制的,只有需要繪制的時候,在去繪制

背景,想必,這個道理大家一定都很明白,但是OpenGL每次在繪制的時候是必須都要進入渲染管線進行繪制

於是很多人就在想,是否可以把一些不需要變化的數據繪制到圖片上,需要繪制的時候在進行重新繪制,就像

windows DC一樣呢?在OpenGL早期的版本中是沒有把數據繪制到圖片上這個功能的,當然在創建OpenGL

的時候有這個選項,本人親身試驗過,那個效率,那個差呀,OpenGL初始化代碼如下所示:

PIXELFORMATDESCRIPTOR pfd = 
        {
            sizeof(PIXELFORMATDESCRIPTOR), 
            1, 
            PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_SUPPORT_DIRECTDRAW | PFD_SWAP_EXCHANGE,
            PFD_TYPE_RGBA, 
            32, 
            8, 
            0,
            8,
            8,
            8,
            0,
            0, 
            0,
            32, 
            8,
            8,
            8, 
            8,
            24,
            8, 
            0, 
            PFD_MAIN_PLANE, 
            0,
            0, 
            0,
            0
        };

紅色的部分就是繪制到圖片的選項。

  這種方案是不可取的,且不說他的效率問題,也滿足不了目前的需求,在OpenGL1.1版本中,我們可以操作顏色緩沖區,或者

叫幀緩沖區,在OpenGL中,至少存在兩個緩沖區(當我們選擇雙緩沖繪制的時候),我們可以把數據繪制到緩沖區以后,在將

緩沖區的數據直接的生成到紋理上,這樣在把紋理繪制到背景中,這樣,就可以有選擇的去更新背景,而不是實時的去繪制背景

數據,流程如下圖所示:

代碼如下所示:

        glClearColor(1, 1, 1, 1);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glPushAttrib(GL_COLOR_BUFFER_BIT | GL_PIXEL_MODE_BIT); // for GL_DRAW_BUFFER and GL_READ_BUFFER
        glDrawBuffer(GL_BACK);
        glReadBuffer(GL_BACK);

        //! 繪制數據到GL_BACK緩沖區
        //! 繪制完成,將緩沖區內容cpopy到紋理

        glBindTexture(GL_TEXTURE_2D, textureId);
        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
        glBindTexture(GL_TEXTURE_2D, 0);
        glPopAttrib(); // GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT

        //! 其他實時繪制內容

當然,這個方式比較老土,但能實現我們想要的功能,而且效率也不賴。在新的OpenGL版本中實現這個過程有很多方式

例如比較流行的就是FBO( Fram buffer object),幀緩沖區對象,其實就是我們上面的過程,所不同的是:上面我們用到

的緩沖區是OpenGL給我們創建的,我們沒有辦法干預創建的過程,而后者則可以干預這個過程,我們可以自己去創建幀

緩沖區,並使用它,當然這個需要更高的OpenGL版本,你需要做更多的事情。

下面是創建Frame Buffer Object 的代碼:

        glGenFramebuffersEXT(1, &targetId._FBOID);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, targetId._FBOID);

        glGenRenderbuffersEXT(1, &targetId._RBOID);
        glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, targetId._RBOID);
        glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);
        glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

        //glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId, 0);

        glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, targetId._RBOID);

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

創建了以后,為了把數據繪制到上面,我們還需要給他綁定一個紋理,這個過程就像我們創建一個內存DC一樣,如果沒有和圖片綁定

繪制是沒有任何意義的;

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, targetId._FBOID);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, textureId._texture, 0);

綁定紋理以后,以后的繪制,則是將數據繪制到紋理上了;代碼中可以這樣使用:

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, targetId->_FBOID);
glBegin()
...
glEnd()
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

在一種方式就是PBuffer:像素緩沖區,過程和這個相似。每一種方式都有自己的優點與缺點,在不同的場合用不同的方式

做到最大化利用就對了。

后續會專門對離屏渲染做專門的例程。感謝大家閱讀,本人能力有限,錯誤,誤導之處請指教。

 


免責聲明!

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



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