OSG渲染状态管理
来源:互联网 发布:剑灵男召唤师捏脸数据 编辑:程序博客网 时间:2024/06/05 06:34
转载:点击打开链接
1. 简介
OpenGL是一个状态机,在OpenGL中如果设置一种状态(比如设置当前的绘制颜色:glColor,那么实际上是设置了OpenGL颜色绘制状态为某种颜色,如果后续没有调用glColor去修改颜色,那么之后所有绘制的对象都使用之前设置的颜色。),在没有修改它的时候,该状态就会一直保持。在OpenGL使用中的状态有以下两种方式:
仅仅通过glEnable和glDisable开启和关闭状态
这里面也有两种不同的取值:
1.1 不涉及和其他状态相关,比如GL_DITHER、GL_POINT_SPRITE等;
1.2 涉及和其他状态的联动,比如GL_ALPHA_TEST、GL_BLEND等,需要使用glEnable开启状态和1.2种的某种状态对应,但是需要设置状态的值(比如glAlphaFunc、glBlendFunc)
在OSG中对OpenGL的状态进行了封装,在OSG中称第一种情形为Mode(模式),称第二种情况为Attribute(属性),使用osg::StateAttribute来封装OpenGL的状态。
2. OSG的状态
在OSG中涉及到状态管理的类有3个,分别是 osg::State, osg::StateSet, osg::StateAttribute,下面就这三个类的关系以及它们的使用方式做一些介绍:
- osg::State
这个类从某种程度上来说就是OpenGL的状态机的封装。它主要封装了当前OpenGL的模式、属性和顶点数组的设置,并且提供了一种lazy state updating的效果(只有当必须修改时,才修改状态),它也提供了查询当前OpenGL状态的函数。除此之外,osg::State还提供了以下特性:
(1)它使用了栈的方式来管理状态,一般来说很少需要我们来修改栈操作
(2)提供了glGet来获取当前的OpenGL状态
osg::State是一个非常大的类,从它的定义的代码中就可以看出来。通过查看它的成员变量,可以知道它包含的主要管理的状态包括:
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
这里面包含两类(模式和属性),其中对于纹理也分了两种(纹理模式和纹理属性),针对纹理额外分出来是因为OpenGL中的多重纹理的扩展,纹理可以使用多个,多个纹理可以相互作用最终影响物体渲染的效果,而普通的模式和属性没有这一特点。
2.1 模式的设置
根据我们上面的讨论,Mode只需要设置开启、关闭两种状态,因此它的记录比较简单,从感性上分析来说,如果用来记录OpenGL中所有的Mode,那么应该是一系列的键值对,也就是某一个模式和它开启和关闭状态的值,类似于
[ GL_LINGHT:true, GL_BLEND:false, …]这种样子。这是我们感性上的认识。在OSG中的实现略有不同,它考虑了状态的lazy updating的特性,因此对应的值是一个ModeStack,但是从原理上来说和我们的设想是一致的,都是提供一个值而已。
- 1
- 1
这其中StateAttribute::GLMode定义如下:(它的取值就是可以被设置在glEnable和glDisable中的枚举值,比如GL_LIGHTING, GL_BLEND, GL_DEPTH_TEST这样的值)
- 1
- 2
- 1
- 2
2.2 属性的设置
对于属性的设置,就有点麻烦了,因为OpenGL中的属性的取值很不一样,有的属性多,有的属性少,有的属性和模式有关联(比如光照计算的属性,必须开启了光照计算的模式,之后设置的光照计算的属性才能生效),有的属性和模式没有关联,这样封装起来就有点麻烦。
OSG对此的封装如下:所有的需要设置属性的类都从osg::StateAttribute继承,通过下图可以看出osg封装的属性的类型(osg 3.4.0版本)
OSG通过StateAttribute提供的函数来找到与Attribute相关联的模式(Mode)
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
默认情况下返回值是false,也就是说没有和它相关联的Mode,如果存在和它相关联的Mode,那么就返回该Mode值,比如osg::Point属性,用来设置点的大小属性,它的实现如下:
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
从函数实现可以知道与它相关联的模式(Mode)是GL_POINT_SMOOTH,那么在State中的
AttributeMap _attributeMap;
到底是什么呢?我们从感性上来说应该就是所有OpenGL的属性的集合,那么它是怎么记录属性值的呢?先看看它的定义:
- 1
- 1
可以看到它是一个Map,那么对应的键值对是什么呢,先看看键:
- 1
- 2
- 1
- 2
这里的type就是所有OpenGL封装的属性的类型,它定义如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
TypeMemberPair对应的第二个变量int值,对某些存在索引标号的属性有关(比如光照计算存在第0到第7号光源,这里的int值就对应0到7中的某一个值。除此之外还有裁剪面也存在Plane0到Plane7,但是这种带索引号的属性不是特别多),这样就可以区分出所有Attribute属性中哪一个变量的值是什么了。比如下面代码,当程序添加了两个裁剪面时,查看对应的TypeMemberPair值可以看到标号是0和1.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
调试中查看到的TypeMemberPair的变量:
对于没有索引号的属性,TypeMemberPair的第二个成员都是0
- osg::StateSet
这个类StateSet只保存了OpenGL状态的一小部分,在OSG场景中的每个节点和可绘制对象(Drawable)都包含一个StateSet,一个StateSet可以被多个Node和Drawable共享。这个类记录的状态信息会在节点遍历的过程中添加到osg::State中,从而对场景中的节点的渲染起到作用。
osg::State和osg::StateSet有点类似于总公司和分公司的关系,osg::StateSet相当于贴近场景渲染Node和Drawable的基层分公司,它记录Node和Drawable中的状态信息(比如这个节点是否开启光照计算、是否开启混合、混合和光照的参数设置值),一般来说各个分公司记录的信息都不一样,并且相对来说不会记录完整的状态信息(因为很少有节点设置所有的OpenGL状态,大部分还都是默认的)。 之后分公司会把捕获到的这些信息反馈给总公司(osg::State),最后由总公司了解到一个渲染对象(Node和Drawable)的完整的状态,并最终正确的渲染它。
查看osg::StateSet的源码,主要看它的成员变量中记录的信息,我们感兴趣的几个信息如下:
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
可以看到osg::StateSet就是一个Node和Drawable模式和属性的合集。
ModeList的定义如下:
- 1
- 1
看起来非常的自然,就是Mode和对应的取值。
AttributeList的定义如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
也就是说,AttributeList的类型是:
- 1
- 1
尝试着写一个Attribute的值:
- 1
- 1
在osg::StateSet中提供了许多函数用来获取某个特定的模式(Mode)和属性(Attribute),并且可以对它们进行必要的修改。比如:
- 1
- 2
- 1
- 2
其他的许多修改和获取函数可以参考该类的API手册。
- osg::StateAttribute
这个类就是OpenGL具体的某一个状态的封装,在osg::State的讨论中已经给出了osg所有继承于osg::StateAttribute的子类。它们就是所有OpenGL的状态的组成。集成于osg::StateAttribute的类都需要实现下面的一个虚函数:
- 1
- 1
查看osg::Point这个状态类的实现:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
这个类将状态传递给了OpenGL的状态机osg::State,最终对渲染的结果产生影响。当我们自定义OSG的状态时,需要重写这个函数,并且在里面写上对状态改变的一些函数。
参考文献:
- 最长的一帧26:关于渲染状态机的一些讨论
- OpenGL glEnable&glDisable
- OSG渲染状态管理
- OSG渲染状态管理
- OSG 结点渲染状态 类图
- [osg]状态管理
- osg 的状态树和渲染树
- osg入门系列-渲染状态实例
- OSG 学习第三天:渲染状态
- OSG的渲染树与状态树
- OGRE 渲染状态管理
- 渲染状态管理
- 渲染状态管理
- 渲染状态管理
- OSG渲染引擎架构
- OSG渲染树
- OpenSceneGraph源码分析——OSG状态机如何处理传入的渲染状态(StateSet)数据
- osg RTT 渲染到纹理
- osg demo24 多窗口渲染
- 学习osg渲染内核笔记
- 正则表达式表单验证实例
- 虚拟币开发专题(数字货币怎样从POW挖矿迁移到POS利息)
- pip 从本地文件夹安装
- 小白学习贴: C# TCP服务器
- json数据格式
- OSG渲染状态管理
- c++初始化
- awk(3)-awk getline
- codova安装与打包H5项目
- Android开发——ViewPage与TabLayout和BottomNavigationView
- leetcode_22_Generate Parentheses
- 记于7月11号的第一篇博文
- Vue.js数据状态管理-Vuex(二)
- 一条SQL语句中算日销售额和月销售额