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

news2024/11/15 8:24:20

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

        本章对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.coloradmin.cn/o/1248591.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML新特性【缩放图像、图像切片、平移、旋转、缩放、变形、裁切路径、时钟、运动的小球】(二)-全面详解(学习总结---从入门到深化)

目录 绘制图像_缩放图像 绘制图像_图像切片 Canvas状态的保存和恢复 图形变形_平移 图形变形_旋转 图形变形_缩放 图形变形_变形 裁切路径 动画_时钟 动画_运动的小球 引入外部SVG 绘制图像_缩放图像 ctx.drawImage(img, x, y, width, height) img &#xf…

R语言——图解taxize,强烈推荐收藏关注,持续更新中

图解taxize 1. taxize分解思路1.1 图解说明 2. 针对不同数据库的函数组2.1 APGⅢ2.2 BOLD&#xff08;barcode of life data system&#xff09; 1. taxize分解思路 taxize可以帮助人们从许多数据库中获取信息。 由于要处理的数据库很多&#xff0c;导致taxize包含的功能函数…

一文教你开启真人3D手办生意

真人手办定制是现代数字化技术结合文化创意视角而诞生的一种新型消费场景。在3D技术的辐射之下&#xff0c;真人3D手办生产与销售的是产销合一的数字化产品&#xff0c;想要实现这种精准消费的高效化、规模化&#xff0c;既需要专业技术也需要在线平台&#xff0c;一旦通路达成…

Ubuntu18.4中安装wkhtmltopdf + Odoo16配置【二】

deepin Linux 安装wkhtmltopdf 1、先从官网的链接里下载linux对应的包 wkhtmltopdf/wkhtmltopdf 下载需要的版本&#xff0c;推荐版本&#xff0c;新测有效&#xff1a; wkhtmltox-0.12.4_linux-generic-amd64.tar.xz 2、解压下载的文件 解压后会有一个wkhtmltox文件夹 3…

linux高级篇基础理论六(firewalld,防火墙类型,,区域,服务端口,富语言)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️不能因为人生的道路坎坷,就使自己的身躯变得弯曲;不能因为生活的历程漫长,就使求索的 脚步迟缓。 ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xff1a;云计算技…

『亚马逊云科技产品测评』活动征文|低成本搭建物联网服务器thingsboard

授权声明&#xff1a;本篇文章授权活动官方亚马逊云科技文章转发、改写权&#xff0c;包括不限于在 Developer Centre, 知乎&#xff0c;自媒体平台&#xff0c;第三方开发者媒体等亚马逊云科技官方渠道。 0. 环境 - ubuntu22&#xff08;注意4G内存勉强够&#xff0c;部署完…

【Linux】进程间通信——进程间通信的介绍和分类、管道、匿名管道、命名管道、匿名管道与命名管道的区别

文章目录 进程间通信1.进程间通信的介绍1.1目的和发展 2.进程间通信分类3.管道3.1匿名管道3.1.1匿名管道的原理&#xff08;文件角度&#xff09;3.1.2匿名管道的原理&#xff08;内核角度&#xff09;3.1.3管道读写规则3.1.4管道特点 3.2命名管道3.2.1创建命名管道3.2.2命名管…

Twincat使用:EtherCAT通信扫描硬件设备链接PLC变量

EtherCAT通信采用主从架构&#xff0c;其中一个主站设备负责整个EtherCAT网络的管理和控制&#xff0c;而从站设备则负责在数据环网上传递数据。 主站设备可以是计算机、工控机、PLC等&#xff0c; 而从站设备可以是传感器、执行器、驱动器等。 EL3102:MDP5001_300_CF8D1684;…

【文末送书】机器学习高级实践

2023年初是人工智能爆发的里程碑式的重要阶段&#xff0c;以OpenAI研发的GPT为代表的大模型大行其道&#xff0c;NLP领域的ChatGPT模型火爆一时&#xff0c;引发了全民热议。而最新更新的GPT-4更是实现了大型多模态模型的飞跃式提升&#xff0c;它能够同时接受图像和文本的输入…

OpenStack云计算平台-镜像服务

目录 一、镜像服务概览 二、安装和配置 1、先决条件 2、安全并配置组件 3、完成安装 三、验证操作 一、镜像服务概览 OpenStack镜像服务是IaaS的核心服务&#xff0c;如同 :ref:get_started_conceptual_architecture所示。它接受磁盘镜像或服务器镜像API请求&#xff0c;…

浏览器缓存控制讲解

缓存的作用 在你访问互联网中的任何资源其所产生的任何链路中的每一个节点几乎都会进行缓存&#xff0c;整个缓存体系和细节十分复杂。比如浏览器缓存&#xff0c;服务器缓存&#xff0c;代理服务器缓存&#xff0c;CDN缓存等。 但是缓存又十分重要&#xff0c;不可缺少&…

matlab三维地形图

matlab三维地形图 %%%%—————Code to draw 3D bathymetry—————————— %-------Created by bobo,10/10/2021-------------------- clear;clc;close all; ncdisp E:\data\etopo\scs_etopo.nc filenmE:\data\etopo\scs_etopo.nc; londouble(ncread(filenm,lon)); lat…

P8 C++引用

前言 本期我们要讲的是 C 中的引用。 上期我们讨论了指针&#xff0c;如果你没有看过那期内容&#xff0c;你一定要回去看看&#xff0c;因为引用实际上只是指针的扩展&#xff0c;你至少需要在基本层面上理解指针是如何工作的&#xff0c;然后才能继续学习本期的内容&#xf…

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

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

哈希表的认识与实现

哈希的概念 可以不经过任何比较&#xff0c;一次直接从表中得到要搜索的元素。如果构造一种存储结构&#xff0c;通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系&#xff0c;那么在查找时通过该函数可以很快找到该元素。 所以当我们设置这种…

【数据结构】—搜索二叉树(C++实现,超详细!)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;消えてしまいそうです—真夜中 1:15━━━━━━️&#x1f49f;──────── 4:18 &#x1f504; ◀️ ⏸ ▶️…

《微信小程序从入门到精通》---笔记1

小程序&#xff0c;我又来学习啦&#xff01;请多关照~ 项目驱动 小程序开发建议使用flex布局在小程序中&#xff0c;页面渲染和业务逻辑是分开的&#xff0c;分别运行在不同的线程中。Mini Program于2017年1月7号正式上线小程序的有点&#xff1a;跨平台、开发门槛低、开发周…

基于战争策略算法优化概率神经网络PNN的分类预测 - 附代码

基于战争策略算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于战争策略算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于战争策略优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

SSL握手失败的解决方案

一、SSL握手失败的原因&#xff1a; 1&#xff0c;证书过期&#xff1a;SSL证书有一个有效期限&#xff0c;如果证书过期&#xff0c;就会导致SSL握手失败。 2&#xff0c;证书不被信任&#xff1a;如果网站的SSL证书不被浏览器或操作系统信任&#xff0c;也会导致SSL握手失败…

(Matalb时序预测)GA-BP遗传算法优化BP神经网络的多维时序回归预测

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、部分代码 四、本文代码数据说明手册分享&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matalb平台编译&am…