您的位置:首页 > 其它

使用模板缓冲区时需要注意的几个问题

2007-12-30 23:25 701 查看
使用模板模板缓冲时需要注意的几个问题
-----作者: 熊 斌 2007.12.30 xiongbincsu@yahoo.com.cn
也许你使用过模板缓冲区,但是你真正懂得它的正确用法吗?

本人根据实践总结出下面几个问题,希望对大家能有所帮助:

1. 使用模板缓冲区的步骤

2.glStencilFunc中的参数意义,及如何选择合理参数?

3.glStencilOp中的参数意义及选用.

====================================================================

问题1:

简而言之:

1)指定默认模板值,用其清除模板缓冲区,

2)开启模板测试功能, 指定模板比较函数, 指定模板测试失败后对相应位置的模板值的操作方式.

3)用绘图命令绘制一个模板图形

4) 绘制其他图形

下面详细叙述:

如果你要使用一个模板缓冲区,那么首先你要在使用之前象清除颜色缓冲区一样,把原来缓冲区里的无效数据给清理干净,这就是在调用glClear() 时 加上GL_STENCIL_BUFFER_BIT. 也就是象这样:

glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)

与颜色缓冲区类似,你在使用这个函数之前也要指定一个默认填充值, 你可以这样指定 glClearStencil(0);

当然你不一定要用0,就像你清除颜色缓冲区时不一定要指定glClearColor(0,0,0).一样,你要根据你的需要来设定.

设定好默认值后,并用这个默认值将模板模板缓冲区填满以后,你就可以在你需要的地方开始使用它了:

glEnable(GL_STENCIL_TEST);

接下来我们要生成我们的模板,实际上就是通过一组绘图命令,来绘出一个图像,把它当作模板. 比如我们要生成一个镂空的花窗,那么我们可以把这个花窗需要空的部分绘出来,当作模板,使得在进行后续绘图时,落到这个模板上的图像不被绘制,就形成了镂空.. 好了,扯远了, 这只是告诉你什么叫模板....... 呵呵,好像没这个必要???

因为我们在创造我们的模板时使用的也是绘图命令,有时候,我们并不想让这个模板本身被别人看见, (一个图形要被看见 等于 它被写入颜色缓冲并最终被交换到屏幕上来)..为了不让这些创建模板的代码被显示为图形,我们需要禁止颜色缓冲的写入, 这可以通过下面的语句做到

glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); 它使所有的颜色通道都不可以写入

同理,如果我们不希望绘制模板的代码影响深度缓冲区,那么我们可以调用 glDisable(GL_DEPTH_TEST); 来禁止深度缓存的写入.

设置好这些后,我们准备开始绘制模板,

绘制模板之前, 我们需要给模板本身所绘制的图形指定一个模板值,为什么呢? 因为模板测试类似与深度测试, 它是通过把已有的模板缓冲区的值,与将要绘制的图形的模板值相比较,然后只绘制使得比较结果为真的那些图像...

现在模板缓冲区里面全是默认值,那么我们需要给模板本身指定一个值,那么在以后进行绘制时,就可以拿要绘制的图像的模板值与这个值做比较从而进行取舍了...

而怎么样给绘制的图像赋上模板值,并进行比较呢? 这就是通过2,3 问题中所述的两个函数来进行, 请接着往下看...

问题2. glStencilFunc 用法

glStencilFunc的原形是: glStencilFunc( GLenum func, GLint ref, GLuint mask);

它的作用就是来指定 模板测试 的比较函数, 这些函数用来将 "当前绘制图像的模板值" 与 "要写入位置的模板值" 进行比较 以得到一个Ture Or False 值 , 这个比较函数由第一个参数指定,它是一个 枚举值,可选的有 GL_GREATER ,GL_LESS 等, 第二个就是紧跟着这个函数的绘图函数所绘图形,的模板值, 它用来与要绘制的目标位置的模板值,用第一个参数指定的函数进行比较,得到结果.. 但是这种比较并不是直接拿这两个值去比, 假如要绘制的目标位置的模板值是B,第二个参数指定的是A, 那么比较是这样进行的, 先将 A与第三个参数 mask 进行AND操作 并同时将 B与mask 进行与操作,然后按指定的比较函数func比较结果 ,

也就是 ((ref & mask) op (svalue & mask))

如果A 与B的比较结构为真,则写入,假则不写入...

问题3: glStencilOp用法

glStencilOp() 函数的原形为: glStencilOp(GLenum fail , GLenum zfail, GLenum zPss );

它的作用是用来指定,当某些图元在绘制的时候,如果模板测试失败(或者深度测试失败),它怎么修改其打算写入的位置的模板值. 它的三个参数 分别指定了,当模板测试失败了 该如何修改, 深度测试失败了如何修改,以及 深度测试如果成功又该怎么修改.... 后面两个参数也就是说,就算模板测试通过,我们也可以通过深度测试的测试结果修改模板值..

它们的可选值为: GL_KEEP(保持不变), GL_DEC(减少) , GL_INCR(增加) ,GL_REPLACE(替换),

特别需要注意的是: 这些操作在每个面片被写入的时候都会进行,如果你使用GL_INCR , 可能你只绘制了一个模型,但是,这个模型有几个面片在深度上重叠,那么在每次写入这些面片时,都会引起一次GL_INCR, 也就是模板值 +1 , 如果你不曾注意到这个问题,那么你在测试函数glStencilFunc 中时选用 GL_EQUAL 就会得到不正确的结果.. 如果你需要使用GL_EQUAL 建议你在本函数中选用 GL_REPLACE ,这个变量引起函数用 glStencilFunc 中指定的 ref 值来替代 当前要绘制位置的模板值, 这样多次操作不会有影响....
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: