osg 使用整理 (5):模板测试与边缘效果
1 模板测试
在渲染管线中,模板测试在片段着色器后执行,通过像素与模板缓冲中的模板值比较,选择性丢弃或者保存这个像素颜色。我们可以通过更新模板测试来获得一些很有意思的效果。下图为LearnOpenGL网站一个例子。
可以发现,颜色缓冲经过模板测试后,只保留了模板值为1的像素颜色。
使用模板缓冲通常的流程:
a 开启模板测试
glEnable(GL_STENCIL_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
b 设置模板测试函数,决定如何使用模板缓冲丢弃片段
glStencilMask(0xFF); // 每一位写入模板缓冲时都保持原样
glStencilMask(0x00); // 每一位在写入模板缓冲时都会变成0(禁用写入)
/* brief:模板缓冲测试函数
para[in]: func 测试规则
para[in]: ref 模板测试参考值
para[in]: mask 掩码
*/
glStencilFunc(GLenum func, GLint ref, GLuint mask)
函数 | 描述 |
---|---|
GL_ALWAYS | 永远通过深度测试 |
GL_NEVER | 永远不通过深度测试 |
GL_LESS | 在片段深度值小于缓冲的深度值时通过测试 |
GL_EQUAL | 在片段深度值等于缓冲区的深度值时通过测试 |
GL_LEQUAL | 在片段深度值小于等于缓冲区的深度值时通过测试 |
GL_GREATER | 在片段深度值大于缓冲区的深度值时通过测试 |
GL_NOTEQUAL | 在片段深度值不等于缓冲区的深度值时通过测试 |
GL_GEQUAL | 在片段深度值大于等于缓冲区的深度值时通过测试 |
c 渲染模型,更新模板缓冲,更新函数为
/* brief:模板缓冲更新函数
para[in]: sfail 模板测试失败时采取的行为
para[in]: dpfail 模板测试通过,但深度测试失败时采取的行为
para[in]: sfail 模板测试和深度测试都通过时采取的行为
*/
glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass)
行为 | 描述 |
---|---|
GL_KEEP | 保持当前储存的模板值 |
GL_ZERO | 将模板值设置为0 |
GL_REPLACE | 将模板值设置为glStencilFunc函数设置的ref 值 |
GL_INCR | 如果模板值小于最大值则将模板值加1 |
GL_INCR_WRAP | 与GL_INCR一样,但如果模板值超过了最大值则归零 |
GL_DECR | 如果模板值大于最小值则将模板值减1 |
GL_DECR_WRAP | 与GL_DECR一样,但如果模板值小于0则将其设置为最大值 |
GL_INVERT | 按位翻转当前的模板缓冲值 |
2 osg::Effect 后处理效果类
osg::Effect类如作者所述,用于实现特殊的渲染效果,其派生包括散射光,亮光,卡通等。它是一系列属性状态stateset的集合,允许采用多个osg::technique封装渲染状态,不同technique可以使用不同的渲染上下文。在使用时,只需要创建所需effect实例,然后添加到场景树中,最后把这个effect要影响的模型节点挂载到effect节点上。要创建自定义渲染效果类,可以继承osg::Effect类,然后重写 define_techniques方法,其中可以使用自定义的technique类,添加technique的顺序十分关键。
勾勒对象的轮廓是用于在游戏,多媒体与工业应用表示特殊效果的实践技术。OpenGL的一个实现是在stencil buffer中写入固定值,然后使用细边线渲染对象。在两遍渲染过程之后,对像周围的轮廓就会显示出来。幸运的是,该效果已经由osgFX库中的osgFX::Effect的派生类osgFX::Outline类实现了。下面是使用示例。
#include <osg/Group>
#include <osgDB/ReadFile>
#include <osgFX/Outline>
#include <osgViewer/Viewer>
void main()
{
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile( "cessna.osg" );
osg::ref_ptr<osgFX::Outline> outline = new osgFX::Outline;
outline->setWidth( 8 );
outline->setColor( osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) );
outline->addChild( model.get() );
osg::DisplaySettings::instance()->setMinimumNumStencilBits( 1 );
osgViewer::Viewer viewer;
viewer.getCamera()->setClearMask(
GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
viewer.setSceneData( outline.get() );
return viewer.run();
}
标签:缓冲,模板,测试,深度,GL,osg,OSG
From: https://www.cnblogs.com/wangxydela/p/17537048.html