对于刚刚接触OpenGL的同学来说,如果不能够很好的了解OpenGL基本的工作机制,那么即使能够在一个窗口中绘制一个三角形,也无法理清代码的运行原理,当遇到更加复杂的工程时,整个思绪就会更加混乱。本文主要介绍的是OpenGL的Context,也就是上下文,它可以帮助我们更好的理清整个OpenGL图形库到底是如何协调工作的。
OpenGL是一个状态机,它拥有非常多的状态变量,并且每个状态变量都有默认值。在程序中,我们可以设置它的各种状态,然后这些状态就会一直生效,直到我们再次修改它们。比如我们使用glClearColor()函数设置了清空窗口的颜色以后,那么,之后清空窗口都会使用该函数设置的这个颜色,直到我们再次调用这个函数进行修改。但是,我们可以对状态变量进行启用和禁用,比如,如果我们画一个2D三角形,就不需要深度测试,就可以通过glDisable(GL_DEPTH_TEST)关闭深度测试,它默认是关闭的,如果需要使用,可以通过glEnable(GL_DEPTH_TEST)启用该状态变量,针对该状态变量,还有一系列的值,包括一个默认值,一般深度测试的值都是一些测试函数。
获取当前状态变量的值:如果需要获取当前状态变量的值,可以使用OpenGL提供的一些获取value的函数,函数细节请参考:https://www.khronos.org/registry/OpenGL-Refpages/gl4/
上下文状态(Context State):
上下文状态控制着GPU渲染管线中的固定函数阶段,比如裁剪,片元的光栅化,帧缓存的清除,深度检测以及指定当前上下文所绑定的对象。
OpenGL是一个仅仅关注图形渲染的图像接口库,它所完成的工作也仅仅是计算机图形学的渲染部分。而OpenGL的渲染上下文是OpenGL在其中存储渲染信息的一个数据结构,它会将各种状态信息保存在上下文中,包括顶点信息、纹理信息、编译好的着色器信息等等,之后的绘制工作就要基于这些信息来完成,当一个上下文被销毁的时候,它所对应的OpenGL渲染工作也将结束。所以,当我们创建一个简单OpenGL的窗口时,总是会先进行以下工作。
GLFWwindow * window = glfwCreateWindow(SRC_WIDTH,SRC_HEIGHT,"Hello Triangle",NULL,NULL);
if (!window) {
cout << "Error: Fails to create window!" << endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
首先创建一个窗口,然后需要判断窗口是否创建成功,之后需要设置当前的上下文,设置完之后,所有的OpenGL命令都会用来改变当前的上下文的状态信息,OpenGL就会根据该上下文中的状态信息进行渲染工作。
一个进程可以创建多个Context,它们可以分别描绘出不同的图形界面,就像一个应用程序可以打开多个窗口一样。每个OpenGL Context是相互独立的,它们都有自己的OpenGL对象集,但是这些Context之间可以共享对象集合。
1.首先是版本信息
OpenGL版本信息查询:如下所示,前两个用于OpenGL3.0版本以上可用,第三个支持所有版本。
glGetString()函数用于查询一些版本和硬件厂商信息;其它上下文里的状态信息由glGetIntegerv()系列函数查询;
glGetIntegerv(GL_MAJOR_VERSION,*);
glGetIntegerv(GL_MINOR_VERSION,*);
glGetString(GL_VERSION);
GLint majorVersion;
glGetIntegerv(GL_MAJOR_VERSION, &majorVersion);
cout << "majorVersion: " << majorVersion << endl;
GLSL版本信息查询:当我们编写着色器时,第一行代码通常为#version,需要我们指定版本,这时如果想知道自己的GLSL版本,就可以通过API来查询。
glGetString(GL_SHADING_LANGUAGE_VERSION);
const GLubyte* glslVersion;
glslVersion=glGetString(GL_SHADING_LANGUAGE_VERSION);
cout << "glslVersion: " << glslVersion << endl;
当前所支持的GLSL版本信息查询:首先获取所支持的版本信息集,然后根据索引获取各个版本的详细信息。
glGetIntegerv(GL_NUM_SHADING_LANGUAGE_VERSION,*);
glGetStringi(GL_SHADING_LANGUAGE_VERSION,k); //k的值为0到GL_NUM_SHADING_LANGUAGE_VERSION-1
2.扩展列表查询
扩展列表的查询和上面的支持的GLSL版本的查询类似,首先获取扩展列表的数量,之后根据索引查询各个扩展。
glGetIntegerv(GL_NUM_EXTENSIONS,*);
glGetStringi(GL_EXTENSIONS,K);
GLint extensionNum;
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionNum);
cout << "extensionNum: " << extensionNum << endl;
OpenGL可查询的所有状态参考官方文档:https://www.khronos.org/registry/OpenGL-Refpages/gl4/
主要使用glGet*()函数,具体规范参考文档;