OSG学习:用多通道(multiple passes)实现透明度
osgFX庫提供了一個(gè)用于多通道渲染(multi-pass rendering)的框架。每個(gè)你想要渲染的子圖都應(yīng)該被添加到osgFX::Effect節(jié)點(diǎn),多通道技術(shù)的定義和使用都可以在這個(gè)節(jié)點(diǎn)中完成。你可能已經(jīng)熟悉一些預(yù)定義的效果,例如osgFX::Scribe和osgFX::Outline。但是在這個(gè)教程中,我們的任務(wù)是我們自己設(shè)計(jì)一個(gè)多通道技術(shù)。這就是所謂的多通道透明度,當(dāng)我們?cè)谕该髂J剑╰ransparent mode)下它可以消除一些錯(cuò)誤。
如何使用
添加必要的頭文件:
#include <osg/BlendFunc>
#include <osg/ColorMask>
#include <osg/Depth>
#include <osg/Material>
#include <osgDB/ReadFile>
#include <osgFX/Effect>
#include <osgViewer/Viewer>
2.首先,我們將提供一個(gè)新技術(shù),這個(gè)技術(shù)繼承于osgFX::Technique節(jié)點(diǎn)。validate()方法是用于檢查現(xiàn)在硬件是否支持這個(gè)技術(shù),如果一切正常會(huì)返回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.在這個(gè)類中,另一個(gè)必須有的方法是define_passes()。這是用于定義多通道的。在這個(gè)教程中,我們將有兩個(gè)通道:一個(gè)是取消顏色掩膜(color mask)以及如果深度緩沖區(qū)值(depth buffer value)小于現(xiàn)在的就記錄下來;另一個(gè)將使用顏色緩沖區(qū),但只有在深度值等于已經(jīng)記錄下來的值的時(shí)候?qū)戇M(jìn)去。(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() );
我們?cè)O(shè)計(jì)完技術(shù)之后,現(xiàn)在我們可以聲明effect類,把技術(shù)添加到它的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函數(shù)中,我們將使用景點(diǎn)的Cessna模型。不過,為了使它透明,我們將在上面添加一個(gè)新的材料,把散射顏色(diffuse color)的alpha通道設(shè)置為小于1的值,以及把TRANSPARENT_BIN這個(gè)hint應(yīng)用到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.創(chuàng)建一個(gè)新定義類的實(shí)例并添加到模型中。
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.現(xiàn)在你將看到適當(dāng)渲染過的透明的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();
}
原理
多通道透明度技術(shù)會(huì)繪制物體兩次。第一個(gè)通道(見后面代碼)僅僅更新深度緩沖區(qū)(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() );
第二個(gè)通道將會(huì)繪制進(jìn)顏色緩沖區(qū)(color buffer),但由于在第一個(gè)通道中設(shè)置的深度值,只有前面的多邊形能夠通過深度檢測(cè),它們的顏色將被繪制,與現(xiàn)在的混合。這避免了我們之前討論過的順序問題。代碼片段如下:
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》第六章
總結(jié)
以上是生活随笔為你收集整理的OSG学习:用多通道(multiple passes)实现透明度的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NodeJS使用volta进行版本管理
- 下一篇: jQuery 全屏滚动插件 fullpa