osgFX扩展库-异性光照、贴图、卡通特效(1)
本章将简单介绍 osgFX扩展库及osgSim 扩展库。osgFX库用得比较多,osgSim库不常用,因此,这里只对这个库作简单的说明。
osgFX扩展库
osgFX是一个OpenSceneGraph 的附加库,是一个用于实现一致、完备、可重用的特殊效果的构架工具,其效果可以添加到OSG 的节点中,它同时还包含了一系列预定义好的特殊效果。可以用一个简单的继承关系图来表示,如图 12-1 。
图 12-1 osgFX类的承关系图
异性光照特效
各向异性光照(Anisotropic Lighting)特效使用单一通道,它使用了一种各向异性的光照来替代OpenGL 的标准光照模型。几何体顶点的颜色在这里不是直接进行计算的,而是纹理映射到用户指定的光照图板的结果。这里需要使用顶点着色器(vertex program)来计算纹理坐标S和T的值:S=N×H ;T=N×L ,这里N表示顶点的法线,L表示光到顶点的向量,H表示中间向量。这种特效很好地演示了State::getInitialViewMatrix()方法的使用,它可以直接获取视口的初始矩阵并实现直接与视口相关的特效,而不需要任何假借的工作,但该特效需要ARB_vertex_program扩展的支持。
osgFX::AnisotropicLighting 的继承关系图如图12-2所示。
图12-2 osgFX::AnisotropicLighting 的继承关系图
从继承关系图中可以看出,osgFX::AnisotropicLighting是一个组节点,它继承自osgFX::Effect类。后面将要介绍的集中特效同样继承自 osgFX::Efect类。因此,如果读者需要自己编写相关的特效,可以继承自osgFX::Effect 类
下面介绍osgFX::AnisotropicLighting 的一些成员函数:
- osg::lmage* getLightingMap () // 得到光照贴图
- const osg::Image " getLightingMap () const // 得到const光照贴图
- void setLightingMap(osg::Image *image) // 设置光照贴图
- int getLightNumber() const // 得到光源数
- void setLightNumber(int n) // 设置光源数,通常支持的光源数8个以下
异性光照特效示例
下面通过一个例子来学习如何在场景中添加osgFX::AnisotropicLighting 特效代码如程序清单12-1所示。
1. /********************************** 异性光照特效示例12-1 ************************************/
2. void anisotropicLighting_12_1(const string &strDataFolder)
3. {
4. osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
5. osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
6. traits->x = 40;
7. traits->y = 40;
8. traits->width = 600;
9. traits->height = 480;
10. traits->windowDecoration = true;
11. traits->doubleBuffer = true;
12. traits->sharedContext = 0;
13.
14. osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
15.
16. osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
17. camera->setGraphicsContext(gc.get());
18. camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
19. GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
20. camera->setDrawBuffer(buffer);
21. camera->setReadBuffer(buffer);
22.
23. // 读取模型,读取飞机模型
24. string strDataPath = strDataFolder + "cessna.osg";
25. osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(strDataPath);
26.
27. // 读取贴图
28. strDataPath = strDataFolder + "Images\\osg256.png";
29. osg::ref_ptr<osg::Image> image = osgDB::readImageFile(strDataPath);
30.
31. // 创建各向异性光照
32. osg::ref_ptr<osgFX::AnisotropicLighting> atl = new osgFX::AnisotropicLighting();
33.
34. // 设置光照图
35. atl->setLightingMap(image);
36.
37. // 设置光源数,支持光源数在8以下
38. atl->setLightNumber(7);
39. atl->addChild(node.get());
40.
41. osg::ref_ptr<osg::Group> root = new osg::Group();
42. root->addChild(atl.get());
43.
44. // 优化场景数据
45. osgUtil::Optimizer optimizer;
46. optimizer.optimize(root.get());
47.
48. viewer->setSceneData(root.get());
49.
50. viewer->realize();
51. viewer->run();
52. }
运行程序,截图如图12-3 所示。
图12-3异性光照特效示例截图
凹凸贴图特效
凹凸贴图(Bump Mapping)特效可以创建一种凹凸不平的表面效果。其子节点必须使用两种纹理,一种是漫反射颜色,另一种是法线贴图(可以使用 aVIDIA 的法线贴图生成器或其他工具,根据高度图自动生成)。此外,还需要创建正切空间 (tangent-space)的基向量并将其关联到每个 Geometry 几何体上(这一步骤可以调用BumpMapping::prepareChildren()方法迅速完成)。注意Geometry对象的漫反射颜色和法线贴图纹理都必须提前定义好对应的UV贴图.该特效推荐使用一种运用了ARB顶点和片段着色器的技法,另外,还定义了一种不使用片段着色器的技法。后者无法处理环境和镜面组件的运算,因此在运行时很受限制。
osgFX::BumpMapping 的继承关系图如图12-4所示。
图12-4 osgFX::BumpMapping 的继承关系图
从继承关系图中可以看出osgFX::BumpMapping 继承自ogFX::Effect类,也是一个组节点,可以添加自己的叶节点。
下面介绍osgFX::BumpMapping 的一些成员函数:
int getLightNumber()const// 得到光源数
void setLightNumber(int n) // 设置光源数
int getDiffuseTextureUnit()const// 得到漫反射纹理单元
void setDiffuseTextureUnit(int n) // 设置漫反射纹理单元
int getNormalMapTextureUnit()const// 得到法线纹理单元
void setNormalMapTextureUnit(int n) // 设置法线纹理单元
osg::Texture2D* getOverrideDiffuseTexture()//得到替代子节点的漫反射纹理
const osg::Texture2D * getOverrideDiffuseTexture()const// 得到替代子节点的漫反射纹理
void setOverrideDiffuseTexture(osg::Texture2D *texture) // 设置替代子节点的漫反射的纹理
osg::Texture2D* getOverrideNormalMapTexture()// 得到替代子节点的法线纹理
const osg:Texture2D * getOverrideNormalMapTexture()const// 得到替代子节点的法线纹理
void setOverrideNormalMapTexture(osg::Texture2D *texture) // 设置替代子节点的法线纹理
void prepareGeometry(osg::Geomctry *geo) //预备一个Geometry用来实现凸凹光照
void prepareNode(osg::Node *node) //预备一个Geometry用来实现凸凹光照
void prepareChildren0) //预备一个Geomctry 用来实现凸凹光照
void setUpDemo()//设置默认的漫反射和法线贴图环境
贴图特效示例
下面通过一个例子来学习如何在场景中添加osgFX::BumpMapping 特效。
代码如程序清单 12-2所示。
1. /********************************** 凹凸贴图特效示例12-2 ************************************/
2. void bumpMapping_12_2(const string &strDataFolder)
3. {
4. osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
5. osg::ref_ptr<osg::Group> root = new osg::Group();
6. osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
7. traits->x = 40;
8. traits->y = 40;
9. traits->width = 600;
10. traits->height = 480;
11. traits->windowDecoration = true;
12. traits->doubleBuffer = true;
13. traits->sharedContext = 0;
14.
15. osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
16.
17. osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
18. camera->setGraphicsContext(gc.get());
19. camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
20. GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
21. camera->setDrawBuffer(buffer);
22. camera->setReadBuffer(buffer);
23.
24. // 读取模型,读取飞机模型
25. string strDataPath = strDataFolder + "cessna.osg";
26. osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(strDataPath);
27.
28. //创建凹凸贴图对象
29. osg::ref_ptr<osgFX::BumpMapping> bm = new osgFX::BumpMapping();
30. //添加子节点
31. bm->addChild(node.get());
32. //设置光源数
33. //bm->setLightNumber(6);
34. //设置漫反射纹理单元
35. bm->setDiffuseTextureUnit(0);
36. //设置法线纹理单元,注意不能于前面的漫反射单元相同
37. bm->setNormalMapTextureUnit(1);
38. //设置默认的漫反射和法线贴图环境,并设置相关的纹理坐标
39. bm->setUpDemo();
40.
41. root->addChild(bm.get());
42.
43. // 优化场景数据
44. osgUtil::Optimizer optimizer;
45. optimizer.optimize(root.get());
46.
47. viewer->setSceneData(root.get());
48.
49. viewer->realize();
50. viewer->run();
51. }
运行程序,截图如图12-5 所示。
图12-5 凹凸贴图特效示例图
卡通染特效
卡通渲染(Cartoon)特效实现了一种名为卡通着色(Cel-Shading)的方法,从而产生一种卡通式的(非真实感的)渲染效果。它需要两个通道支持:第一个用于绘制实体表面,第二个用于绘制轮廓线。该特效需要使用顶点着色器来设置纹理坐标,以便在运行时生成的纹理单元0上实现一种尖锐的光照效果。该特效需要ARB_vertex_program扩展或者OpenGL着色语言的支持。osgFX::Cartoon的继承关系图如图12-6所示。
图12-6 osgFX::Cartoon 的继承关系图
1. // 得到轮廊线的颜色
2. const osg::Vec4 & getOutlineColor() const
3. // 设置轮廓线的颜色
4. void setOutlineColor (const osg::Vec4 &color)
5. // 得到轮廓线的宽度
6. float getOutlineLineWidth()const
7. // 设置轮廊线的宽度
8. void setOutlincLineWidth (float w)
9. // 得到光源数
10. int getLightNumber() const
11. // 设置光源数
12. void setLightNumber(int n)
卡通渲染特效示例
下面通过一个例子来学习如何在场景中添加osgFX::Cartoon特效。
代码如程序清单12-3所示。
1. /********************************** 卡通渲染特效示例12-3 ************************************/
2. void cartoon_12_3(const string &strDataFolder)
3. {
4. osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
5. osg::ref_ptr<osg::Group> root = new osg::Group();
6. osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
7. traits->x = 40;
8. traits->y = 40;
9. traits->width = 600;
10. traits->height = 480;
11. traits->windowDecoration = true;
12. traits->doubleBuffer = true;
13. traits->sharedContext = 0;
14.
15. osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
16.
17. osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
18. camera->setGraphicsContext(gc.get());
19. camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
20. GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
21. camera->setDrawBuffer(buffer);
22. camera->setReadBuffer(buffer);
23.
24. // 读取模型,读取飞机模型
25. string strDataPath = strDataFolder + "cessna.osg";
26. osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(strDataPath);
27.
28. // 创建卡通渲染对象
29. osg::ref_ptr<osgFX::Cartoon> ct = new osgFX::Cartoon();
30. ct->setOutlineColor(osg::Vec4(1.0, 1.0, 1.0, 1.0)); // 设置轮廓线的颜色
31. ct->setOutlineLineWidth(2.0);// 设置轮廓线的宽度
32. ct->setLightNumber(0); // 设置光源数,通常设置为0
33. ct->addChild(node.get());//添加子节点
34.
35. root->addChild(ct.get());
36.
37. // 优化场景数据
38. osgUtil::Optimizer optimizer;
39. optimizer.optimize(root.get());
40.
41. viewer->setSceneData(root.get());
42.
43. viewer->realize();
44. viewer->run();
45. }
运行程序,截图如图 12-7
图 12-7卡通渲染特效例截图
相关文章:

