对opengl模板缓冲原理小感

时间:2021-03-02 01:30:01
 

这篇文章是针对在你看了书本或者其他资料对opengl模板原理的一般性介绍后但又不理解模板到底是怎么工作的情况而写的,所有相关函数的原型及参数不再做详细介绍。

 opengl的模板就像是挡在屏幕前的一块挡板,如果挡板是透明的,则可以看到整个屏幕的图像,如果是部分透明部分不透明,则只可以看到透明部分的屏幕图像。

为了抛弃书本或其他叙述性文字的笼统介绍,这里从代码解析角度分析,相信更能让人明白模板的原理:

 

 glClearStencil(0.0f);

 

 glEnable(GL_STENCIL_TEST);

 glClear(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

 

 glStencilFunc(GL_NEVER,0x0,0x0);

 glStencilOp(GL_INCR,GL_INCR,GL_INCR);//

 

 

 glColor3f(1.0f,1.0f,1.0f);

 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,0x1);

 glStencilOp(GL_INCR,GL_INCR,GL_INCR);//

 

 

 glColor3f(1.0f,0.0f,0.0f);

 glRectd(x11,y11,x11+rsize,y11+rsize);

 

 

代码中第一句glClearStencil(0.0f)是将整个模板上所有值的清楚值初始化为0.0,为后面的比较测试提供初值。下面来看看2次比较关键的函数调用代码:

第一次

glStencilFunc(GL_NEVER,0x0,0x0);

glStencilOp(GL_INCR,GL_INCR,GL_INCR);//

这两句对后面for循环画图glBegin(GL_LINE_STRIP)和glVertex2d(dRadius*cos(dAngel),dRadius*sin(dAngel))的影响就是:第一句glStencilFunc(GL_NEVER,0x0,0x0)第一个参数设为GL_NEVER是让所有像素都因为模板值不通过测试而不显示,也就是这块模板的任何位置是不透明的,你不能看到绘图代码所绘制的任何图像像素。而glStencilOp(GL_INCR,GL_INCR,GL_INCR) 参数设为GL_INCR则是将所画的曲线上的所有像素的位置对应的模板位置的模板值都加1而变成1,而其他没有像素的地方所对应的模板位置的模板值保持原值0.0不变。

 

第二次

glStencilFunc(GL_NOTEQUAL,0x1,0x1);

glStencilOp(GL_INCR,GL_INCR,GL_INCR);//

第一次相关模板函数的作用后,只在所画曲线对应位置的模板值因加1变成了1,模板上其他地方的模板值则依然为0.0,所以这次调用模板相关函数的影响就是glStencilFunc(GL_NOTEQUAL,0x1,0x1)将所有模板中的模板值与mask参数0x1进行与运算将结果与参考值0x1比较,不相等(第一个参数GL_NOTEQUAL)的就通过(也就是变透明),相等的就不通过(也就是不透明),所以所画曲线对应位置的模板因模板值为1是而测试失败,也就是说后续画图代码glRectd(x11,y11,x11+rsize,y11+rsize)绘制的像素所在的位置如果跟模板值为1的模板位置一样的话,那么这些像素是不会显示的。而其他地方的模板位置因为值为0.0都是通过的,那么处在这些位置上的图像像素就可以显示并看到