OSG之替代节点

213 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 25 天

1 替代节点

替代节点(osgSim::Impostor)继承自osg::LOD节点。替代节点也是一种布告板,它是通过从当前 视点将一个复杂物体对象绘制到一幅图像纹理上来创建的,其中渲染的图像纹理映射到布告板上。

值得注意的是,绘制过程与替代物在屏幕上覆盖的像素点数而不是顶点数或者物体的复杂程度成正比。替代节点可用于物体的一些实例或图形的一些画面,可以加速图像的绘制及渲染。替代节点的另一个优点是可以对纹理图像进行低通滤波,从而生成一张可用于景深效果的模糊图像。

在实际运用中,绘制一个替代节点应该比绘制其所表示的物体要快很多,而且替代物应该和标识的物体非常相像。同样重要的是,替代节点应该可以重复用于挨在一起的多个视点,从而可以有效地利用帧与帧之间的相关性。

随着视点距离的加大,物体的投影图像会随之变小,所以通常这种情形意味着可以使用替代节点方法来处理距离视点较远的缓慢运动的物体。就是距离视点比较近,而且运动时有一面总是面向视点的物体也比较适合用替代节点。

但很多时候替代节点对当前几何形状的近似不是很好,当错误超过某个范围时,替代节点就会变得无效。通常,对替代物的有效限制就是它的分辨率。

当一个远处的替代节点慢慢靠近时,纹理中的单个像素将变得越来越明显,原来的视觉效果就会慢慢消失,这时就需要根据视点和替代节点的当前位置生成新的替代物。这种情况下,图形纹理的分辨率绝对不能超过屏幕的当前分辨率。

osgSim::Impostor的继承关系图如下图所示。

1.png

osgSim::Impostor的成员函数如下:

void setImpostorThreshold(float distance);

这个函数用于设置开始启用Impostor的距离,参数可以根据情况适当调节。它继承自LOD节点,因此它同样可以有多个子节点来控制模型的层次显示。

2 替代节点示例

替代节点(osgSim::Impostor)示例的代码如程序清单所示。

#include <osgViewer/Viewer>

#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osgSim/Impostor>

#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> node = osgDB::readNodeFile(GetCurrentPath() + "\\Data\\cow.osg");

	// 创建一个替代节点
	osg::ref_ptr<osgSim::Impostor> impostor = new osgSim::Impostor;
	// 设置50.0f以后开始使用贴图
	impostor->setImpostorThreshold(50.0f);
	// 设置模型显示范围在0-10000内
	impostor->addChild(node.get(), 0, 10000.0f);

	root->addChild(impostor.get());

	// 优化场景数据
	osgUtil::Optimizer optimizer;
	optimizer.optimize(root.get());

	// 设置窗口大小
	setWindowSize(viewer.get(), 600, 400, "Impostor");

	// 设置场景数据
	viewer->setSceneData(root.get());
	// 初始化并创建窗口
	viewer->realize();
	// 开始渲染
	viewer->run();

	return 0;
}

效果图

2.png

动态效果图

1.gif

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 25 天