OpenGL幀緩衝區 轉載

http://www.cnblogs.com/yxnchinahlj/archive/2010/11/19/1881781.html


在OpenGL窗口中, 左下角的像素爲(0, 0). 一般而言, 像素(x, y)佔據的矩形區域左下角爲(x, y), 右上角爲(x+1, y+1).

10.1 緩存及其用途


1) 顏色緩存,  左前,右前,左後,右後和任意數量的輔助顏色緩存;
2) 深度緩存
3) 模板緩存
4) 累積緩存

注意:X窗口系統,RGBA模式至少保證1個顏色緩衝區,模板緩衝區,深度緩衝區,累計緩衝區
顏色索引模式至少保證1個眼色緩衝區,深度緩衝區,模板緩衝區.
可以使用glXGetConfig{}函數查詢.

用glGetIntegerv()查詢每個像素佔據的緩存空間的參數
GL_RED_BITS, GL_GREEN_BITS, GL_BLUE_BITS, GL_ALPHA_BITS --- 顏色緩存中R, G, B, A分量的位數
GL_INDEX_BITS --- 顏色緩存中每個顏色索引的位數
GL_DEPTH_BITS --- 深度緩存中每個像素的位數
GL_STENCIL_BITS --- 模板緩存中每個像素的位數
GL_ACCUM_RED_BITS, GL_ACCUM_GREEN_BITS, GL_ACCUM_BLUE_BITS, GL_ACCUM_ALPHA_BITS --- 累積緩存中R, G, B, A分量的位數.

10.1.1 顏色緩存


1) 顏色緩存存儲了顏色索引或RGB顏色數據, 還可能存儲了alpha值. 
2) 支持立體觀察(stereoscopic viewing)的OpenGL實現有左顏色緩存和右顏色緩存. 它們分別用於左立體圖像和右立體圖像.
3) 如不支持立體觀察, 則只使用左顏色緩存.
4) 雙顏色緩存有前緩存和後緩存, 單緩存系統只有前緩存.
5) 支持不可顯示的輔助顏色緩存
6) 函數glGetBooleanv()查詢是否支持立體觀察和雙緩存: GL_STEREO和GL_DOUBLE_BUFFER. 
   函數glGetIntegerv()查詢多少個輔助緩存可用: GL_AUX_BUFFERES.

10.1.2 深度緩存


深度緩存 --- 存儲了每個像素的深度值. 通常是離視點的距離, 因此深度值大的像素會被深度值小的像素覆蓋.

10.1.3 模板緩存


用途之一: 繪圖範圍限制在屏幕的特定區域內.

10.1.4 累積緩存


累積緩存也存儲RGBA顏色數據, 將一系列的圖像合成一幅圖像. 
可以對圖像進行超量採樣, 然後對樣本進行平均, 並將結果寫入顏色緩存中, 從而實現場景反走樣. 不能將數據直接寫入累積緩存.
累加操作總是針對一個矩形塊的, 通常是將數據移入或移出顏色緩存.

10.1.5 清空緩存


void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
void glClearIndex(GLfloat index);
void glClearDepth(GLclampd depth);
void glClearStencil(GLint s);
void glClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
功能: 指定用於清除顏色緩存(RGBA模式或顏色索引模式), 深度緩存, 模板緩存和累積緩存的值. 
類型爲GLclampf和GLclampd的參數值被截取到[0.0, 1.0]. 深度緩存的默認清除值爲1.0, 其他緩存爲0.0.

設置清除值後, 便可以調用函數glClear()來清除緩存.
void glClear(GLbitfield mask);
功能: 清除指定的緩存. 
mask:GL_COLOR_BUFFER_BIT, GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT, GL_ACCUM_BUFFER_BIT的邏輯或(OR).
清除顏色緩存時, 如果啓用了像素所有權測試, 裁剪測試和抖動操作, 它們都會在清除操作中執行. 
屏蔽操作(glColorMask()和glIndexMask())也會生效.alpha測試, 模版測試, 深度測試並不會影響glClear()函數的操作.

10.1.6 指定要讀寫的顏色緩存


指定要寫入的緩存 glDrawBuffer();
指定要讀取的緩存 glReadBuffer();

