OSG粒子系统与阴影-雾效模拟(1)

        虚拟现实中有很多效果,如雨效、雪效、雾效等,这些都可以通过粒子系统来实现。一个真实的粒子系统的模式能使三维场景达到更好的效果。

        本章对OSG粒子系统的使用以及生成自定义粒子系统的方法进行了详细介绍最后还附带说明了阴影的使用方法。在实时的场景中,阴影是非常重要的,是一个很大的范畴,笔者也没有深入研究,因此,这里只是简单介绍一下。

粒子系统

        粒子系统是一个非常复杂的粒子模拟过程。在 OSG中专门定义了新的名字空间 osgParticle 来处理粒子系统的模拟。

        osgParticle 能够高效地模拟粒子系统,生成非常真实的效果。在OSG 预定义的粒子系统中,大部分的粒子系统模拟都采用的是 Billboard 与色彩融合技术生成粒子。Billboard 技术前面已经讲到过虽然它还存在很多问题,但是总体来说,效果还是非常不错的。色彩融合技术就是在渲染的过程中将各种颜色,如顶点颜色、光照颜色、质颜色和纹理颜色等按照 Alpha 值按一定的比例进行融合,以达到真实的效果。在本书自定义的粒子系统示例中,会向读者展示一个爆炸的效果,当然只是演示一个简单的技术,如果深入的话,还需要重新定义模块。

粒子系统的主要模块

        当打开粒子系统的文档时,读者会发现里面包含很多类,但很多类都是内部操作,在模拟一个粒子系统时,只需要使用其中的一部分就可以完成很好的模拟效果,具体使用的类如图11-1 所示。

11-1子系统成块

        对于一个普通的粒子系统的模拟,可以用图 11-1 来显示主要模块。通过图 11-1 让读者明白一个粒子系统所需要的模块。下面分别介绍这些模块。

  • 放射极(osgParticle::Emitter):一个标准放射极(osgParticle::ModularEmitter)包括一个计数器、一个放置器和一个发射器,它为用户控制粒子系统中多个元素提供了一个标准机制。
  • 粒子系统(osgParticle::ParticleSystem):维护并管理一系列粒子的生成、更新染和销毁。粒子系统类继承自Drawable类,用于控制粒子的渲染,因此与其他 Drawable对象的渲染类似,控制其渲染属性StateAttribute 即可。OSG提供了一个方便的函数以允许用户控制3个常用的渲染状态属性,方法setDefaultAttributes可用于指定材质(或指定为NULL以禁用材质)、允许/禁止附加的图像融合及允许/禁止光照。
  • 粒子(osgParticle::Particle):粒子系统的基本单元。粒子类同时具有物理属性图像属性,它的形状可以是任意的点(PONT)、四边形(QUAD)、四边形带(QUADTRIPSTRIP)、六角形(HEXAGON)或线(LINE)。每个粒子都有自己的生命周期,生命周期也就是每个粒子可以存活的秒数,生命周期为负数的粒子可以存活无限长时间。所有的粒子都具有大小(SIZE)、Alpha值和颜色(COLOR)属性,每组粒子都可以指定其最大和最小值。为了便于粒子生命周期的管理,粒子系统通过改变生命周期的最大和最小值来控制单个粒子的渲染,它会根据已经消耗的时间在最小和最大值之间进行线性插值。
  • 放置器(osgParticle::Placer):设置粒子的初始位置。用户可以使用预定义的放置器或定义自己的放置器,已经定义的放置器包括点放置器 PointPlacer(所有的粒子从同一点出生)、扇面放置器SectorPlacer(所有的粒子从一个指定中心点、半径范围和角度范围的扇面出生)以及多段放置器MultiSegmentPlacer(用户指定一系列的点,粒子沿着这些点定义的线段出生)。
  • 发射器 (osgParticle::Shooter):指定粒子的初始速度。RadialShooter 类允许用户指定一个速度范围(米/秒)以及弧度值表示的方向,方向由两个角度指定(theta角是与Z轴的夹角,phi角是与XY平面的夹角)。
  • 计数器 (osgParticle::Counter):控制每一产生的粒子数。RandomRateCounter 类允许用户指定每帧产生粒子的最大和最小数。
  • 粒子系统更新器(osgParticle::ParticleSystemUpdater):用于自动更新粒子,将其置于场景中时,它会在拣选遍历中调用所有“存活”粒子的更新方法。
  • 标准编程器(osgParticle::ModularProgram):在单个粒子的生命周期中,用户可以使用ModularProgram实例控制粒子的位置,ModularProgram需要与Operator对象组合使用。
  • 操作器(osgParticle::Operator):提供了控制粒子在其生命周期中的运动特性的方法。用户可以改变现有 Operator 类实例的参数或定义自己的 Opcrator 类。OSG提供的Operator类包括AccelOperator(加速度)、AngularAccelOperator(角加速度)、FluidFrictionOperator (空气阻力或流体操作)以及ForceOperator(压力)。

        在OSG中除了这些粒子系统的主要模块以外,还包含其他的已经定义好的模块,如osgParticle::ExplosionDebrisEfect(爆炸碎片)、osgParticle::ExplosionEffect (爆炸模拟)、osgParticle::SmokeEfect(烟雾模拟)和 osgParticle::FireEffect(火光模拟)。

        还有一个比较重要的类osgParticle::PrecipitationEfect,它是OSG定义的新类,用来模拟一些在OSG中已经定义好的粒子系统,如雨效和雪效,使用方法很简单,可以直接加入到场景中。

