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

OpenSceneGraph: Don't update the z-buffer when drawing semi-transparent objects

问题

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

动机

绘制半透明对象时,它们的绘制顺序很重要,因为如果以错误的顺序绘制,本应可见的表面可能会被遮挡。在某些情况下,OpenSceneGraph 自己关于对象绘制顺序的直觉会失败——半透明表面被其他半透明表面遮挡,当 OSG 认为对象中心到相机的距离顺序已更改,并决定更改渲染顺序。因此,有必要通过在状态集上使用 setRenderBinDetails 方法为每个对象手动指定渲染箱来手动控制半透明对象的渲染顺序。

然而,这也可能并不总是有效,因为在一般情况下,不可能为对象选择渲染顺序(即使场景中的各个三角形是有序的)以便绘制所有片段正确(参见 painter's problem), and one might still get occlusion. An alternative is to use depth peeling or some other order-independent transparency 方法,但坦率地说,我不知道在 OpenSceneGraph 中实现它有多困难,或者它会减慢应用程序的速度。

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

你的方向完全正确。

是的,可以启用 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 nodekit:https://github.com/XenonofArcticus/OSG-Transparency-Tool

它包含多种透明度方法,您可以在场景中测试这些方法并检查其源代码实现,包括独立于顺序的透明深度剥离实现和受 Open Inventor 启发的延迟混合方法。 Delayed Blend 是一种高性能的单通道未排序近似值,如果绝对透明度精度不是最重要的标准,它可能会检查您想要的所有框。

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