OpenSceneGraph:绘制半透明对象时不要更新z缓冲区

时间:2018-10-17 09:22:24

标签: graphics rendering transparency openscenegraph

问题

是否可以告诉OpenSceneGraph在绘制半透明对象时使用Z缓冲区而不更新它?

动机

绘制半透明对象时,其绘制顺序很重要,因为如果以错误的顺序绘制它们,则可能会遮挡应显示的曲面。在某些情况下,OpenSceneGraph自己对绘制对象顺序的直觉会失败—半透明的表面被其他半透明的表面所遮盖,并且当OSG认为“弹出”(如果可以以这种方式使用该词)时,可能会发生对象中心到相机的距离的顺序已更改,并决定更改渲染顺序。因此,有必要通过使用状态集上的setRenderBinDetails方法为每个对象手动指定渲染容器来手动控制半透明对象的渲染顺序。

但是,这仍然可能并不总是有效,因为在一般情况下,不可能为对象选择渲染顺序(即使场景中的各个三角形都已排序),以使所有片段都正确绘制(参见painter's problem),并且可能仍然会被遮挡。一种替代方法是使用depth peeling或其他order-independent transparency方法,但是坦率地说,我不知道在OpenSceneGraph中实现这种方法有多困难,或者会使应用程序变慢多少。

就我而言,作为美学和算法复杂度及速度之间的折衷,理想情况下,我始终希望绘制一个半透明表面的片段,即使另一个半透明表面的另一个片段(在那种情况下像素)更接近已经绘制的相机。这将防止其他半透明表面弹出和遮盖半透明表面,并且对于每个渲染的半透明对象,如果Z缓冲区用于测试可见性但未更新,则可以有效地实现当片段被绘制时。

1 个答案:

答案 0 :(得分:2)

您完全在正确的轨道上。

是的,可以启用Z测试,但在绘制过程中使用setWriteMask()关闭Z写入:

// Disable Z-writes
osg::ref_ptr<osg::Depth> depth = new osg::Depth;
depth->setWriteMask(false);
myNode->getOrCreateStateSet()->setAttributeAndModes(depth, osg::StateAttribute::ON)

// Enable Z-test (needs to be done after Z-writes are disabled, since the latter
// also seems to disable the Z-test)
myNode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);

https://www.mail-archive.com/osg-users@openscenegraph.net/msg01119.html

http://public.vrac.iastate.edu/vancegroup/docs/OpenSceneGraphReferenceDocs-2.8/a00206.html#a2cef930c042c5d8cda32803e5e832dae

您可能希望查看几年前我们为CAD客户端编写的osgTransparencyTool节点工具包:https://github.com/XenonofArcticus/OSG-Transparency-Tool

它包括几种透明度方法,可以对场景进行测试并检查其源实现,包括“顺序无关的透明度深度剥离”实现和受Open Inventor启发的“延迟混合”方法。延迟混合是一种高性能的单程未排序近似值,如果绝对透明精度不是最重要的标准,它可能会选中您想要的所有框。

如果您还没有阅读过,这里有一篇论文详细讨论了各种方法: http://lips.informatik.uni-leipzig.de/files/bathesis_cbluemel_digital_0.pdf