使用雙緩存, 通常只繪製後緩存, 並在繪製完成後交換緩存. 你可能想將雙緩存窗口視爲單緩存窗口: 通過調用函數glDrawBuffer()使得可以同時繪製前緩存和後緩存.
void glDrawBuffer(GLenum mode); 
功能: 指定要寫入或消除的顏色緩存以及禁用之前被啓用的顏色緩存. 可以一次性啓用多個緩存.
GL_FRONT: 單緩存的默認值    
GL_FRONT_RIGHT:    
GL_NONE:
GL_FRONT_LEFT:
GL_FRONT_AND_BACK:
GL_RIGHT:
GL_AUXi: i表示第幾個輔助緩存.
GL_LEFT:
GL_BACK_RIGHT:
GL_BACK: 雙緩存的默認值
GL_BACK_LEFT:
注意: 啓用多個緩存用於寫操作時, 只要其中一個緩存存在, 就不會發生錯誤. 如果指定的緩存都不存在, 就發生錯誤.

void glReadBuffer(GLenum mode); 
功能: 選擇接下來的函數調用glReadPixels(), glCopyPixels(), glCopyTexImage*(), glCopyTexSubImage*() 和 glCopyConvolutionFilter*()將讀取的緩存.
      並啓用以前被函數glReadBuffer()啓用的緩存.
參數mode取值:
GL_FRONT: 單緩存默認
GL_FRONT_RIGHT:
GL_BACK_RIGHT:
GL_FRONT_LEFT:
GL_LEFT:
GL_AUX:
GL_BACK_LEFT:
GL_BACK: 雙緩存默認
GL_RIGHT:
注意: 啓用緩存用於讀取操作時, 指定的緩存必須存在, 否則將發生錯誤.

10.1.7 屏蔽緩存


void glIndexMask(GLuint mask);
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
void glDepthMask(GLboolean flag);
void glStencilMask(GLuint mask);
 
功能: 設置掩碼, 用於控制寫入到指定緩存中的數據,
glIndexMask: 只用於顏色索引模式中, 掩碼中1對應的數據位被寫入顏色索引緩存中. 0對應的位不寫入.
glColorMask: 隻影響RGBA模式下的寫入, red, green, blue, alpha決定是否寫入相應的分量, GL_TRUE時寫入.
glDepthMask(): 如果參數flag的值爲GL_TRUE, 則啓用深度緩存用於寫入, 否則禁用深度緩存.
glStencilMask(): 參數mask的含義與函數glIndexMask()中相同. 
所有GLboolean參數的默認值是GL_TRUE, 兩個GLuint參數的默認值都是1.

禁用深度緩存: 如果背景很複雜, 則在背景繪製之後, 禁用深度緩存. 繪製新增的物體, 只要不相互重疊.. 下一幀時, 只需恢復樹木圖像, 無需恢復深度緩存中的值.
這種方法很有效.

模板緩存的屏蔽操作讓你能夠使用一個多位模板緩存來存儲多個模板(每位一個)
函數glStencilMask()指定的掩碼用於控制哪些模板位面可寫, 與函數glStencileFunc()的第三個參數指定的掩碼無關, 後者指定模板函數將考慮哪些位面.

10.2 片段測試和操作


測試順序:
1. 裁剪測試 
2. alpha測試 
3. 模版測試
4. 深度測試
5. 混合
6. 抖動
7. 邏輯操作

10.2.1 裁剪測試


void glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
設置裁剪矩形的位置和大小. 需要啓用GL_SCISSOR_TEST.

10.2.2 alpha測試


需要啓用GL_ALPHA_TEST
void glAlphaFunc(GLenum func, GLclampf ref); 
設置用於alpha測試的參考值和比較函數.
alpha測試可用於透明算法和貼花.

10.2.3 模板測試


void glStencilFunc(GLenum func, GLint ref, GLuint mask);
void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
 
設置模板測試所使用的比較函數(func),參考值(ref),掩碼(mask)

void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass);
void glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
指定當一個片段通過或未通過模板測試時, 模板緩衝區中的數據如何進行修改.

下圖設置模板爲中間的方塊

11

模板查詢glGetInteger()可使用的參數:
GL_STENCIL_FUNC
GL_STENCIL_REF
GL_STENCIL_VALUE_MASK
GL_STENCIL_FAIL
GL_STENCIL_PASS_DEPTH_FAIL
GL_STENCIL_PASS_DEPTH_PASS

 

