[TOC]
2. Declaring Vertex Attribute Variables in a Vertex Shader
- 顶点属性变量的声明在前文第五章的“输入输出变量”一节已经介绍过,使用in限定符声明变量,同时可选使用layout限定符来声明顶点属性的索引位置,例如:
layout (location = 0) in vec4 a_position;
layout (location = 1) in vec2 a_texcoord;
layout (location = 2) in vec3 a_normal;
-
注意,顶点属性变量不能声明为数组或结构体。in 只能用于数据类型 float, vec2, vec3, vec4, int, ivec2, ivec3, ivec4, uint, uvec2, uvec3, uvec4, mat2, mat2x2, mat2x3, mat2x4, mat3, mat3x3, mat3x4, mat4, mat4x2, and mat4x3.
-
OpenGL ES 3.0 支持 GL_MAX_VERTEX_ATTRIBS 个4分量向量顶点属性,而声明为标量、2分量向量 或 3分量向量 的顶点属性也会被当做1个4分量向量,声明为二维 、 三维 或 四维矩阵的顶点属性会被分别当做2个、3个 或 4个 4分量向量。不像 Uniform和 ***vertex shader output/fragment shader input variables ***可以被编译器自动打包,顶点属性不会被打包。所以声明顶点属性时尽可能充分的利用起来。
-
顶点变量是只读的,不能被修改。并且如果这个变量没有被使用,则被认为是非活动的,不会被统计。
-
查询一个程序的活动的顶点属性数量的方法:
glGetProgramiv (program, GL_ACTIVE_ATTRIBUTES, &numActiveAttribs);
- 通过index查询顶点属性:
void glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei * length, GLint * size, GLenum * type, GLchar * name)
- program : 要查询的program对象
- index : 要查询的顶点属性索引,范围是从0到GL_ACTIVE_ATTRIBUTES
- bufsize : 变量名字的最大字符数量,包括null终止符(按照字面意思理解,也就是要分配的缓冲区大小)
- length : 如果这个值不是NULL,会被写入变量名字的字符数(不包括终止字符)
- type : 被写入该uniform的类型,可取值为
GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4,
GL_FLOAT_MAT2, GL_FLOAT_MAT3, GL_FLOAT_MAT4,
GL_FLOAT_MAT2x3, GL_FLOAT_MAT2x4,
GL_FLOAT_MAT3x2, GL_FLOAT_MAT3x4,
GL_FLOAT_MAT4x2, GL_FLOAT_MAT4x3,
GL_INT, GL_INT_VEC2, GL_INT_VEC3, GL_INT_VEC4,
GL_UNSIGNED_INT, GL_UNSIGNED_INT_VEC2, GL_UNSIGNED_INT_VEC3, GL_UNSIGNED_INT_VEC4,- size : 返回顶点属性的size,由type返回的类型决定。如果变量不是一个数组,size值总是1;如果变量是一个数组,size就是数组的大小。(个人理解,如果type的类型是矩阵的话,由于矩阵实际上是向量的数组,所以这里需要知道数组的大小)
- name : 顶点属性变量的名字
Binding Vertex Attributes to Attribute Variables In a Vertex Shader
前面我们已经介绍了如何声明顶点属性、为顶点属性赋值,也介绍了如何声明属性变量及查询属性信息,现在我们来介绍属性索引是如何映射到属性变量的。先来看一个图:
在OpenGL ES 3.0中,有三种方法可以将一个顶点属性索引映射到一个属性变量上:
- 在声明属性变量时通过layout (location = N)直接指定(推荐)
- OpenGL ES 3.0会将属性索引绑定到属性变量上
- 应用程序可以会将属性索引绑定到属性变量上
通过layout (location = N)直接指定是最简单的方法,同时也可以使用glBindAttribLocation命令来绑定,这种绑定只有当program对象下一次被链接时才会生效 :
void glBindAttribLocation (GLuint program, GLuint index, const GLchar * name)
- program : 程序对象
- index : 顶点属性索引
- name : 属性变量名字
如果属性变量已经被绑定了,那么它所绑定的顶点索引会被替换为新的索引。glBindAttribLocation甚至可以在顶点shader附着到program对象之前使用。不存在的变量或者非活跃的变量会被忽略。
另一种选择是在program对象进行链接时,由OpenGL ES来进行绑定:对于每一个属性变量,OpenGL ES会检查该变量是否已经进行了绑定,如果没有,就自动为该变量分配一个属性索引。这种分配是特定于实现的,一个实现和另一个实现可能会有差别,可以通过下面方法来查询属性变量的索引:
GLint glGetAttribLocation (GLuint program, const GLchar * name)
- program : program对象
- name : 属性名字
- 如果属性名字不存在,或者program对象发生错误,该方法会返回-1,表示无效的索引
网友评论