osgFX扩展库-异性光照、贴图、卡通特效(1)
本章将简单介绍 osgFX扩展库及osgSim 扩展库。osgFX库用得比较多,osgSim库不常用,因此,这里只对这个库作简单的说明。 osgFX扩展库 osgFX是一个OpenSceneGraph 的附加库,是一个用于实现一致、完备、可重用的特殊效果的构架工具,其…...
SELinux零知识学习三十一、SELinux策略语言之角色和用户(2)
接前一篇文章:SELinux零知识学习三十、SELinux策略语言之角色和用户(1) 三、SELinux策略语言之角色和用户 SELinux提供了一种依赖于类型强制(类型增强,TE)的基于角色的访问控制(Role-Based Access Control),角色用于组域类型和限制域类型与用户之间的关系,SELinux中…...

Unity UGUI的自动布局-LayoutGroup(水平布局)组件
Horizontal Layout Group | Unity UI | 1.0.0 1. 什么是HorizontalLayoutGroup组件? HorizontalLayoutGroup是Unity UGUI中的一种布局组件,用于在水平方向上对子物体进行排列和布局。它可以根据一定的规则自动调整子物体的位置和大小,使它们…...
【SpringCloud】设计原则之分层架构与统一通信协议
一、设计原则之分层架构 应用分层看起来很简单,但每个程序员都有自己的一套方法,哪怕是初学者,所以实施起来并非易事 最早接触的分层架构应该是最熟悉的 MVC(Model - View - Controller)架构,其将应用分成…...

