设为首页 加入收藏

TOP

OpenGL超级宝典学习笔记——Using OpenGL(三)
2015-02-25 22:43:40 来源: 作者: 【 】 浏览:28
Tags:OpenGL 超级 宝典 学习 笔记 Using

OpenGL状态机


? ? 绘制3D图形是一项复杂的任务。我们需要许多的属性,比如光照属性,材料属性,纹理等。如果我们在每次绘制图形的时候,都去设置这些属性,或者以参数的形式传进去。那工作量非常大,而且还易出错。所以OpenGL使用了状态模式,来管理这些属性,使得图形编程变得更简洁,容易。


? ? 光照属性,材料属性等等属性变量的集合就是管线的状态。状态机是一系列状态变量的集合的抽象模型。每个状态变量可以有不同的值,例如打开或关闭等。


打开状态可以使用:


void glEnable(GLenum capability);


关闭状态可以使用


void glDisable(GLenum capability);


例子:


打开光照


glEnable(GL_LIGHTING);


关闭光照


glDisable(GL_LIGHTING);


Opengl还提供了检查这些状态的方法:


GLboolean glIsEnabled(GLenum capability);


不是所有的状态变量只有简单的打开或关闭的状态。许多OpenGL的函数设置这些状态值一直到被改变为止。你可以随时查找这些状态变量的值。OpenGL提供了各种类型的超找函数。


void glGetBooleanv(GLenum pname, GLboolean params);


void glGetDoublev(GLenum panme, GLdouble params);


void glGetFloatv(GLenum pname, GLfloat params);


void glGetIntegerv(GLenum pname, GLint params);


每一个函数返回一个值或者一个值数组,存储在你提供的参数params中。


保存和恢复状态


OpenGL提供了保存和恢复状态的方法。是使用栈(后进先出LIFO)的方式来保存这些变量的。


两个OpenGL的命令如下:


保存状态 void glPushAttrib(GLbitfield mask);


恢复状态 void glPopAttrib(GLbitfield mask);


参数是使用位段的方式来保存状态。这就意味着你可以在单个函数调用中用位OR操作来表示多个状态。


例如:


glPushAttrib(GL_TEXTURE_BIT|GL_LIGHTING_BIT);


获取时:


glPopAttrib(mask);


if (mask & GL_LIGHTING_BIT == GL_LIGHTING_BIT)? glEnable(GL_LIGHTING);


OpenGL的错误处理


OpenGL在内部维护了一组错误标志,每个标志代表一种不同类型的错误。当一个错误发生时,与这个错误相对应的标志会被设置。我们可以调用glGetError(void)来检查这些标志。


GLenum glGetError(void);


glGetError会返回一个错误值。如果被设置的错误值不止一个,glGetError仍然只返回一个值。需要遍历不断去取值,持续检查错误值,直到返回GL_NO_ERROR。


错误代码
描述


GL_INVALID_ENUM
枚举值超出函数范围


GL_INVALID_VALUE
数值参数超出范围


GL_INVALID_OPERATION
在当前的状态下操作非法


GL_STACK_OVERFLOW
堆栈上溢


GL_STACK_UNDERFLOW
堆栈下溢


GL_OUT_OF_MEMORY
没有足够的内存来执行这条命令


GL_TABLE_TOO_LARGE
指定的表太大


GL_NO_ERROR
没有出现错误


我们可以使用GLU函数库的另一个函数gluErrorString来获得一个错误标志的字符串描述


const GLubyte gluErrorString(GLenum errorCode);


这个函数将错误标志作为它的唯一参数,并返回一个描述这个错误的静态字符串。


例子: 如果当前的错误标志位GL_INVALID_ENUM,则


gluErrorString(glGetError()); 将返回


invalid enumerant?


获取版本


有时候我们希望利用一个特定环境所提供的特定功能。我们需要针对不同的环境进行编程的话,我们需要知道OpenGL驱动程序的生产商和版本号。可以调用glGetString


const GLubyte glGetString(GLenum name);


这个函数返回一个静态的字符串,描述了GL函数库的相关信息。


GLU函数库提供了另一个对应的函数gluGetString.


const GLubyte gluGetString(GLenum name);


这个函数返回一个字符串,描述它所请求的GLU函数的相关信息。


glHint


有时我们需要在性能和渲染效果中进行选择,而glHint能给OpenGL提供一个启示,你更关注渲染效果还是性能。


glHint允许指定偏重与视觉还是性能,函数原型如下:


void glHint(GLenum target, GLenum mode);


target指定行为类型。mode参数则告诉OpenGL我们最为关心的部分。这是唯一一个完全依赖于生产商的实现的函数。


检查扩展


OpenGL允许厂商进行扩展。要检查一个驱动程序包含了哪些扩展。如下:


const char szExtensions = glGetString(GL_EXTENTIONS);


这个字符串包含了驱动程序支持的所有扩展名称(用空格分隔)。查找希望使用的扩展:


if(strstr(extensions, “WGL_EXT_swap_control”)? != NULL)
{
? ? wglSwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress(“wglSwapIntervalEXT”);
? ? if (wglSwapIntervalEXT != NULL)
? ? ? ? ? wglSwapIntervalEXT(1);
}


使用这种方法,还应该确保扩展后面的那个字符串是空格或NULL,否则如果这个扩展被WGL_EXT_swap_control2所取代。此时C运行时函数strstr仍然找到第一个字符串,但是我们无法确定第二个的行为和第一个是否相同。


OpenGL的扩展前缀


NVida的扩展得到了广泛的使用,ATI也支持了NVida的扩展。


ARB批准的扩展,是通过OpenGL ARB的审查的扩展。


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇OpenGL超级宝典学习笔记——Using.. 下一篇OpenGL超级宝典学习笔记——空间..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: