OpenGL--幀緩沖區


  • 理論基礎
    1,幀緩沖區(顯存):是由像素組成的二維數組,每一個存儲單元對應屏幕上的一個像素,整個幀緩沖對應一幀圖像即當前屏幕畫面。幀緩沖通常包括:顏色緩沖,深度緩沖,模板緩沖和累積緩沖。這些緩沖區可能是在一塊內存區域,也可能單獨分開,看硬件。而像素數據在進入幀緩沖之前(稱為片段)必須通過一系列測試才能寫入幀緩沖,如果片段在其中某個測試沒有通過,后面的測試或操作都將不再進行。這些測試或操作流程是:開始(片段)-裁剪測試-alpha測試-模板測試-深度測試-混合-抖動-邏輯操作-結束(寫入幀緩沖).
    2,創建幀緩沖區對象:前面章節講過OpenGL一般的緩沖區對象,主要是優化性能。而幀緩沖區對象除了優化性能還增加了一些功能,類似GDI中的輔助DC,和系統的幀緩沖區一樣也是保存當前屏幕圖像,只是它是后台保存看不見。具體它可以關聯紋理對象(即顏色緩沖區)和渲染緩沖對象(Renderbuffer有深度緩沖和模板緩沖)來組成自己后台的幀緩沖區。例如,渲染動態紋理,多屏實現等。
    這里寫圖片描述

注釋:幀緩沖可能是GPU專屬內存,也可能是GPU和CPU共享內存,看硬件。手機一般是共享內存,PC獨立顯卡一般是專屬內存,集成顯卡是共享內存。


1,創建幀緩沖區對象

void init()
{
    // 創建紋理對象內存空間
    glGenTextures(1, &textureId);
    glBindTexture(GL_TEXTURE_2D, textureId);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);//開啟多級紋理
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    glBindTexture(GL_TEXTURE_2D, 0);//解除綁定(好的習慣:用完就關閉,哪里用哪里開)

     // 創建幀緩沖對象
    glGenFramebuffers(1, &fboId);//沒有空間的,需要關聯紋理對象或渲染緩沖對象才有意義
    glBindFramebuffer(GL_FRAMEBUFFER, fboId);

    //用渲染緩沖對象創建了一個深度緩沖區
    glGenRenderbuffers(1, &rboId);
    glBindRenderbuffer(GL_RENDERBUFFER, rboId);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, TEXTURE_WIDTH, TEXTURE_HEIGHT);
    glBindRenderbuffer(GL_RENDERBUFFER, 0);//臨時解綁

    // 關聯到紋理
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);

    // 關聯到深度緩沖區
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);//臨時解綁
}

2,使用

//動態紋理貼圖:使用幀緩沖對象效率要明顯提高
void displayCB()
{
    //使用幀緩沖對象(直接渲染到綁定的紋理對象)
    if(fboUsed)
    {
        // 激活當前幀緩沖對象
        glBindFramebuffer(GL_FRAMEBUFFER, fboId);

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

        glPushMatrix();
        glRotatef(angle*0.5f, 1, 0, 0);
        glRotatef(angle, 0, 1, 0);
        glRotatef(angle*0.7f, 0, 0, 1);
        glTranslatef(0, -1.575f, 0);
        drawTeapot();//繪制動態茶壺
        glPopMatrix();

        glBindFramebuffer(GL_FRAMEBUFFER, 0); // 用完解綁
    }

    // 沒有使用幀緩沖對象(先渲染到后天緩沖再copy到紋理)
    else
    {
        glClearColor(1, 1, 1, 1);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glPushAttrib(GL_COLOR_BUFFER_BIT | GL_PIXEL_MODE_BIT);
        glDrawBuffer(GL_BACK);
        glReadBuffer(GL_BACK);

        glPushMatrix();
        glRotatef(angle*0.5f, 1, 0, 0);
        glRotatef(angle, 0, 1, 0);
        glRotatef(angle*0.7f, 0, 0, 1);
        glTranslatef(0, -1.575f, 0);
        drawTeapot();
        glPopMatrix();

        // copy緩沖區的像素到紋理
        glBindTexture(GL_TEXTURE_2D, textureId);
        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
        glBindTexture(GL_TEXTURE_2D, 0);

        glPopAttrib();
    }

    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    // 繪制立方體(紋理貼圖)
    draw();

    glutSwapBuffers();
}

這里寫圖片描述

版權聲明:本文為博主原創文章,未經博主允許不得轉載。


免責聲明!

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



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