在Linux环境如何启动和redis数据库?
Linux中连接redis数据库: 前台启动: 第一步:redis-server:服务器启动命令 当我们启动改窗口后,出现如下所示: 该窗口就不能关闭,否则会出现redis无法使用的情况,重新打开一个窗口,…...

selenium判断元素是否存在的方法
文章目录 快捷方法完整示例程序 快捷方法 selenium没有exist_xxx相关的方法,无法直接判断元素存在。但是锁定元素时使用的browser.find_elements(By.CSS_SELECTOR, "css元素")会返回一个列表list,如果不存在这个元素就会返回一个空列表。因此…...
后端真批量新增的使用
1,添加真批量新增抽象接口 public interface EasyBaseMapper extends BaseMapper { /** * 批量插入 仅适用于mysql * * return 影响行数 */ Integer insertBatchSomeColumn(Collection entityList); } 2,新增类,添加真批量新增的方法 public class InsertBatchSqlInjector ext…...

HttpRunner原来还能这么用,大开眼界!!!
hook机制 Httprunner 框架中的 hook 机制相当于unittest框架中的 setup , teardown 函数,用来进行测试用例执行之前的环境初始化以及测试用例执行完毕之后的环境清理操作。 httprunner 中的 hooks 机制可以用在测试用例层级也可以用在测试步骤层级,其关键…...
给WordPress 自带的搜索功能添加过滤只搜索文章的标题
如果想让 WordPress 自带的搜索功能只搜索文章标题,让搜索结果更加精确(其实WordPress 自带的搜索功能本来模糊查找就很弱),可以将下面的代码添加到当前主题functions.php中: 用过滤器:posts_search 就可以…...
frp内网穿透
1 概述 frp 是什么? frp 是一款高性能的反向代理应用,专注于内网穿透。它支持多种协议,包括 TCP、UDP、HTTP、HTTPS 等,并且具备 P2P 通信功能。使用 frp,您可以安全、便捷地将内网服务暴露到公网,通过拥有公网 IP 的节点进行中转。frp原理 公网服务器作为服务端,内网服…...

