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.mzph.cn/news/167895.shtml

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

相关文章

pairplot

Python可视化 | Seaborn5分钟入门(七)——pairplot - 知乎 (zhihu.com) Seaborn是基于matplotlib的Python可视化库。它提供了一个高级界面来绘制有吸引力的统计图形。Seaborn其实是在matplotlib的基础上进行了更高级的API封装&#xff0c;从而使得作图更加容易&#xff0c;不需…

红黑树详解

红黑树的概念与性质 前置知识 在学习红黑树之前&#xff0c;最好有二叉查找树和AVL树的基础&#xff0c;因为红黑树本质就是一种特殊的二叉查找树&#xff0c;而红黑树的操作中需要用到AVL树中旋转的相关知识。至于二叉查找树和AVL树&#xff0c;可以参考如下两篇博客&#xf…

Matplotlib图形注释_Python数据分析与可视化

Matplotlib图形注释 添加注释文字、坐标变换 有的时候单单使用图形无法完整清晰的表达我们的信息&#xff0c;我们还需要进行文字进行注释&#xff0c;所以matplotlib提供了文字、箭头等注释可以突出图形中重点信息。 添加注释 为了使我们的可视化图形让人更加容易理解&#…

长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, …, numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0 。 示例 1&#xff1a; 输入&#x…

MySQL 有多个普通索引时会取哪一个索引?

我们都知道MySQL在查询时底层会进行索引的优化&#xff0c;假设有两个普通索引&#xff0c;且where 后面也根据这两个普通索引查询数据&#xff0c;那么执行查询语句时会使用到那个索引&#xff1f; 为了方便演示&#xff0c;新建users表&#xff0c;新建idx_name、idx_city这两…

前端vue导出PPT,使用pptxgen.js

前言 公司新需求需要导出ppt给业务用&#xff0c;查阅资料后发现也挺简单的&#xff0c;记录一下。 如有不懂的可以留言&#xff01;&#xff01;&#xff01; 1.安装包 npm install pptxgenjs --save2.引入包 在需要使用的文件中引入 import Pptxgenfrom "pptxgenjs&…

Oracle研学-介绍及安装

一 ORACLE数据库特点: 支持多用户&#xff0c;大事务量的事务处理数据安全性和完整性控制支持分布式数据处理可移植性(跨平台&#xff0c;linux转Windows) 二 ORACLE体系结构 数据库&#xff1a;oracle是一个全局数据库&#xff0c;一个数据库可以有多个实例&#xff0c;每个…

nodejs+vue+python+PHP+微信小程序-留学信息查询系统的设计与实现-安卓-计算机毕业设计

1、用户模块&#xff1a; 1&#xff09;登录&#xff1a;用户注册登录账号。 2&#xff09;留学查询模块&#xff1a;查询学校的入学申请条件、申请日期、政策变动等。 3&#xff09;院校排名&#xff1a;查询国外各院校的实力排名。 4&#xff09;测试功能&#xff1a;通过入学…

python-选择排序

选择排序是一种简单直观的排序算法&#xff0c;它的基本思想是每一轮选择未排序部分的最小元素&#xff0c;然后将其放到已排序部分的末尾。这个过程持续进行&#xff0c;直到整个数组排序完成。(重点&#xff1a;通过位置找元素) 以下是选择排序的详细步骤和 Python 实现&…

HarmonyOS应用开发实战—登录页面【ArkTS】

文章目录 本页面实战效果预览图一.HarmonyOS应用开发1.1HarmonyOS 详解1.2 ArkTS详解二.HarmonyOS应用开发实战—登录页面【ArkTS】2.1 ArkTS页面源码2.2 代码解析2.3 心得本页面实战效果预览图 一.HarmonyOS应用开发 1.1HarmonyOS 详解 HarmonyOS(鸿蒙操作系统)是华为公司…

js粒子效果(一)

