开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 23 天
1 细节层次节点
细节层次节点(osg::LOD)继承自osg::Group。使用细节层次节点可以实现不同层次下物体的渲染。细节层次(Level of Detail,LOD)的基本思想是使用物体的一种简单形式表达物体,这样可以使绘制的图形尽量简洁。
当视点靠近物体时,用详细的细节表示;当视点远离物体时,用简化模型来表示。由于距离原因,简化后的模型与细节详细的模型看上去很接近,这样就可以获得一个比较好的加速效果。在后面的章节中还会讲到粒子系统中的雾效,可以与LOD一起使用,当一个物体进入不透明的雾化区域时,可以完全不用绘制这个物体。
此外,还可以使用雾化机制实现时间临界绘制,通过将远平面移近,可以对物体进行提前裁剪,这样可以取得比较快的绘制速度,从而提高帧率。
在OSG中,对于一个LOD模型,它是一次性载入内存的,而且只是有选择地绘制渲染。osg::LOD的继承关系图如下图所示。
LOD计算的是视点到物体包围盒中心的距离,在应用程序中也可以改变这种方式,它有两种中心模式。LOD的切换同样是根据距离来确定的,应用程序中同样可以根据屏幕像素大小来切换,它也有两种变换模式。
enum CenterMode
{
USE_BOUNDING_SPHERE_CENTER, //包围盒中心
USER_DEFINED_CENTER //自定义中心,需要自己调用 setCenter()
}
enum RangeMode
{
DISTANCE_FROM_EYE_POINT, //距视点的距离
PIXEL_SIZE_ON_SCREEN //屏幕像素的大小
}
2 细节层次节点示例
细节层次节点(osg::LOD)示例代码如下所示。
#include <osgViewer/Viewer>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/LOD>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgUtil/Optimizer>
#include "utility.h"
int main()
{
// 创建Viewer对象,场景浏览器
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
// 创建场景组根节点
osg::ref_ptr<osg::Group> root = new osg::Group();
// 创建一个节点,读取牛模型
osg::ref_ptr<osg::Node> node1 = osgDB::readNodeFile(GetCurrentPath() + "\\Data\\cow.osg");
// 创建一个节点,读取滑翔机模型
osg::ref_ptr<osg::Node> node2 = osgDB::readNodeFile(GetCurrentPath() + "\\Data\\glider.osg");
// 创建一个细节层次LOD节点
osg::ref_ptr<osg::LOD> lod = new osg::LOD();
// 添加子节点,在0-30显示牛
lod->addChild(node1.get(), 0.0f, 30.0f);
// 添加子节点,在30-100范围内显示滑翔机
lod->addChild(node2.get(), 30.0f, 100.0f);
// 写入lod.osg文件
osgDB::writeNodeFile(*(lod.get()), GetCurrentPath() + "\\Data\\lod.osg");
// 添加到场景
root->addChild(lod.get());
// 优化场景数据
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
// 设置窗口大小
setWindowSize(viewer.get(), 600, 400, "Lod");
// 设置场景数据
viewer->setSceneData(root.get());
// 初始化并创建窗口
viewer->realize();
// 开始渲染
viewer->run();
return 0;
}
效果图
动态效果图