上一次我们在这里分析了OpenGL的例子,但是最后还少分析最重要的部分:着色器相关的代码。因此这一次作为前一篇文章的续集。
上一篇文章的地址
首先我们回顾下之前的代码
ShaderInfo shaders[] = { { GL_VERTEX_SHADER, "triangles.vert" }, { GL_FRAGMENT_SHADER, "triangles.frag"}, { GL_NONE, NULL} };
这里的 triangles.vert 对应顶点着色器文件
#version 430 corelayout(location = 0) in vec4 vPosition;void main(){ gl_Position = vPosition;}
第一行#version 430 core 表示我们所使用的4.3版本的OpenGL对应的GLSL语言,core表示使用OpenGL的核心模式。
若#version没有设置,则默认使用110版本。
第二行layout(location=0) in vec4 vPosition 分配了一个着色器变量(着色器变量是着色器与外部世界的联系所在),就这么一行也是包含了许多内容,我们从右往左看:
1、vPosition指变量名称,它所保存的是顶点的位置信息
2、vec4是GLSL中的一种数据类型,在这里表示GLSL的四维浮点数向量,默认值为(0,0,0,1),表示(x,y,z,w)。当有字段缺失时,会填充对应的默认值。
在第三篇,我们将会进一步学习GLSL,这里先浅尝辄止。
3、in字段的话,表示设置这个变量,即vPosition为着色器阶段的输入变量,指定了数据进入着色器的流向,在这里代表数据从外部流入。
4、layout(location=0),这一字段非常重要,它将vPosition的位置属性location设置为0,为它提供了元数据。
回顾之前的代码,这一字段与glVertexAttribPointer以及glEnableVertexAttribArray产生了联系。使得我们的着色器变量可以获得相关联的数据。
/** 函数原型:void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer); 之前我们调用了glBindData所传递给缓存的只是数据,之后我们要使用它,还必须指定数据类型。 所以该函数完成的主要任务是: 1、告诉OpenGL,该存储数据的格式 2、因为我们使用着色器来编程,因此在顶点着色器阶段,我们会使用该函数来给着色器中的in类型的属性变量传递数据。 那么它们是怎么联系起来的呢? 便是通过第一个参数index,指明了着色器程序中变量的下标的作用。 例如:layout( location=index ) in vec4 position; 如果这个index和glVertexAttribPointer的第一个参数一样,那么相关缓存区的数据就会传递到这个position变量中去。 3、该函数执行之后,会影响改变VAO的状态,VBO会被复制保存到VAO中。之后如果改变了当前所绑定的缓存对象,也不会改变到VAO里的对象。 */ glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); /** 因为默认情况下,顶点属性数组是不可访问的,所以我们需要调用以下函数激活它。 范围为0到GL_MAX_VERTEX_ATTRIBS-1 */ glEnableVertexAttribArray(vPosition);
5、最后的main函数,无论是在哪一个着色阶段,都会有一个main函数。它所实现的就是将输入的顶点位置复制到顶点着色器的指定输出位置gl_Position中。
gl_Positon是一个内置变量,使用前不需要声明。在OpenGL中,它表示输出属性-变换后的顶点的位置,用于后面的固定的裁剪等操作。所有的顶点着色器都必须写这个值。
-------------------------------------------------------------------------------------------------------------------------------------------------------------
我们再继续看看片段着色器的代码
这里的 triangles.frag 对应顶点着色器文件
#version 430 coreout vec4 fColor;void main(){ fColor = vec4(0.0, 0.0, 1.0, 1.0);}
可以看得出,几乎所有着色器的基本结构都是这样的。
我们着重看看不同的地方
1、变量fColor使用的out类型的限定符,与之前的in相反,说明该着色器会将fColor所对应的数值输出,这也是片段所对应的颜色值。
2、fColor = vec4(0.0, 0.0, 1.0, 1.0)用一个四维向量设定了片段的颜色值。事实上,OpenGL使用了RGBA的颜色空间,
-------------------------------------------------------------------------------------------------------------------------------------------------------------
自此,我们完成了第一个OpenGL例子。还是要再次说明的是
glVertexAttribPointer以及glEnableVertexAttribArray两个函数指定了和顶点着色器的变量与存储在缓存对象中数据的关系。
-------------------------------------------------------------------------------------------------------------------------------------------------------------
在学习过程中,发现对VAO与VBO不是很明白的,可以继续看这一篇文章 【VAO与VBO】
另外,如果有发现我的内容有错误,恳请告诉我,我会改正,谢谢!
过几天,我会继续写第三篇 关于GLSL着色语言的。
2015.7.29
广州