OSG学习:用多通道(multiple passes)实现透明度
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::OVE
RRIDE );
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学习示例之遇到问题四骨骼动画编译osgCal
osg学习示例之遇到问题四骨骼动画编译osgCal 转自:http://blog.csdn.net/wuwangrun/article/details/8239451 今天学到书<OpenSce ...
- 【OSG学习笔记之一:】OSG+VS2010+win7 64位环境搭建
虽然出生的时候,没有说过“Hello World!”,但是自从走上了编程之路,每一次输出“Hello World!”的时候,都觉得好比中了彩票大奖似的: 仔细算算,从2012年暑假到现在,经历了3年半 ...
- Arm开发板+Qt学习之路-multiple definition of
问题描述:在一个头文件a.h中定义一些变量x,在其他.c文件中(b.c,c.c)要用到.用一般的全局变量的方法,编译时总是提示error:multiple definition of x 问题分析:o ...
- osg学习笔记3 简单几何模型
osg::Geode (geometry node) osg::Geode类表示场景中的渲染几何叶节点,它包含了渲染用的几何信息,没有子节点. 要绘制的几何数据保存在osg::Geode管理的一组os ...
- osg学习笔记2, 命令行参数解析器ArgumentParser
ArgumentParser主要负责命令行参数的读取 #include <osgDB/ReadFile> #include <osgViewer/Viewer> int mai ...
- OSG学习:裁剪变换(2)
接着上一篇博客说. 还有一种裁剪的方法:osg::Scissor类. 这个类封装了OpenGL中的glScissor()函数. 该类主要用于设置一个视口裁剪平面举行.设置裁剪平面举行的函数如下: vo ...
- OSG学习:裁剪变换(1)
在OSG中,默认了6个裁剪平面以去除没有必要显示的物体.也可以自己定义其他的裁剪平面来确定裁剪. osg::ClipPlane类继承自osg::StateAttribute类,封装了OpenGL中的g ...
- OSG学习:计算纹理坐标
在很多时候,直接指定纹理坐标是非常不方便的,如曲面纹理坐标,只有少数的曲面(如圆锥.圆柱等)可以在不产生扭曲的情况下映射到平面上,其他的曲面在映射到表面时都会产生一定程度的扭曲.一般而言,曲面表面的曲 ...
- OSG学习:LOD、数据分页、动态调度
LOD(level of detail):是指根据物体模型的结点在显示环境中所处的位置和重要度,决定物体渲染的资源分配,降低非重要物体的面数和细节度,从而获得高效率的渲染运算.在OSG的场景结点组织结 ...
随机推荐
- 【五】安装fcig
安装fcig 安装fcig 此步骤是为了让spawn-fcgi能够识别自定义的demo 编译文件 自定义c文件 测试成功后,启动spawn cgi进行代理托管 此步骤是为了让spawn-fcgi能够识 ...
- python小项目之微信远程控制
前两天接触了一个有趣的python模块--itchat,这个模块可以非常方便的操作微信,今天就来使用这个模块来实现微信远程控制. 环境准备 itchat模块不是python标准模块(内置模块),是一个 ...
- wechall MySQL Authentication Bypass II
首先看看源码 username password分开来验证.但是没做过滤 通常的利用方法是使用union构造已知MD5值的查询. 如果username存在则执行查询,并且为admin.我们用unnio ...
- 2017-2018-1 20155321《信息安全技术》实验二——Windows口令破解
2017-2018-1 20155321<信息安全技术>实验二--Windows口令破解 实验原理 口令破解方法 口令破解主要有两种方法:字典破解和暴力破解. 字典破解是指通过破解者对管理 ...
- 20155322 2016-2017-2 《Java程序设计》第4周学习总结
20155322 2016-2017-2 <Java程序设计>第4周学习总结 教材学习内容总结 本周的学习内容为课本第六章与第七章: 第六章主要讲继承和多态.首先是我们为什么要学习继承和多 ...
- PyQt5 结合 matplotlib 时,如何显示其 NavigationToolbar
本文目的:展示 PyQt5 结合 matplotlib 时,如何显示其 NavigationToolbar. 本人搜遍所有网络无果,没办法,查看PyQt5源代码,最终才搞明白...特此留记. 〇.Py ...
- Zabbix学习之路(八)之自动化监控网络发现和主动注册
1.网络发现 分两步走:创建发现规则(rule)和执行的动作(Action)(1)创建发现规则"Configuration"-->"Create discover ...
- javaweb(三十一)——国际化(i18n)
一.国际化开发概述 软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的.符合来访者阅读习惯的页面或数据. 国际化(internationaliz ...
- 探究linux设备驱动模型之——platform虚拟总线(二)
上回说到,platform_match是驱动和设备之间的媒人婆,那么platform_match是如何匹配驱动和设备的呢?platform总线定义的匹配条件很简单,主要就是查看驱动结构体和设备结构体的 ...
- 三边定位 c#
MATLAB是美国MathWorks公司出品的商业数学软件,用于算法开发.数据可视化.数据分析以及数值计算的高级技术计算语言和交互式环境,主要包括MATLAB和Simulink两大部分. 项目中用到三 ...