osgFX扩展库-异性光照、贴图、卡通特效(1)

2023-11-29 03:01

本文主要是介绍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 的一些成员函数:

  1. osg::lmage* getLightingMap () // 得到光照贴图  
  2. const osg::Image " getLightingMap () const // 得到const光照贴图  
  3. void setLightingMap(osg::Image *image) // 设置光照贴图  
  4. int getLightNumber() const // 得到光源数  
  5. 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)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/431199

相关文章

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

PHP7扩展开发之数组处理

前言 这次,我们将演示如何在PHP扩展中如何对数组进行处理。要实现的PHP代码如下: <?phpfunction array_concat ($arr, $prefix) {foreach($arr as $key => $val) {if (isset($prefix[$key]) && is_string($val) && is_string($prefix[$key])) {$arr[

PHP7扩展开发之字符串处理

前言 这次,我们来看看字符串在PHP扩展里面如何处理。 示例代码如下: <?phpfunction str_concat($prefix, $string) {$len = strlen($prefix);$substr = substr($string, 0, $len);if ($substr != $prefix) {return $prefix." ".$string;} else

PHP7扩展开发之类型处理

前言 这次,我们将演示如何在PHP扩展中如何对类型进行一些操作。如,判断变量类型。要实现的PHP代码如下: <?phpfunction get_size ($value) {if (is_string($value)) {return "string size is ". strlen($value);} else if (is_array($value)) {return "array si

『功能项目』战士的平A特效【35】

我们打开上一篇34武器的切换实例的项目, 本章要做的事情是在战士的每次按A键时在指定位置生成一个平A特效 首先将之前下载的技能拖拽至场景中 完全解压缩后重命名为AEffect 拖拽至预制体文件夹 进入主角动画的战士动画层级 双击第一次攻击 选择Animation 创建事件 创建的动画事件帧放在攻击动画挥剑指定处 命名为PerpetualAtt

PHP7扩展开发之依赖其他扩展

前言 有的时候,我们的扩展要依赖其他扩展。比如,我们PHP的mysqli扩展就依赖mysqlnd扩展。这中情况下,我们怎么使用其他扩展呢?这个就是本文讲述的内容。 我们新建立一个扩展,名字叫 demo_dep , 依赖之前的say扩展。 在demo_dep扩展中,我们实现demo_say方法。这个方法调用say扩展的say方法。 代码 基础代码 确保say扩展的头文件正确安装到了php

PHP7扩展开发之函数方式使用lib库

前言 首先说下什么是lib库。lib库就是一个提供特定功能的一个文件。可以把它看成是PHP的一个文件,这个文件提供一些函数方法。只是这个lib库是用c或者c++写的。 使用lib库的场景。一些软件已经提供了lib库,我们就没必要再重复实现一次。如,原先的mysql扩展,就是使用mysql官方的lib库进行的封装。 在本文,我们将建立一个简单的lib库,并在扩展中进行封装调用。 代码 基础

PHP7扩展开发之对象方式使用lib库

前言 上一篇文章,我们使用的是函数方式调用lib库。这篇文章我们将使用对象的方式调用lib库。调用代码如下: <?php $hello = new hello(); $result = $hello->get(); var_dump($result); ?> 我们将在扩展中实现hello类。hello类中将依赖lib库。 代码 基础代码 这个扩展,我们将在say扩展上增加相关代码。sa