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 雾效模拟示例截图

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

html幸运大转盘抽奖(附源码)

文章目录 1.设计来源1.1 幸运大转盘 风格11.2 幸运大转盘 风格21.3 幸运大转盘 风格31.4 幸运大转盘 奖品效果1.5 幸运大转盘 活动未开始1.6 幸运大转盘 活动已结束1.7 幸运大转盘 图片源素材 2.效果和源码2.1 动态效果2.2 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&a…

毅速丨3D打印随形水路为何受到模具制造追捧

在模具制造行业中&#xff0c;随形水路镶件正逐渐成为一种革命性的技术&#xff0c;其提高冷却效率、优化产品设计、降低成本等优点&#xff0c;为模具制造带来了巨大的创新价值。 随形水路是一种根据产品形状定制的冷却水路&#xff0c;其镶件可以均匀地分布在模具的表面或内部…

指针运算详解

1.引入 指针的基本运算有三种&#xff0c;分别是&#xff1a; • 指针- 整数 • 指针-指针 • 指针的关系运算 2.指针- 整数 因为数组在内存中是连续存放的&#xff0c;只要知道第⼀个元素的地址&#xff0c;顺藤摸⽠就能找到后⾯的所有元素。 int arr[10] {1,2,3,4,5,…

Nginx安装与配置、使用Nginx负载均衡及动静分离、后台服务部署、环境准备、系统拓扑图

目录 1. 系统拓扑图 2. 环境准备 3. 服务器安装 3.1 mysql&#xff0c;tomcat 3.2 Nginx的安装 4. 部署 4.1 后台服务部署 4.2 Nginx配置负载均衡及静态资源部署 1. 系统拓扑图 说明&#xff1a; 用户请求达到Nginx若请求资源为静态资源&#xff0c;则将请求转发至静态…

HarmonyOS开发:ArkTs常见数据类型

前言 无论是Android还是iOS开发&#xff0c;都提供了多种数据类型用于常见的业务开发&#xff0c;但在ArkTs中&#xff0c;数据类型就大有不同&#xff0c;比如int&#xff0c;float&#xff0c;double&#xff0c;long统一就是number类型&#xff0c;当然了也不存在char类型&…

【C/PTA —— 10.函数1(课外实践)】

C/PTA —— 10.函数1&#xff08;课外实践&#xff09; 一.函数题6-1 符号函数6-2 求排列数6-3 求一个大于10的n位整数w的后n-1位的数&#xff0c;并作为函数值返回。6-4 其右上三角&#xff08;含主对角线&#xff09;元素之和。6-5 字符串比较6-6 使用函数求素数和6-7 使用函…

简答的体系架构分析

背景 一点体系架构的分析 体系架构图

常用数据存储格式介绍:Excel、CSV、JSON、XML

在现代数字时代&#xff0c;数据经过提炼后可以推动创新、简化运营并支持决策流程。然而&#xff0c;在提取数据之后&#xff0c;并将其加载到数据库或数据仓库之前&#xff0c;需要将数据转化为可用的数据存储格式。本文将介绍开发者常用的4种数据存储格式&#xff0c;包括 Ex…

待办委托超方便,流程审批效率大提升丨三叠云

流程委托 路径 我的流程 >> 我的待办 功能简介 我的流程增加「待办委托」功能&#xff0c;用户可以将待处理的流程审批委托他人处理。 应用场景&#xff1a; 如果当前审批人不方便审批时&#xff0c;可以委托给指定的人&#xff08;被委托人&#xff09;处理&#…

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

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

DQN算法

DQN算法 教程链接 DataWhale强化学习课程JoyRL https://johnjim0816.com/joyrl-book/#/ch7/main DQN算法 DQN(Deep Q-Network) 主要创新点在于将Q-learning算法中的Q表记录动作价值函数转为引入深度神经网络来近似动作价值函数 Q ( s , a ) Q(s,a) Q(s,a),从而能够处理连续…

智慧城市运营管理平台解决方案:PPT全文61页,附下载

关键词&#xff1a;智慧城市建设方案&#xff0c;智慧城市解决方案&#xff0c;智慧城市的发展前景和趋势&#xff0c;智慧城市建设内容&#xff0c;智慧城市运营管理平台 一、智慧城市运营平台建设背景 随着城市化进程的加速&#xff0c;城市面临着诸多挑战&#xff0c;如环…

Keil5MDK创建C51工程

Keil5MDK创建C51工程 1.概述 上篇文章介绍了安装Keil5MDK和C51工具&#xff0c;这篇文章介绍工具的使用&#xff0c;首先介绍如何创建一个51单片机工程&#xff0c;写一个demo程序通过编译&#xff0c;烧录到单片机。 第一篇安装工具文章地址&#xff1a;https://blog.csdn.ne…

智慧楼宇可视化视频综合管理系统,助力楼宇高效安全运行

随着互联网技术的进步和发展&#xff0c;智能化的楼宇建设也逐步成为人们选择办公场所是否方便的一个重要衡量因素。在智能化楼宇中&#xff0c;安全管理也是重要的一个模块。得益于互联网新兴技术的进步&#xff0c;安防视频监控技术也得到了快速发展并应用在楼宇的安全管理中…

区块链技术与应用 【全国职业院校技能大赛国赛题目解析】第四套区块链应用后端开发

第四套区块链应用后端开发 环境 : ubuntu20 fisco : 2.8.0 springboot 2.1.1 fisco-java-sdk: 2.7.2 maven 3.8.8 前言 这套后端样题,只涉及调用fisco的系统接口,不涉及此食品溯源项目的业务接口,所以我就直接生成一个springboot项目进行完成此题目。 请提前准备好一…

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

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

【免费使用】基于PaddleSeg开源项目开发的人像抠图Web API接口

基于PaddleSeg开源项目开发的人像抠图API接口&#xff0c;服务器不存储照片大家可放心使用。 1、请求接口 请求地址&#xff1a;http://apiseg.hysys.cn/predict_img 请求方式&#xff1a;POST 请求参数&#xff1a;{"image":"/9j/4AAQ..."} 参数是jso…

Python零基础入门之模块详解

文章目录 一、模块1、模块的四种形式2、为什么要用模块&#xff1f; 二、如何用模块1、import 模块名导入重命名&#xff1a;smt变量指向span模块的名称空间导入多个模块 2、from 模块名 import 具体的函数rom … import \* 语句&#xff1a;导入文件内所有的功能&#xff1a; …

2014年全国硕士研究生入学统一考试管理类专业学位联考数学试题——解析版

文章目录 2014 年考研管理类联考数学真题一、问题求解&#xff08;本大题共 15 小题&#xff0c;每小题 3 分&#xff0c;共 45 分&#xff09;下列每题给出 5 个选项中&#xff0c;只有一个是符合要求的&#xff0c;请在答题卡上将所选择的字母涂黑。真题&#xff08;2014-01&…

“三个绝技“让项目经理轻松做好进度管理

大家好&#xff0c;我是老原。 我离开腾讯之后&#xff0c;曾经加入一家互联网创业公司。 要知道&#xff0c;当你在一个大公司的平台上做事做习惯之后&#xff0c;觉得一些流程都应该是严谨的、完备的、按计划进行的。 但是当时&#xff0c;经常出现一个致命问题——进度拖…