细数OSG中的“神来之剪”

本文详细介绍了OpenGL中的几种裁剪技术,包括背面裁剪、视椎体裁剪、细节裁剪和遮挡裁剪,以提高渲染效率。背面裁剪通过剔除不可见的背面多边形降低复杂度;视椎体裁剪利用视椎体剔除场景中不在视野内的物体;细节裁剪根据像素阈值筛选微小物体;遮挡裁剪则涉及判断物体间的遮挡关系,通过遮挡板优化室内场景等。这些技术在3D图形渲染中起到关键作用。
摘要由CSDN通过智能技术生成

目录

1. 前言

2. 常见的裁剪技术

2.1. 背面裁剪

2.2. 视椎体裁剪

2.3. 细节裁剪

2.4. 遮挡裁剪


1. 前言

       裁剪”就是从大量的事务中进行挑选、删除。对一个庞大的三维体而言,往往存在着大量无助于最终渲染结果的对象;将它们从场景中剔除后,将剩余的场景对象发送到OpenGL管线中,即可完成一帧的绘制工作。这类型的裁剪工作通常称为“可见性裁剪”,即只有真正能够被终端用户看到的对象才会被发送到渲染管线中。

2. 常见的裁剪技术

2.1. 背面裁剪

      当我们观察一个不透明物体时,通常大约有一半的物体表面是看不到的,因此完全可以省去这一半的绘制工作,场景的多边形复杂度也将降低1/2左右。osg本身提供了如下图的背面裁剪的实现函数:

osg::ref_ptr<osg::CullFace>cullface=new osg::CullFace(osg::CullFace::Back);
stace->setAttribute(cullface.get());
state->setMode(GL_CULL_FACE,osg::StateAttribute::ON);

2.2. 视椎体裁剪

视椎体裁剪就是将不在视椎体中的物体剔除掉、不绘制,而只绘制视椎体内部或与视椎体相交的物体。此举对性能的提升有着巨大的帮助。通常,物体是不规则的,为了方便,我们用该物体的包围球与当前视锥体进行比较。如果包围球在视锥体外,那么不需要绘制此包围球所表达的节点及其所有的子节点。如下图所示,红色方块在视锥体外,该方块将被裁剪。

视锥体裁剪包括近平面裁剪、远平面裁剪以及视锥体侧面裁剪三部分。下图中setProjectionMatrixAsPerspective中的参数zNear、zFar就是对在osg中对相机的远近裁剪面的设置。NEAR_PLANE_CULLING是近平面裁剪,将超出近平面范围以外的对象裁剪:

osg::ref_ptr<osg::Camera>rpCamera = new osg::Camera();
rpCamera->setProjectionMatrixAsPerspective(dAngle,aspectRatio,zNear,zFar);
rpCamera->setComputeNearFarMode(osg::CullSettings::NEAR_PLANE_CULLING);

2.3. 细节裁剪

       场景中某些物体对于观察者而言可能是极其微小的,足以忽略不计,此时可以用细节筛选特性将它们剔除。判断对象是否足够细微,需要用一个像素阈值来决定!注意,这种筛选可能会剔除一些必要的信息(比如用户在屏幕上绘制了一些点,却发现它们全部被吞噬掉了),因此它是一种通过牺牲质量来换取速度的技术。

osg::CullStack::CullingMode cullingMode = viewer.getCamera()->getCullingMode();
cullingMode &= ~ (osg::CullStack::SMAL_FEATURE_CULLING);
viewer.getCamera()->setCullingMode(cullingMode);

2.4. 遮挡裁剪

       判断场景中的物体是否有互相遮挡关系,剔除那些被完全遮挡的对象,保留可见物体。但是,完全的遮挡测试算法往往具有过高的复杂度,需要判断每个场景对象与其他对象的遮挡关系,导致计算带来的开销大于绘制带来的开销,并不实用!

       比较常见的方法是定义一种“遮挡板”对象(在osg中使用OccluderNode节点),其形状不固定,并且可以遮挡场景中的其他对象。少量的遮挡板可以有效的增加场景的裁剪效率,尤其在室内景物的裁剪等场合,使用遮挡板来模拟墙面和门体是再好不过的选择~。

       在osg中OccluderNode本身并不具备遮挡能力,需要指定一个遮挡面osg::ConvexPlanarOccluder来进行遮挡。

//创建遮挡节点对象
osg::ref_ptr<osg::OccluderNode>occluderNode = new osg::OccluderNode;
//创建遮挡平面
osg::ref_ptr<osg::ConvexPlanarOccluder>cpo = new osg::ConvexPlanarOccluder;
//关联遮挡平面
occluderNode->setOccluder(cpo.get());

2.5。 聚集裁剪

       这是一种类似于背面筛选的场景筛选方法,但是它可以将多个对象组合起来进行统一的背面筛选,从而加快背面筛选的速度。其基本原理是:使用一种截断圆锥体来包含某组几何体的所有法线方向和所有点。圆锥的顶点位于一个控制点cp,并使用法线n和半角A辅助进行定位。因此对于视点eye如果出现下面的条件:
 

则认为视点位于该截断圆锥的背面,应当统一剔除它所包含的多个几何体,如下图所示: 

在osg中聚集裁剪相关的类名称为ClusterCullingCallback,使用方法如下图所示: 

osgText::Text*text = new osgText::FadeText;
osg::Vec3 normal = ellipsoid->computeLocalUpVector(X,Y,Z);
text->setCullCallback(new osg::ClusterCullingCallback(osg::Vec3(X,Y,Z),nrmal,0.0));

 本文转自:细数OSG中的“神来之剪”_lavanana的博客-CSDN博客_osg遮挡裁剪

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值