OpenGL的状态机理解
OpenGL是一种状态机模式,比如你用glEnable打开一个状态,在以后的绘图中将一直保留并应用这个状态,除非你调用glDisable及同类函数来改变该状态或程序退出。例如当前颜色是一个状态变量,可以把当前颜色设置为白色、红色或其他任何颜色,在此之后绘制的所有物体都将使用这种颜色,直到把当前颜色设置为其他颜色。
除当前颜色之外,OpenGL绝大多数函数都是一种状态机,如控制当前视图和投影变换、直线和多边形点画模式、多边形绘图模式、像素包装约定、光照的位置和特征以及被绘制物体的材料属性等。
前一段时间里,论坛有位朋友问什么是状态机。按我的理解,状态机就是一种存在于理论中的机器,它具有以下的特点:
1. 它有记忆的能力,能够记住自己当前的状态。
2. 它可以接收输入,根据输入的内容和自己的状态,修改自己的状态,并且可以得到输出。
3. 当它进入某个特殊的状态(停机状态)的时候,它不再接收输入,停止工作。
理论说起来很抽象,但实际上是很好理解的。
首先,从本质上讲,我们现在的电脑就是典型的状态机。可以对照理解:
1. 电脑的存储器(内存、硬盘等等),可以记住电脑自己当前的状态(当前安装在电脑中的软件、保存在电脑中的数据,其实都是二进制的值,都属于当前的状态)。
2. 电脑的输入设备接收输入(键盘输入、鼠标输入、文件输入),根据输入的内容和自己的状态(主要指可以运行的程序代码),修改自己的状态(修改内存中的值),并且可以得到输出(将结果显示到屏幕)。
3. 当它进入某个特殊的状态(关机状态)的时候,它不再接收输入,停止工作。
OpenGL也可以看成这样的一种机器。让我们先对照理解一下:
1. OpenGL可以记录自己的状态(比如:当前所使用的颜色、是否开启了混合功能,等等,这些都是要记录的)
2. OpenGL可以接收输入(当我们调用OpenGL函数的时候,实际上可以看成OpenGL在接收我们的输入),根据输入的内容和自己的状态,修改自己的状态,并且可以得到输出(比如我们调用glColor3f,则OpenGL接收到这个输入后会修改自己的“当前颜色”这个状态;我们调用glRectf,则OpenGL会输出一个矩形)
3. OpenGL可以进入停止状态,不再接收输入。这个可能在我们的程序中表现得不太明显,不过在程序退出前,OpenGL总会先停止工作的。
还是没理解?呵呵,看来这真不是个好的开始呀,难得等了这么久,好不容易教程有更新了,怎么如此的难懂啊??没关系,实在没理解,咱就不理解它了。接着往下看。
为什么我要提到“状态机”这个枯燥的、晦涩的概念呢?其实它可以帮助我们理解一些东西。
比如我在前面的教程里面,经常说:
可以使用glColor*函数来选择一种颜色,以后绘制的所有物体都是这种颜色,除非再次使用glColor*函数重新设定。
可以使用glTexCoord*函数来设置一个纹理坐标,以后绘制的所有物体都是采用这种纹理坐标,除非再次使用glTexCoord*函数重新设置。
可以使用glBlendFunc函数来指定混合功能的源因子和目标因子,以后绘制的所有物体都是采用这个源因子和目标因子,除非再次使用glBlendFunc函数重新指定。
可以使用glLight*函数来指定光源的位置、颜色,以后绘制的所有物体都是采用这个光源的位置、颜色,除非再次使用glBlendFunc函数重新指定。
……
呵呵,很繁,是吧?“状态机”可以简化这个描述。
OpenGL是一个状态机,它保持自身的状态,除非用户输入一条命令让它改变状态。
颜色、纹理坐标、源因子和目标因子、光源的各种参数,等等,这些都是状态,所以这一句话就包含了上面叙述的所有内容。
此外,“是否启用了光照”、“是否启用了纹理”、“是否启用了混合”、“是否启用了深度测试”等等,这些也都是状态,也符合上面的描述:OpenGL会保持状态,除非我们调用OpenGL函数来改变它。
| 取得OpenGL的当前状态 OpenGL保存了自己的状态,我们可以通过一些函数来取得这些状态。 首先来说一些启用/禁用的状态。 我们通过glEnable来启用状态,通过glDisable来禁用它们。例如: glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); 可以用glIsEnabled函数来检测这些状态是否被开启。例如: glIsEnabled(GL_DEPTH_TEST); glIsEnabled(GL_BLEND); glIsEnabled(GL_CULL_FACE); glIsEnabled(GL_LIGHTING); glIsEnabled(GL_TEXTURE_2D); 如果状态是开启的,则glIsEnabled函数返回GL_TRUE(这是一个不为零的常量,一般被定义为1);否则返回GL_FALSE(这是一个常量,其值为零) 我们可以在程序里面写: if( glIsEnabled(GL_BLEND) ) {
// 当前开启了混合功能 } else { // 当前没有开启混合功能 } 再看其它类型的状态。 // 取得当前的直线宽度
GLfloat lw; glGetFloatv(GL_LINE_WIDTH, &lw); // 取得当前的颜色 GLfloat cc[4]; glGetFloatv(GL_CURRENT_COLOR, cc); // 取得当前的视口 GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); 说明: GLfloat cc[4];
GLdouble dcc[4]; glGetFloatv(GL_CURRENT_COLOR, cc); glGetDoublev(GL_CURRENT_COLOR, dcc); glGetBooleanv, glGetIntegerv, glGetFloatv, glGetDoublev这四个函数可以得到OpenGL中多数的状态,但是还有一些状态不便用这四个函数来取得。比如光源的状态,因为可能有多个光源,所以不可能使用类似glGetFloatv(GL_LIGHT_POSITION, pos);这样的方法来得到光源位置。为了解决这个问题,OpenGL专门提供了glGetLight*系列函数,来取得光源的状态。 |
设置OpenGL状态
呵呵,读者可能会有疑问。既然有getXXX这样的函数来取得OpenGL的状态,那么为什么没有setXXX这样的函数来设置OpenGL状态呢?
答案很简单,因为OpenGL已经提供了大量的函数来设置状态了:glColor*, glMaterial*, glEnable, glDisable, 等等,大多数OpenGL函数都是用来设置OpenGL状态的,因此不需要再设计一个setXXX函数来设置OpenGL状态。
OpenGL的状态机理解的更多相关文章
- 小强学渲染之OpenGL状态机理解
状态机是理论上的一种机器,呃这个说法非常非常的抽象.通俗一点理解,状态机描述了一个对象在其生命周期内所经历的各种状态,状态间的转变,发生转变的动因,条件及转变中所执行的活动.或者说,状态机是一种行为, ...
- OpenGL坐标系的理解
搬运自: https://learnopengl-cn.github.io/01%20Getting%20started/08%20Coordinate%20Systems/#3d 为了将坐标从一个坐 ...
- opengl的矩阵理解
原文链接:http://blog.csdn.net/byhuang/article/details/1476199 矩阵真的是一个很神奇的数学工具, 虽然单纯从数学上看, 它并没有什么特别的意义, 但 ...
- Android OpenGL ES(七)----理解纹理与纹理过滤
1.理解纹理 OpenGL中的纹理能够用来表示图像.照片,甚至由一个数学算法生成的分形数据.每一个二维的纹理都由很多小的纹理元素组成.它们是小块的数据,类似于我们前面讨论过的片段和像素.要使用纹理,最 ...
- opengl微发展理解
1.什么是OpenGL? 一种程序,可以与界面和图形硬件交互作用.一个开放的标准 2.软件管道 请看上图 - Apllication层 表示你的程序(调用渲染命令.如opengl API) - ...
- OpenGL理解
说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640*480分辨率.16色 ...
- opengl入门学习
OpenGL入门学习 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640 ...
- OpenGL入门学习(转)
OpenGL入门学习 http://www.cppblog.com/doing5552/archive/2009/01/08/71532.html 说起编程作图,大概还有很多人想起TC的#includ ...
- 小强学渲染之OpenGL的CPU管线
读到这里,应该对OpenGL渲染管线有了初步简单了解.下面着重分析CPU管线,即逻辑控制中心做了什么,这部分还是容易理解的.如下图: 一,将数据加载到显存中. 这是由GPU是访问显存中的数据决定的.因 ...
随机推荐
- QTP特点有哪些?
QTP特点有哪些? 浏览:77 | 更新:2013-06-19 12:35 QTP是一个侧重于功能的回归自动化测试工具:提供了很多插件,如:.NET的,Java的,SAP的,Terminal Emul ...
- 深入分析ENode的内部实现流程和关键地方的幂等设计
ENode 2.0 - 深入分析ENode的内部实现流程和关键地方的幂等设计 前言 ENode架构图 ENode框架内部实现流程分析 Command的幂等处理 Domain Event持久化时的并发冲 ...
- svn外网访登录不进去提示证书错误Authorization Required
为了外网能访问内网svn.于是坐在外网端口映射.但是奇怪的是内网能访问,外网总也登录不进去.以为是浏览器版本低 但是其他浏览器也一样.最后客户端也登录不进去.提示报错: Authorization ...
- cvs vss svn和git比较
cvs vss svn和git比较 特征 CVS Git Mercurial Subversion 是否原子提交 CVS: 没有. CVS提交不是原子的 Git: 是的. 提交都是原子的 Mercur ...
- iOS基础 - 触摸事件与手势识别
一.iOS的输入事件 UIKit可识别三种类型的输入事件: 触摸事件 运动(加速计)事件 远程控制事件 二.UIEvent iOS中许多事件对象都是UIEvent类的实例,记录事件产生的时刻和类型 U ...
- 浅谈DevExpress<二>:设计一个完整界面(2)
下面来把剩下的工作做完,换肤功能昨天已近讨论过,今天就不重复了.首先建立三个全局变量,一个存放文件路径,一个存放数据,一个存放过滤条件. string DBFileName; DataView dat ...
- 7 MySQL存储过程和函数
目录: 1. 存储过程和函数概述2. 准备工作3. 存储过程操作4. 创建带参存储过程5. 查看存储过程 1. 存储过程和函数概述 MySQL的存储过程(stored procedure)和函数(st ...
- jquery 分页控件1
jquery 分页控件(一) 以前一直都是用别人的分页控件,虽然用得很爽,但总觉的还是自己写个小插件比较好,这个插件效果.代码等都有参照别人完成的控件.即便功能并不是那么完善,扩展性也不好,bug或许 ...
- [转]iOS Anti-Debugging Protections
source-1: http://www.coredump.gr/articles/ios-anti-debugging-protections-part-1/ source-2: http://ww ...
- 一点MongoDB的基础及mongodb在mac上的安装
最近发现维持写博客的习惯还是挺困难的,尤其对我来说,计划好的事过了好长时间才想到要去做. 这段时间一直在熟悉MongoDB,首先我是参考的这一篇:8天学通MongoDB 原博主写得非常好,我这里就 ...