效果: 代码: <!doctype html> <html> <head><meta charset"utf-8"><title>HTML5鼠标经过粒子散开动画特效</title><style>html, body {position: absolute;overflow: hidden;margin: 0;padding: 0;width: 100%;height: 1…

DELL MD3600F存储重置管理软件密码

注意&#xff1a;密码清除可能会导致业务秒断&#xff0c;建议非业务时间操作 针对一台控制器操作即可&#xff0c;另一控制器会同步操作 重置后密码为空&#xff01; 需求&#xff1a;重置存储管理软件密码 管理软件中分配物理磁盘时提示输入密码(类似是否了解风险确认操作的提…

io.lettuce.core.RedisCommandExecutionException

io.lettuce.core.RedisCommandExecutionException: ERR invalid password ERR invalid password-CSDN博客 io.lettuce.core.RedisCommandExecutionException /** Copyright 2011-2022 the original author or authors.** Licensed under the Apache License, Version 2.0 (the…

Rust UI开发(一):使用iced构建UI时,如何在界面显示中文字符

注&#xff1a;此文适合于对rust有一些了解的朋友 iced是一个跨平台的GUI库&#xff0c;用于为rust语言程序构建UI界面。 iced的基本逻辑是&#xff1a; UI交互产生消息message&#xff0c;message传递给后台的update&#xff0c;在这个函数中编写逻辑&#xff0c;然后通过…

2023-11-24--oracle--实验--[Merge 语句]

oracle--实验---Merge语句 1.认知Merge 语句 • merge 语句是 sql 语句的一种。在 SQL server 、 Oracle 数据库中可用&#xff0c; MySQL 中不可用。 • merge 用来合并 update 和 insert 语句。目的&#xff1a;通过 merge 语句&#xff0c;根据一张表&#xff08; 原数据表…

AT360-6T GNSS 单频高精度授时模块特性参数

AT360-6T 模块具有高灵敏度、低功耗、低cost等优势&#xff0c;可以满足电力授时&#xff0c;通信授时等领域的应用。AT360-6T特点&#xff1a; 1.支持北斗二代/北斗三代信号 2.高精度授时 3.可靠性授时 实时高精度授时 AT360-6T 系列模块的授时秒脉冲抖动可以达到 10ns&am…

杰发科技AC7801——ADC软件触发的简单使用

前言 7801资料读起来不是很好理解&#xff0c;大概率是之前MTK的大佬写的。在此以简单的方式进行描述。我们做一个简单的规则组软件触发Demo。因为规则组通道只有一个数据寄存器&#xff0c;因此还需要用上DMA方式搬运数据到内存。 AC7801的ADC简介 7801的ADC是一种 12 位 逐…

洛谷P1157组合的输出 递归:我他又来辣

没没没没没没没错&#xff0c;这是一道简单的递归&#xff08;其实是深搜加回溯) 我不管&#xff0c;我说是递归就是递归。 上题干&#xff1a; 题目描述 排列与组合是常用的数学方法&#xff0c;其中组合就是从 n 个元素中抽出 r个元素&#xff08;不分顺序且 r≤n&#x…

大数据技术之数据安全与网络安全——CMS靶场实训

大数据技术之数据安全与网络安全——CMS靶场实训 在当今数字化时代&#xff0c;大数据技术的迅猛发展带来了前所未有的数据增长&#xff0c;同时也催生了对数据安全和网络安全的更为迫切的需求。本篇博客将聚焦于大数据技术背景下的数据安全与网络安全&#xff0c;并通过CMS&a…

C语言-指针讲解(3)

文章目录 1.字符指针变量1.1 字符指针变量类型是什么1.2字符指针变量的两种使用方法&#xff1a;1.3字符指针笔试题讲解1.3.1 代码解剖 2.数组指针变量2.1 什么是数组指针2.2 数组指针变量是什么&#xff1f;2.2.3 数组指针变量的举例 2.3数组指针和指针数组的区别是什么&#…