写在前面的废话:今天俺又来了哈哈,真的好棒棒!
今天的内容:之前我们大概描述了,我们自己定义的顶点坐标是如何被加载到GPU之中,并且介绍了顶点缓冲对象VBO用于管理这一块内存。今天开始详细分析它的具体作用和用法。
首先OpenGL要求我们必须拥有一个顶点着色器和一个片段着色器,这样才可以进行渲染。当然这两个是必须经过编辑才能使用,而编辑所用的语言是GLSL(OpenGL Shading Language),然后编译这个着色器,这样我们就可以使用了。
举个例子像这样,
这是一个稍微复杂的顶点着色器的编写,大家可以先只看layout(location=0) in vec3 position.这一句我一步步向后解释。但在此之前我们#version 330 core表示的是我们所用的GLSL版本号是3.3 这个版本号要与我们之前在程序开头所用到的opengl的版本一致才可以。
接下来,进入顶点着色器的定义部分,in 在这被Xcode 理解成关键字,和后面out相对应,这里有点像hardwaresimulator里面的in 和out 他们分别表示了顶点着色器输入和输出所特定的数据类型。这里用到的数据类型都是向量型的,比如vec3 表示一个空间向量(即x,y,z),vec2表示的则是一个平面向量(x,y)。例如:这里第一行 in vec3 position 表示这个position这个变量是一个空间向量并且作为输入顶点着色器的存在。
layout(location=0)这里我暂时不解释,等下能提到。
注意你可能看到了一个叫vec4 的东西,这个地方插嘴补一句:在GLSL中一个向量有最多4个分量,每个分量值都代表空间中的一个坐标,它们可以通过vec.x
、vec.y
、vec.z
和vec.w
来获取。注意vec.w
分量不是用作表达空间中的位置的(我们处理的是3D不是4D),而是用在所谓透视划分(Perspective Division)上。当然这个还算是比较简单的,以后会有更为复杂的顶点着色器。
在这之前,提一下由于我这里已经学到后面独立文件里创建shader,刚入门的朋友们建议暂时把它们放到一个字符串中如下图。这样的目的是接着介绍如何编译这个着色器,也能让大家更加了解这一步。
之前我们已经编辑好了着色器的内容,接下来要编译他们,这样OpenGL才能实时动态使用他们。
先看代码
首先第一步,我们需要创建一个着色器对象,这里按照我的理解,OpenGL为我们封装好了很多编译所需要的东西,我们只需要先创建一个容器(也就是我们的顶点着色器),然后把我们具体操作放入其中,再编译即可。
所以这里参数写顶点着色器。
而在这之后,就到了向容器(vertexShader)里面放内容的步骤了。这里用到glshaderSource函数,首先 第一个参数表示我们容器的名字,第二个参数表示我们所装入的内容的长度,由于只有一个字符串,所以这里填1, 第三个参数就是我们之前的字符串的头指针,第四个直接写NULL。
为了保险,大家可以加上一个检测步骤,让程序运行的时候帮我检查这个顶点着色器是否书写正确。
GLuint success; //这个整形用于表示是否编译成功
GLchar infoLog[512]; //这个数组用于储存错误信息
glGetShaderiv(vertexShader,GL_COMPILE_STATUS,&success);//通过这个函数可以给success 赋值,如果编译通过则赋值1 失败赋值0
接下来判断success 的值
if(!success)
{
glGetShaderInfoLog(vertexShader,512,NULL,infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED
" << infoLog << std::endl;
}
ok ,以上就是顶点着色器的编辑和编译部分。接下来介绍片段着色器。
同样先创造一个空的容器.. 其他步骤与顶点着色器一致,代码如下。
接下来则是片段着色器的内容了。
#version 330 core out vec4 color; void main() { color = vec4(1.0f, 0.7f, 0.3f, 1.0f); }
简单给定一个RGBA格式的颜色即可。
好的,到目前为止,我们两个重要的着色器就完成了,接下来让我们把这两个单独的程序连接到一起,从而成为一个着色器程序对象(Shader Program Object )
正如之前介绍到的,渲染管线其实是一个阶段连着下一个阶段所形组成的,而现在我们所需要的程序对象,它的功能就是把我们之前定义的两个着色器的in和out链接起来,让他们可以相互完成传递。打个比方来说,两个着色器可以看作两个流水线上的工人,他们一个在前一个在后处理流水线上的东西,当前一个人交接任务给后一个人的时候,我们还没给定这个交接的时候统一接口。(前一个shader的out 是否作为后一个shader的in)
和之前创建着色器类似,代码如下:
唯一要注意的就是glAttachShader()函数的两个参数,第一个是目标程序,第二个是着色器。
好的今天暂时到这里,明天或者后天我将更加详细的解释下VBO以及后面的VAO。