OpenGL模板缓冲区---StencilBuffer
来源:互联网 发布:徐州市网络电子备课 编辑:程序博客网 时间:2024/05/21 11:30
前言
在OpenGL中存在着多种缓冲区,这些缓冲区大致分为:
颜色缓冲区:用于绘图的缓冲区,它包含了颜色索引或者RGBA颜色数据。
深度缓冲区:存储每个像素的深度值,当启动深度测试时,片段像素深度值和深度缓冲区深度值进行比较,决定片段哪些像素点数据可以替换到颜色缓冲区中。
模板缓冲区(Stencil Buffer):与颜色缓冲区和深度缓冲区类似,模板缓冲区可以为屏幕上的每个像素点保存一个无符号整数值。这个值的具体意义视程序的具体应用而定。在渲染的过程中,可以用这个值与一个预先设定的参考值相比较,根据比较的结果来决定是否更新相应的像素点的颜色值。这个比较的过程被称为模板测试。模板测试发生在透明度测试(alpha test)之后,深度测试(depth test)之前。如果模板测试通过,则相应的像素点更新,否则不更新。就像使用纸板和喷漆一样精确的混图一样,当启动模板测试时,通过模板测试的片段像素点会被替换到颜色缓冲区中,从而显示出来,未通过的则不会保存到颜色缓冲区中,从而达到了过滤的功能。下图描述了模板缓冲区的原理:
累积缓冲区:累积缓冲区允许你把渲染到颜色缓冲区的值,拷贝到累积缓冲区。在多次拷贝操作到累积缓冲区时,可以用不同方式的把颜色缓冲区内容和当前累积缓冲区的内容进行重复混合
读者一定还记得在写OpenGL程序的时候熟悉的glClear命令吧,经常需要传入的缓冲区类型包括:- 颜色缓冲区 GL_COLOR_BUFFER_BIT
- 深度缓冲区 GL_DEPTH_BUFFER_BIT
- 模板缓冲区GL_STENCIL_BUFFER_BIT
为了方便可以在一个命令中清除多个缓冲区(使用|操作符)
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
模板缓冲区
了解模板缓冲区的原理,下面我们看看在OpenGL中如何使用模板缓冲区进行测试。OpenGL中与模板缓冲区相关的函数有如下几个:
- // 默认模板缓冲区并未开启需要使用glEnable开启
- glEnable(GL_STENCIL_TEST);
- // 设置模板缓冲区的写入掩码:当为false时禁止在Stencil Buffer中写入(默认0xff)
- glStencilMask(0xFF);
- // 清除Stencil Buffer的值默认为0
- glClearStencil(clearStencilValue);
- // 默认值GL_ALWAYS, 0, 0xFF, 总是通过Stencil测试
- glStencilFunc(func, ref, mask);
- // 默认GL_KEEP, GL_KEEP, GL_KEEP, 不会改变Stencil Buffer
- glStencilOp(fail,zfail,zpass);
- // 清除StencilBuffer
- glClear(GL_STENCIL_BUFFER_BIT);
- //哈哈:来我这儿考试吧,通过的和不通过的都去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: 掩码值(会与参考值和模板缓冲区内的值先作与操作,在参考func中的参数测试是否通过测试)
- //呵呵:来看看怎么处理你们:
- 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(按位取反)
1. 模板缓冲区测试失败了:那么执行glStencilOp中第一个参数fail的操作方式;
2.模板缓冲区测试通过了:那么执行glStencilOp中第二个参数zfail的操作方式;
3.模板缓冲区测试通过了:那么执行glStencilOp中第三个参数zpass的操作方式;
注意三者的共同点都是对模板缓冲区进行操作。
如果模板缓冲区测试失败了,那么对颜色缓冲区就不会写入任何值。利用这个特点,我们可以如下操作:
- // 设置模板缓冲区测试失败,后续的绘制操作只会在模板缓冲区中进行
- glStencilFunc(GL_NEVER, 0x0, 0x0);
- glStencilOp(GL_INCR, GL_INCR, GL_INCR);
- //绘制模板对象
- draw_template_object()
- //接着在非模板对象的缓冲区绘制,这样就可以把模板部分空出来,有种被模板楼空的感觉
- glStencilFunc(GL_NOTEQUAL, 0x1, 0x1);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
下面通过一个示例来演示如何使用模板缓冲区:
- glClearStencil(0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glEnable(GL_STENCIL_TEST);
- glStencilFunc(GL_NEVER, 0x0, 0x0);
- glStencilOp(GL_INCR, GL_INCR, GL_INCR);
- glColor3f(1.0f, 1.0f, 1.0f);
- GLdouble dRadius = 1.0;
- //在模板缓冲区绘制(因为模板测试失败不能在颜色缓冲区写入)
- glBegin(GL_LINE_STRIP);
- for (double angle = 0.0; angle < 400.0; angle += 0.1)
- {
- glVertex3d(dRadius * cos(angle), dRadius * sin(angle), 0.0);
- dRadius *= 1.002;
- }
- glEnd();
- //现在与颜色缓冲区在模板缓冲区对应处有线的地方不会绘制
- glStencilFunc(GL_NOTEQUAL, 0x1, 0x1);
- glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
- glColor3f(0.0, 1.0, 1.0);
- glRectf(x, y, x+_rectSize, y-_rectSize);
这个颜色缓冲区中的矩形的一部分(条纹线)并没有被绘制,因为这部分对应到Stencil Buffer里面的值是1,而值等于1的地方不会通过模板缓冲区测试(因此并不会在颜色缓冲区中被绘制出来)
下面我们看看在osg中怎么实现同样的效果:
- osg::Geometry *lineStripGeometry = new osg::Geometry;
- osg::Vec3Array *lineVertexArray = new osg::Vec3Array;
- double dRadius = 0.1;
- for (float angle = 0.0; angle < 400.0; angle += 0.1)
- {
- lineVertexArray->push_back(osg::Vec3(dRadius * cos(angle), dRadius * sin(angle), 0));
- dRadius *= 1.002;
- }
- osg::Vec4Array *lineColorArray = new osg::Vec4Array;
- lineColorArray->push_back(osg::Vec4(1.0, 1.0, 1.0, 1.0));
- lineStripGeometry->setVertexArray(lineVertexArray);
- lineStripGeometry->setColorArray(lineColorArray);
- //OSG 3.2之后的版本在setColorArray中设置绑定方式
- lineStripGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);
- lineStripGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, lineVertexArray->size()));
- lineStripGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
- //添加模板测试
- osg::Stencil *lineStripStencil = new osg::Stencil;
- lineStripStencil->setFunction(osg::Stencil::NEVER, 0x0, 0x0);
- lineStripStencil->setOperation(osg::Stencil::INCR, osg::Stencil::INCR, osg::Stencil::INCR);
- lineStripGeometry->getOrCreateStateSet()->setAttributeAndModes(lineStripStencil);
- //////////////////////////////////////////////////////////////////////////
- osg::Geometry *quadGeometry = new osg::Geometry;
- osg::Vec3Array *quadVertexArray = new osg::Vec3Array;
- quadVertexArray->push_back(osg::Vec3(0, 0, 0));
- quadVertexArray->push_back(osg::Vec3(25, 0, 0));
- quadVertexArray->push_back(osg::Vec3(25, 25, 0));
- quadVertexArray->push_back(osg::Vec3(0, 25, 0));
- osg::Vec4Array *quadColorArray = new osg::Vec4Array;
- quadColorArray->push_back(osg::Vec4(0.0, 1.0, 1.0, 1.0));
- quadGeometry->setVertexArray(quadVertexArray);
- quadGeometry->setColorArray(quadColorArray);
- quadGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);
- quadGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
- quadGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
- osg::Stencil *quadStencil = new osg::Stencil;
- quadStencil->setFunction(osg::Stencil::NOTEQUAL, 0x1, 0x1);
- quadStencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);
- quadGeometry->getOrCreateStateSet()->setAttributeAndModes(quadStencil);
- osg::Geode *geode = new osg::Geode;
- geode->addDrawable(lineStripGeometry);
- geode->addDrawable(quadGeometry);
0 0
- OpenGL模板缓冲区---StencilBuffer
- OpenGL模板缓冲区---StencilBuffer
- OpenGL模板缓冲区---StencilBuffer
- OpenGL模板缓冲区
- opengl模板缓冲区
- OpenGL: 模板缓冲区
- OpenGL: 模板缓冲区
- OPenGL模板缓冲区示例程序
- OpenGL: 模板缓冲区的理解
- OpenGL模板缓冲区与模板测试
- OpenGL模板缓冲区与模板测试
- OpenGL学习笔记——StencilBuffer
- 对OpenGL中模板缓冲区解释
- OpenGL学习二十九:模板缓冲区与模板测试
- opengl缓冲区
- Opengl缓冲区
- OpenGL中关于模板缓冲区的详细解释
- OpenGL 学习笔记3_5(缓冲区相关) 模板缓冲区待详细分析
- Hibernate注解详细解析
- 定时任务
- java虚拟机类加载过程内存情况底层源码分析及ClassLoader讲解
- 如何与离职员工面谈沟通?
- Execution failed for task:"app:clean"
- OpenGL模板缓冲区---StencilBuffer
- Tomcat 7 源码分析 - 下载 tomcat source code 并导入eclipse
- 仿QQ左滑出现删除,只能有一条记录显示有左滑js实现
- 我们都忽略了Html5的力量,如果只看成一种技术就大错特错了!
- C、C++动态分配函数暨几种参数传递疑难解析
- Eclipse导入Tomcat源码
- 华为服务器RH5885 V3进入BIOS
- 第一个Android app,计算器~
- 自己利用opencv2.4.4和MFC写的视频目标标注助手