OpenGL模板緩衝區與模板測試

原文地址:http://www.blogjava.net/qileilove/archive/2014/01/23/409269.html

幀緩衝區有許多緩衝區構成,這些緩衝區大致分爲:

    顏色緩衝區:用於繪圖的緩衝區,它包含了顏色索引或者RGBA顏色數據。
     深度緩衝區:存儲每個像素的深度值,當啓動深度測試時,片段像素深度值和深度緩衝區深度值進行比較,決定片段哪些像素點數據可以替換到顏色緩衝區中。
  模板緩衝區:就像使用紙板和噴漆一樣精確的混圖一樣,當啓動模板測試時,通過模板測試的片段像素點會被替換到顏色緩衝區中,從而顯示出來,未通過的則不會保存到顏色緩衝區中,從而達到了過濾的功能。
  累積緩衝區:累積緩衝區允許你把渲染到顏色緩衝區的值,拷貝到累積緩衝區。在多次拷貝操作到累積緩衝區時,可以用不同方式的把顏色緩衝區內容和當前累積緩衝區的內容進行重複混合

  模板測試
  模板測試只有存在模板緩衝區的情況下進行,模板測試把像素存儲在模板緩衝區的點與一個參考值進行比較(glStencilFunc),根據測試結果,對模板緩衝區的值進行響應的修改glStencilOp
  void glStencilFunc (GLenum func, GLint ref, GLuint mask);
  func:GL_NEVER 從來不能通過
  GL_ALWAYS 永遠可以通過(默認值)
  GL_LESS 小於參考值可以通過
  GL_LEQUAL 小於或者等於可以通過
  GL_EQUAL 等於通過
  GL_GEQUAL 大於等於通過
  GL_GREATER 大於通過
  GL_NOTEQUAL 不等於通過
  ref: 參考值
  mask:掩碼,書上說模板測試只在哪些對應爲1的位上進行。(不是很確定具體作用)
  舉例:glStencilFunc (GL_LESS, 1.0, 1.0);模板緩衝區對應的像素點的值如果小於1.0,則通過模板測試
  void glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
  fail模板測試未通過時該如何變化;zfail表示模板測試通過,但深度測試未通過時該如何變化;zpass表示模板測試和深度測試或者未執行深度測試均通過時該如何變化
  GL_KEEP(不改變,這也是默認值)
  GL_ZERO(回零)
  GL_REPLACE(使用測試條件中的設定值來代替當前模板值)
  GL_INCR(增加1,但如果已經是最大值,則保持不變),
  GL_INCR_WRAP(增加1,但如果已經是最大值,則從零重新開始)
  GL_DECR(減少1,但如果已經是零,則保持不變),
  GL_DECR_WRAP(減少1,但如果已經是零,則重新設置爲最大值)
  GL_INVERT(按位取反)
  未啓用模板緩衝區

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0, 0, -20);
glColor3f(1.0f,1.0f,1.0f);
dRadius = 5.0*(sqrt(2.0)/2.0);
glBegin(GL_LINE_STRIP);
for (dAngel=0;dAngel<380.0;dAngel+=0.1)
{
glVertex2d(dRadius*cos(dAngel),dRadius*sin(dAngel));
dRadius*=1.003;
}
glEnd();
glColor3f(1.0f,0.0f,0.0f);
glRectf(-5,-5,5,5);

 

初始清除背景填充顏色爲藍色
  以上這部分代碼可以用如下3張圖表示繪製的過程
  開啓模板緩衝區
void init()
{
glClearColor(0,0,1.0,0);
glClearStencil(0);
glClearDepth(1.0f);
glEnable(GL_STENCIL_TEST);
}
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);//1
glLoadIdentity();
glTranslatef(0, 0, -20);
glStencilFunc(GL_NEVER,0x0,0xFF);  //2
glStencilOp(GL_INCR,GL_INCR,GL_INCR);//3
glColor3f(1.0f,1.0f,1.0f);
dRadius = 5.0*(sqrt(2.0)/2.0);
glBegin(GL_LINE_STRIP);
for (dAngel=0;dAngel<380.0;dAngel+=0.1)
{
glVertex2d(dRadius*cos(dAngel),dRadius*sin(dAngel));
dRadius*=1.003;
}
glEnd();
glStencilFunc(GL_NOTEQUAL,0x1,0xFF);  //4
glStencilOp(GL_KEEP,GL_KEEP,KEEP); //5
glColor3f(1.0f,0.0f,0.0f);
glRectf(-5,-5,5,5);


  當執行到1處,3個緩衝區都被清空
  顏色緩衝區:每個像素點顏色都是藍色
  深度緩衝區:每個像素點深度都是1.0
  模板緩衝區:每個像素點模板值都是0
  執行到2,3處,模板測試條件是從不通過測試,如果不通過測試結果是模板值+1
  接着應用模板測試進行繪製一組點,由於模板測試條件是從不通過測試,所以顏色緩衝器值不會變化,但是繪製的點對應的像素點的模板值變爲1,此時
  顏色緩衝區:每個像素點顏色都是藍色
  深度緩衝區:每個像素點深度都是1.0
  模板緩衝區:點數組對應的模板值是1,其他區域像素點的模板值還是0
  執行到4,5處,模板測試條件是模板值不一定1則通過測試,如果不通過測試結果是模板值+1
   接着應用剛纔的模板測試進行繪製一個(-5,-5,5,5)的矩形,在這個矩形區域內,像素點的模板值分爲2中,值爲1的是上1步的點數組。值爲0的是 上一步非的點數組像素點。那個根據模板測試條件,模板值爲0的像素點通過測試,可以進行替換顏色緩衝區的值(替換成紅色),模板值爲0的像素點不能通過測 試,因此不能改變顏色緩衝區的值
  顏色緩衝區:(-5,-5,5,5)區域內 模板值爲0的像素點爲紅色,其他區域都爲藍色
  深度緩衝區:每個像素點深度都是1.0
  模板緩衝區:點數組對應的模板值是1,其他區域像素點的模板值還是0
模板查詢
  可以用glGetInteger函數獲取與模板相關的參數值
#include "header.h"
float dRadius =0;
float dAngel;
float aspect=0;
void init()
{
glClearColor(0,0,1.0,0);
glClearStencil(0);
glClearDepth(1.0f);
glEnable(GL_STENCIL_TEST);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0, 0, -20);
////glStencilFunc(GL_ALWAYS, 0,0x00);
glStencilFunc(GL_NEVER,0x0,0xFF);
glStencilOp(GL_INCR,GL_INCR,GL_INCR);
glColor3f(1.0f,1.0f,1.0f);
dRadius = 5.0*(sqrt(2.0)/2.0);
glBegin(GL_LINE_STRIP);
for (dAngel=0;dAngel<380.0;dAngel+=0.1)
{
glVertex2d(dRadius*cos(dAngel),dRadius*sin(dAngel));
dRadius*=1.003;
}
glEnd();
glStencilFunc(GL_NOTEQUAL,0x1,0xFF);
glStencilOp(GL_INCR,GL_INCR,GL_INCR);//
glColor3f(1.0f,0.0f,0.0f);
glRectf(-5,-5,5,5);
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0,0,w,h);
aspect = (w*1.0)/h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, aspect, 1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
//glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_STENCIL);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_STENCIL|GLUT_DEPTH);
glutInitWindowPosition(200,200);
glutInitWindowSize(600,600);
glutCreateWindow("模板緩衝區與模板測試");
glewInit();
init();
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
return 0;
}


發佈了54 篇原創文章 · 獲贊 13 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章