​​​​​​​粒子系统的模拟过程

        下面将介绍如何模拟一个真实的粒子系统。对于模拟粒子系统的过程可以分为两种,一是OSG中已经定义好的粒子系统模块,二是根据需要自定义粒子系统。预定义粒子系统模块模拟过程如下;

        (1) 创建预定义粒子系统模块对象,设置相应的参数。

        (2) 作为子节点加到场景节点中。从上面列举的子系统的关系继承图中可以看出,它们继承自osg::Node或osg::Group 节点,因此可以直接作为一个节点加入到场景中。

        自定义粒子系统模拟过程如下:

        (1)创建粒子系统(osgParticle::ParticleSystem),并将其加入到场景中,设置相应的属性,如材质、放射及光照。

        (2)创建粒子模板(osgParticle::Particle),控制场景中每一个粒子的特性并关联到粒子系统,设置粒子模板对应的特性,如大小、颜色、生命周期及重量等。

        (3)创建粒子系统放射器(osgParticle::ModularEmitter),标准的放射器包括计数器(Counter)、放置器(Placer)和发射器(Shooter)3 部分,设置相应的属性,如位置、形状、速度和方向等。

        (4)创建粒子系统编程器对象(osgParticle::Program),控制粒子在声明周期内的运动。一个标准编程器对象包含各种操作器,如osgParticle::AccelOperator和osgParticle;:FluidFrictionOperator等。

        (5)创建粒子系统更新器(osgParticle::ParticleSystemUpdater),用于管理每一帧的粒子的属性如位置、速度和方向等。

        通过上面的步骤,可以完成一个简单的粒子系统的模拟。对于一般的需要而言是没有任何问题的。如果需要更高要求的,可以从shader 开始编写属于自己的粒子系统。

​​​​​​​雾效模示例

        雾效其实并不是一种粒子系统,只是一种状态属性,放在这里来演示,因为它本身很像一种粒子系统。

        雾效的管理主要是由osg::Fog来控制染的。osg::Fog类直接继承自osg::StateAttribute类继承关系图如图11-2所示。

