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旗下所…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
《Docker》架构
文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器,docker,镜像,k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...
算法—栈系列
一:删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...