10.2.4 深度測試


void glDepthFunc(GLenum func); 
爲深度測試設置比較函數.

10.2.5 遮擋測試


遮擋測試允許我們判斷一組幾何圖形在進行深度測試之後是否可見.
步驟:
1. 爲每個所需的遮擋查詢生成一個查詢ID
2. 調用glBeginQuery(), 表示開始一個遮擋查詢
3. 渲染需要進行遮擋查詢的幾何圖形
4. 調用glEndQuery(), 表示已經完成了遮擋查詢
5. 提取通過遮擋查詢的樣本數量.

生成查詢對象
void glGenQueries(GLsizei n, GLuint* ids);

對遮擋查詢對象進行初始化
void glBeginQuery(GLenum target, GLuint id);
void glEndQuery(GLenum target);
 
target必須爲GL_SAMPLES_PASSED.

判斷遮擋查詢的結果
void glGetQueryObjectiv(GLenum id, GLenum pname, GLint *params);
void glGetQueryObjectuiv(GLenum id, GLenum pname, GLuint *params);

清除遮擋查詢對象
void glDeleteQueries(GLsizei n, const GLuint *ids);

10.2.6 混合,抖動和邏輯操作


void glLogicOp(GLenum opcode); 
選擇需要執行的邏輯操作.

10.3 累計緩衝區


void glAccum(GLenum op, GLfloat value); 
控制累積緩衝區
op參數:
GL_ACCUM--用glReadBuffer()所讀取的當前緩衝區中讀取每個像素.把R,G,B,A值乘以value.而後結果累加到累積緩衝區.
GL_LOAD--同上,只是用結果替換累積緩衝區中的值.
GL_RETURN--累積緩衝區中的值乘以value, 結果放在顏色緩衝區中.
GL_ADD和AL_MULT--累積緩衝區中的值與value相加或者相乘,結果寫回累積緩衝區. 另GL_MULT的結果截取[-1.0. 1.0].GL_ADD的結果不截取.

10.3.1 場景抗鋸齒


首先清除累積緩衝區, 並啓用前緩衝區用於讀取和寫入.
然後循環執行幾次(例如n次)代碼, 對圖像進行微移和繪製.
對數據進行累積的方法:
glAccum(GL_ACCUM, 1.0/n);    // 繪製到不會顯示的顏色緩衝區中, 避免顯示中間圖像.
並最終調用
glAccum((GL_RETURN, 1.0);    // 繪製到可顯示的顏色緩衝區中(或即將交換的後緩衝區).

可提供一用戶接口, 來顯示每次圖像累積之後所獲得的改善, 如圖像足夠滿意, 可隨時終止累積.

本例主要是逐步在窗口累積各顏色分量.
一共累積八次,且其中每次都用j8數組的數據微移場景, 使用glFrustum函數可以是的我們場景不必對稱.

正交投影的偏移只需要用glTranslatef()移動一個像素內的偏移即可.

下圖爲沒有反鋸齒沒有用累積緩存的圖像

 2

下圖爲使用了累積緩存反鋸齒的圖像

1

 

累積緩存我分步驟顯示,看看效果

 3 4 5 6 7

10.3.2 運動模糊


按照相同的方式設置累積緩衝區, 但不是對圖像進行空間上的微移, 而是進行時間上的微移.
glAccum(GL_MULT, decayFactor); 
這樣隨着場景繪製到累積緩衝區中,整個場景越來越模糊. 其中decayFactor是個0.0到1.0之間的數字, 其值越小, 運動速度越快.
然後使用
glAccum(GL_RETURN, 1.0); 
轉移到眼色緩衝區中.

9

10.3.3 景深


距離聚焦平面越遠,物體就越模糊.

accPerspective函數
第五個和第六個參數表示在x和y方向上微移, 實現場景抗鋸齒
第九個參數設定聚焦平面.
模糊程度有第七個和第八個參數決定, 由這兩個參數的乘積決定.

10

10.3.4 柔和陰影


多個光源所產生的柔和陰影-- 可以多次渲染場景,每次只打開一個光源, 然後將渲染結果累積起來.

10.3.5 微移


樣本的微移值


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章