图11-2 osg::Fog 的继承关系图

        从继承关系图中可以看到,它继承自osg::StateAttribute类,因此它同样可以通过设置状态模式来控制雾效的开启或关闭,代码如下:

  1. root->getOrCreateStateSet()->setAttributeAndModes(fog.get(),osg::StateAttribute::ON); 

        在OSG中,雾效有两种模式,可以通过下面的方式来获取或设置:

  1. void setMode(Mode mode)  
  2. Mode getMode() const  
  3. enum Mode  
  4. {  
  5.     LINEAR = GL_LINEAR,// 线性务  
  6.     EXP = GL_EXP, //全局雾  
  7.     EXP2 = GL_EXP2// 全局雾  
  8. }; 

        雾的坐标源也有两种,可以通过下面的方式来设置或获取:

  1. void setFogCoordinateSource(GLint source)  
  2. GLint getFogCoordinateSource() const  
  3. enum FogCoordinateSource  
  4. {  
  5.     FOG_COORDINATE = GL_FOG_COORDINATE,//雾坐标  
  6.     FRAGMENTDEPTH = GL_FRAGMENT_DEPTH// 眼坐标  
  7. }; 

        雾的坐标源在使用固定管道的顶点处理时,雾效的值可以是眼坐标系中的y坐标值,也可以是经过插值的雾坐标,这是由雾的标源是设置成GL_FRAGMENT_DEPTH还是GL_FOG_COORDINATE决定的,在可编程管线中应用比较多。

        雾效的特性还有颜色、浓度和起始位置等,可以调用下列类的成员函数来设置相应的特性:

  1. void setDensity(float density)// 设置浓度  
  2. float getDensity() const  
  3. void setStart(float start)// 设置起点  
  4. float getStart() const  
  5. void setEnd(float end)// 设置终点  
  6. float getEnd() const  
  7. void setColor(const Vec4 &color) // 设置雾的颜色  
  8. const Vec4 &getColor() const  

        雾效的特性已经都讲了,解释了雾效可能需要设置所有特性,下面来看一个简单的示例。

代码如程序清单11-1 所示。

// 创建雾效
osg::ref_ptr<osg::Fog> createFog(bool m_Linear)
{// 创建Fog对象osg::ref_ptr<osg::Fog> fog = new osg::Fog();// 设置颜色fog->setColor(osg::Vec4(1.0, 1.0, 1.0, 1.0));// 设置浓度fog->setDensity(0.01);// 设置雾效模式为线性雾if (!m_Linear){fog->setMode(osg::Fog::LINEAR);}else// 设置雾效模式为全局零{fog->setMode(osg::Fog::EXP);}// 设置雾效近点浓度fog->setStart(5.0);// 设置雾效远点浓度fog->setEnd(2000.0);return fog.get();
}void fog_11_1(const string &strDataFolder)
{osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;traits->x = 40;traits->y = 40;traits->width = 600;traits->height = 480;traits->windowDecoration = true;traits->doubleBuffer = true;traits->sharedContext = 0;osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());osg::ref_ptr<osg::Camera> camera = viewer->getCamera();camera->setGraphicsContext(gc.get());camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;camera->setDrawBuffer(buffer);camera->setReadBuffer(buffer);osg::ref_ptr<osg::Group> root = new osg::Group();// 读取模型string strDataPath = strDataFolder + "lz.osg";osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(strDataPath);root->addChild(node.get());// 启用雾效root->getOrCreateStateSet()->setAttributeAndModes(createFog(false), osg::StateAttribute::ON);// 优化场景数据osgUtil::Optimizer optimize;optimize.optimize(root.get());viewer->setSceneData(root.get());viewer->realize();viewer->run();
}

        运行程序,截图如图11-3所示

图11-3 雾效模拟示例截图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/215448.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电源控制系统架构(PCSA)之系统分区电源域

目录 4.2 电源域 4.2.1 电源模式 4.2.2 电源域的选择 4.2.3 系统逻辑 4.2.4 Always-On域 4.2.5 处理器Clusters 4.2.6 CoreSight逻辑 4.2.7 图像处理器 4.2.8 显示处理器 4.2.9 其他功能 4.2.10 电源域层次结构要求 4.2.11 SOC域示例 4.2 电源域 电源域在这里被定…

流程图是什么,用什么软件做?

在工作流程中&#xff0c;经常会遇到需要图形化呈现整个流程的情况。流程图就是一种一目了然的图形化表现方式&#xff0c;便于人们理解、沟通和管理整个流程。 1.Visio Visio是一款微软公司的图表软件&#xff0c;可以用于创建各种类型的流程图、组织结构图、网络图、平面图…