哈希和unordered系列封装(C++)
哈希和unordered系列封装 一、哈希1. 概念2. 哈希函数,哈希碰撞哈希函数(常用的两个)哈希冲突(碰撞)小结 3. 解决哈希碰撞闭散列线性探测二次探测代码实现载荷因子(扩容) 开散列哈希桶代码实现扩…...
PHP基础与安全
基础 1. 简介概述 ●PHP是脚本语言-是一门弱类型语言,不需要事先编译 ●PHP 脚本在服务器上执行,然后向浏览器发送回纯文本的 HTML 结果 ●超文本预处理器,服务器端脚本语 2.创建(声明)PHP变量 ● 变量以 $ 符号开…...

【面试HOT200】滑动窗口篇
系列综述: 💞目的:本系列是个人整理为了秋招面试的,整理期间苛求每个知识点,平衡理解简易度与深入程度。 🥰来源:材料主要源于【CodeTopHot200】进行的,每个知识点的修正和深入主要参…...
cocos2dx Animate3D(三)
一些总结 动作(Actions) move移动:moveto/moveby 从一个位置移动到另外一个位置 从一个位置移动多少数量级rotate旋转:rotateto/rotateby 从一个角度旋转到另外一个角度 旋转多少个数量级scale缩放:scaleto/scaleby …...

单文件组件MVVM
单文件组件&MVVM 所谓组件化开发,就是创建一个个组件。 Vue是一个大类,渲染一切从new Vue开始。 指定视图:el template render:jsx语法 $mount[数学公式] 编译App.vue,作为视图入口 单个组件:结构 样式 data compu…...

python基础练习题库实验6
文章目录 题目1代码实验结果题目2代码实验结果题目3代码实验结果题目4代码实验结果题目总结题目1 根据以下规范编写一个函数: 函数名称:triple输入参数:1个输入参数数据类型字符串返回值:函数返回1个字符串值。该字符串由每个字符重复3次的句子构成。例如,如果句子是Uni,…...

SwiftUI 如何动态开始和停止播放永久重复(repeatForever)动画
0. 功能需求 在 SwiftUI 丰富多彩的动画世界中,我们有时希望可以随意开始和停止永久循环(repeatForever)的动画,不过这时往往会产生错误的动画“叠加”效果。 从上图可以看到:虽然我们希望密码输入框背景只在用户输入密码时才发生闪烁,但顶部的密码输入框随着不断输入其…...
批量采集淘宝商品数据,有哪些方式可以实现?
引言 在当今的数字化时代,数据已经成为企业竞争的核心资源。对于电商行业来说,对商品数据的采集和分析更是关键。淘宝作为中国最大的电商平台之一,其丰富的商品数据和用户行为数据具有极高的价值。那么,如何批量采集淘宝商品数据…...

Solidworks模型上色技巧以及增加快捷键快速打开和关闭“阴影效果和楼板反射”
Solidworks模型上色技巧 Chapter1 给Solidworks模型上色技巧设置外观的方法具体操作删除颜色的技巧这样操作: Chapter2 SOLIDWORKS小技巧 | SolidWorks装配体零件快速上色自动设置Chapter3 solidworks装配图如何去掉阴影?Solidworks2022中的阴影效果怎么…...

Corel产品注册机Corel Products KeyGen 2023 – XFORCE解决会声会影2023试用30天
CorelDRAW注册机2023支持全系列产品_Corel Products KeyGen 2023 X-FORCE v8 CorelDRAW注册机2023支持全系列产品_Corel Products KeyGen 2023 X-FORCE v8,Corel产品注册机(Corel Products KeyGen 2023 – XFORCE),支持Corel旗下所…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...

2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》
🧠 LangChain 中 TextSplitter 的使用详解:从基础到进阶(附代码) 一、前言 在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个…...