传递顶点属性信息
之前讲过,vertex shader会被每个顶点调用,通常一个顶点会包含很多信息,例如顶点坐标、顶点法向量、纹理坐标等等,我们称这些信息为顶点的属性。在之前的OpenGL版本里,每个属性都对应了一个特定的通道,我们使用glVertex,glTexCoord,,glNormal(或者通过访问指针函数glVertexPointer, glTexCoordPointer, orglNormalPointer)等函数来访问和设置它们。随后,shader会自己通过内置变量gl_Vertex 和 gl_Normal来访问这些属性。但在OpenGL3.0版本里,这些都被弃用了。在后续版本里,甚至都被移除了。而现在,这些通过generic vertex attributes,图形顶点属性,来提供(通常和顶点缓冲对象互相协作来完成)。我们可以根据需要为每个顶点定义任意数量的(其实是在0到GL_MAX_VERTEX_ATTRIBS – 1之间)属性。OpenGL会为这些属性定义一个索引,我们只要根据这些索引来访问就可以了。
在一个vertex shader里,一个顶点属性是由GLSL 标识符 “in” 来定义的。例如,下面的代码里定义了两个vec3的属性,VertexPosition和VertexColor。
#version 400
in vec3VertexPosition;
in vec3 VertexColor;
out vec3 Color;
void main()
{
Color = VertexColor;
gl_Position = vec4(VertexPosition,1.0);
}
注意到这里还有一个类型为vec3的输出 Color,它将传递给下一层处理的shader中,这里也就是我们的fragment shader(fragment可以理解为具有很多属性的像素)。这里,我们还是使用之前那个简单的fragment shader。
#version 400
in vec3 Color;
out vec4 FragColor;
void main() {
FragColor = vec4(Color, 1.0);
}
当然,vertexshader真正的数据还需要我们从OpenGL程序里传入。这就有了两种向Shader传递顶点属性的方法。
在这之前,我们首先要创建一个VAO,vertex array object,顶点数组对象。主要想要仔细了解这个是干嘛的,还请自行查阅资料,还是很多滴。这里,我们只要知道,它包含了我们的缓冲区和输入的顶点属性之间的对应关系就可以了。在一个OpenGL程序里,我们可以使用多个VAO,并在它们之间切换。现在我们只使用一个。
GLuint VertexArrayID;
glGenVertexArrays(1,&VertexArrayID);
glBindVertexArray(VertexArrayID);
最后一句话表明,接下来我们所做的所有绑定操作,例如建立顶点属性和输入之间的对应关系,都是针对这个VAO的。
下面我们需要为要传输的数据生成对应的缓冲区。这些缓冲区随后会在绘制函数中,通过顶点属性索引传递给我们的shader。
因为在本例中,我们有两个属性值,因此需要建立两个缓冲区。
首先定义缓冲区的数据,也就是我们的顶点信息。我们现在需要画一个三角形,因此只需要三个点。
// An array of 3vectors which represents 3 vertices
float positionData[]= {
-0.8f, -0.8f, 0.0f,
0.8f, -0.8f, 0.0f,
0.0f, 0.8f, 0.0f };
然后创建一个缓冲区,并用上面的数据为其填充。
// This will identifyour vertex buffer
GLuint vertexbuffer;
// Generate 1 buffer,put the resulting identifier in vertexbuffer
glGenBuffers(1, &vertexbuffer);
// The followingcommands will talk about our 'vertexbuffer' buffer
glBindBuffer(GL_ARRAY_BUFFER,vertexbuffer);
// Give our verticesto OpenGL.
glBufferData(GL_ARRAY_BUFFER,sizeof(positionData), positionData, GL_STATIC_DRAW);
这样就完成的第一个顶点属性,VertexPosition数据的前期准备工作。VertexColor的数据是类似的。
float colorData[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f };
// This will identifyour vertex buffer
GLuint colorbuffer;
// Generate 1 buffer,put the resulting identifier in vertexbuffer
glGenBuffers(1,&a