笔记:内网渗透流程之信息收集

信息收集 首先&#xff0c;收集目标内网的信息&#xff0c;包括子网结构、域名信息、IP地址范围、开放的端口和服务等。这包括通过主动扫描和渗透测试工具收集信息&#xff0c;以及利用公开的信息源进行信息搜集。 本机信息收集 查看系统配置信息 查看系统详细信息&#xf…

第一百七十八回 介绍一个三方包组件:SlideSwitch

文章目录 1. 概念介绍2. 使用方法3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"如何创建垂直方向的Switch"相关的内容&#xff0c;本章回中将 介绍SlideSwitch组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们…

linux -系统通用命令查询

有时候内网环境下&#xff0c;系统有些命令没有安装因此掌握一些通用的linux 命令也可以帮助我们解决一些问题查看 1.查看系统内核版本 uname -r2.查看系统版本 cat /etc/os-release3. 查看cpu 配置 lscpu4.查看内存信息 free [参数] 中各个数值的解释如下表 数值解释t…

基于51单片机电子钟万年历LCD1602显示

51单片机的电子钟万年历LCD1602显示 &#x1f534; &#x1f535;51单片机的电子钟万年历LCD1602显示&#x1f534; &#x1f535;主要功能&#xff1a;&#x1f534; &#x1f535;讲解视频&#x1f534; &#x1f535;仿真图&#xff1a;&#x1f534; &#x1f535;程序&…

python之pyqt专栏2-项目文件解析

项目结构 在上一篇文章python之pyqt专栏1-环境搭建&#xff0c;创建新的pyqt项目&#xff0c;下面我们来看一下这个项目下的文件。 从下面的文件结构图可以看到&#xff0c;该项目下有3个文件&#xff0c;untitled.ui,untitled.py 以及main.py。 QtDesigner可以UI界面的方式&am…

怎样自动把网页截图发到微信群里

现在很多公司都在使用企业微信了&#xff0c;不但方便公司内部交流和客户交流&#xff0c;还能组建各种小组群&#xff0c;业务群。企业微信群提供一个机器人的功能&#xff0c;方便我们把公司业务信息&#xff0c;或来自外部的信息自动发布到群里。 这里研究一下如何向微信群…

Verilog基础:时序调度中的竞争(一)

相关阅读 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 作为一个硬件描述语言&#xff0c;Verilog HDL常常需要使用语句描述并行执行的电路&#xff0c;但其实在仿真器的底层&#xff0c;这些并行执行的语句是有先后顺序…

管理类联考——数学——汇总篇——知识点突破——应用题——路程——记忆

路程——【考频&#xff1a;高】——【解题提示&#xff1a;根据题意画图&#xff0c;找等量关系&#xff08;一般是时间和路程&#xff09;&#xff0c;列方程求解。】 【 应用题 ⟹ \Longrightarrow ⟹ 路程 ⟹ \Longrightarrow ⟹ 直线 ⟹ \Longrightarrow ⟹ 匀速、相遇、…

【ArcGIS Pro微课1000例】0036:栅格影像裁剪与提取(矢量范围裁剪dem高程数据)

本实验讲解在ArcGIS Pro中进行栅格影像裁剪与提取(矢量范围裁剪dem高程数据)的方法。DEM、DOM、DSM等栅格数据方法也可以实现。 文章目录 一、加载实验数据二、裁剪工具的使用1. 裁剪栅格2. 按掩膜提取一、加载实验数据 加载配套实验数据包中的0036.rar中的dem数据和矢量裁剪…

【经典小练习】简单的文件加密解密

文章目录 &#x1f339;什么是文件加密⭐应用场景 &#x1f6f8;案例&#x1f33a;描述&#x1f33a;代码 &#x1f339;什么是文件加密 Java文件加密是指使用Java编程语言和相关的加密算法对文件进行加密处理。通过这种方式&#xff0c;可以将文件内容转换为一种非常规的形式…