OSG学习:用多通道(multiple passes)实现透明度
来源:互联网 发布:软件开发做什么 编辑:程序博客网 时间:2024/06/06 15:41
osgFX库提供了一个用于多通道渲染(multi-pass rendering)的框架。每个你想要渲染的子图都应该被添加到osgFX::Effect节点,多通道技术的定义和使用都可以在这个节点中完成。你可能已经熟悉一些预定义的效果,例如osgFX::Scribe和osgFX::Outline。但是在这个教程中,我们的任务是我们自己设计一个多通道技术。这就是所谓的多通道透明度,当我们在透明模式(transparent mode)下它可以消除一些错误。
如何使用
- 添加必要的头文件:
#include <osg/BlendFunc>#include <osg/ColorMask>#include <osg/Depth>#include <osg/Material>#include <osgDB/ReadFile>#include <osgFX/Effect>#include <osgViewer/Viewer>
2.首先,我们将提供一个新技术,这个技术继承于osgFX::Technique节点。validate()方法是用于检查现在硬件是否支持这个技术,如果一切正常会返回true。
class TransparencyTechnique : public osgFX::Technique{public:TransparencyTechnique() : osgFX::Technique() {}virtual bool validate( osg::State& ss ) const{return true;}protected:virtual void define_passes();};
3.在这个类中,另一个必须有的方法是define_passes()。这是用于定义多通道的。在这个教程中,我们将有两个通道:一个是取消颜色掩膜(color mask)以及如果深度缓冲区值(depth buffer value)小于现在的就记录下来;另一个将使用颜色缓冲区,但只有在深度值等于已经记录下来的值的时候写进去。(the second one will enable the useage of the color buffer but only to write to it when the depth value equals to the recorded one.)
osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;ss->setAttributeAndModes( new osg::ColorMask(false, false, false, false) );ss->setAttributeAndModes( new osg::Depth(osg::Depth::LESS) );addPass( ss.get() );ss = new osg::StateSet;ss->setAttributeAndModes( new osg::ColorMask(true, true, true, true) );ss->setAttributeAndModes( new osg::Depth(osg::Depth::EQUAL) );addPass( ss.get() );
- 我们设计完技术之后,现在我们可以声明effect类,把技术添加到它的define_techniques()方法中。这里的META_Effect宏用于定义effect的基本方法:库名,类名,作者名和描述。
class TransparencyNode : public osgFX::Effect{public:TransparencyNode() : osgFX::Effect() {}TransparencyNode( const TransparencyNode& copy,const osg::CopyOp op=osg::CopyOp::SHALLOW_COPY ): osgFX::Effect(copy, op) {}META_Effect( osgFX, TransparencyNode, "TransparencyNode","", "" );protected:virtual bool define_techniques(){addTechnique(new TransparencyTechnique);return true;}};
- 在main函数中,我们将使用景点的Cessna模型。不过,为了使它透明,我们将在上面添加一个新的材料,把散射颜色(diffuse color)的alpha通道设置为小于1的值,以及把TRANSPARENT_BIN这个hint应用到state set中。
osg::Node* loadedModel = osgDB::readNodeFile( "cessna.osg" );osg::ref_ptr<osg::Material> material = new osg::Material;material->setAmbient( osg::Material::FRONT_AND_BACK,osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) );material->setDiffuse( osg::Material::FRONT_AND_BACK,osg::Vec4(1.0f, 1.0f, 1.0f, 0.5f) );loadedModel->getOrCreateStateSet()->setAttributeAndModes(material.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE );loadedModel->getOrCreateStateSet()->setAttributeAndModes(new osg::BlendFunc );loadedModel->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN );
6.创建一个新定义类的实例并添加到模型中。
osg::ref_ptr<TransparencyNode> fxNode = new TransparencyNode;fxNode->addChild( loadedModel );//Start the viewer now.osgViewer::Viewer viewer;viewer.setSceneData( fxNode.get() );return viewer.run();
7.现在你将看到适当渲染过的透明的Cessna。
全部代码:
#include <osg/BlendFunc>#include <osg/ColorMask>#include <osg/Depth>#include <osg/Material>#include <osgDB/ReadFile>#include <osgFX/Effect>#include <osgViewer/Viewer>#include "CommonFunctions"class TransparencyTechnique : public osgFX::Technique{public: TransparencyTechnique() : osgFX::Technique() {} virtual bool validate( osg::State& ss ) const { return true; }protected: virtual void define_passes() { osg::ref_ptr<osg::StateSet> ss = new osg::StateSet; ss->setAttributeAndModes( new osg::ColorMask(false, false, false, false) ); ss->setAttributeAndModes( new osg::Depth(osg::Depth::LESS) ); addPass( ss.get() ); ss = new osg::StateSet; ss->setAttributeAndModes( new osg::ColorMask(true, true, true, true) ); ss->setAttributeAndModes( new osg::Depth(osg::Depth::EQUAL) ); addPass( ss.get() ); }};class TransparencyNode : public osgFX::Effect{public: TransparencyNode() : osgFX::Effect() {} TransparencyNode( const TransparencyNode& copy, const osg::CopyOp op=osg::CopyOp::SHALLOW_COPY ) : osgFX::Effect(copy, op) {} META_Effect( osgFX, TransparencyNode, "TransparencyNode", "", "" );protected: virtual bool define_techniques() { addTechnique(new TransparencyTechnique); return true; }};int main( int argc, char** argv ){ osg::Node* loadedModel = osgDB::readNodeFile( "cessna.osg" ); osg::ref_ptr<osg::Material> material = new osg::Material; material->setAmbient( osg::Material::FRONT_AND_BACK, osg::Vec4(0.0f, 0.0f, 0.0f, 1.0f) ); material->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4(1.0f, 1.0f, 1.0f, 0.5f) ); loadedModel->getOrCreateStateSet()->setAttributeAndModes( material.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE ); loadedModel->getOrCreateStateSet()->setAttributeAndModes( new osg::BlendFunc ); loadedModel->getOrCreateStateSet()->setRenderingHint( osg::StateSet::TRANSPARENT_BIN ); osg::ref_ptr<TransparencyNode> fxNode = new TransparencyNode; fxNode->addChild( loadedModel ); osgViewer::Viewer viewer; viewer.setSceneData( fxNode.get() ); return viewer.run();}
原理
多通道透明度技术会绘制物体两次。第一个通道(见后面代码)仅仅更新深度缓冲区(depth buffer),以及找到最前面的多边形:
osg::ref_ptr<osg::StateSet> ss = new osg::StateSet;ss->setAttributeAndModes( new osg::ColorMask(false, false, false, false) );ss->setAttributeAndModes( new osg::Depth(osg::Depth::LESS) );addPass( ss.get() );
第二个通道将会绘制进颜色缓冲区(color buffer),但由于在第一个通道中设置的深度值,只有前面的多边形能够通过深度检测,它们的颜色将被绘制,与现在的混合。这避免了我们之前讨论过的顺序问题。代码片段如下:
ss = new osg::StateSet;ss->setAttributeAndModes( new osg::ColorMask(true, true, true, true) );ss->setAttributeAndModes( new osg::Depth(osg::Depth::EQUAL) );addPass( ss.get() );
选自《OSG3 Cookbook》第六章
- OSG学习:用多通道(multiple passes)实现透明度
- OSG 透明度
- OSG透明度
- osg开启透明度
- osg 透明度显示方式
- 修改材质通道的透明度
- osg多光源的实现
- osg学习
- OSG学习
- 图像不能包含 alpha 通道或透明度
- 图像不能包含 alpha 通道或透明度
- 图像不能包含 alpha 通道或透明度
- 图片去掉alpha通道或透明度
- 图像不能包含alpha通道或透明度
- 去除图像中的alpha通道或透明度
- opencv学习日记之单通道分离多通道融合
- STM32 ADC单通道与多通道_DMA学习笔记
- OSG 多视图 实现导航拖拽器
- iOS多种线程锁的简介
- dockerfile创建镜像运行spring-boot
- ajax提交file表单,spring mvc后台获取file表单数据
- Oracle 12c pdb/cdb 监听和tns 配置
- Retrofit 2.0使用
- OSG学习:用多通道(multiple passes)实现透明度
- 深入浅出JMS(一)--JMS基本概念
- CDN技术介绍
- 状态模式
- express入门(8)- 加密
- leetcode 8 String to Integer (atoi)
- Axure RP 8 注册码(亲测可用)
- UML(统一的模型语言)
- Python操作MySQL数据库