- 理論基礎
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();
}
版權聲明:本文為博主原創文章,未經博主允許不得轉載。