一个属性能够声明在一个顶点着色器,但若是它不使用,那么它是不被激活的。你能使用glGetActiveAttrib查询一个被激活的属性内容。GL_ACTIVE_ATTRIBUTESgit
void glGetActiveAttrib( GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
bufsize是那些能被写为属性名的字符的最大数目,包括空('\0')。length是返回的名字长度,type是数据的类型GL_FLOAT等。size是返回的属性大小,是返回type的单位大小,若是是数组就是数组的尺寸,不是数组就是1。name是着色器声明的属性变量的名字。github
顶点着色器中使用glBindAttribLocation绑定一个普通的顶点属性索引到属性变量,这个绑定在项目下次连接时有效,在当前连接的项目里不会改变。若是一个名字前面被绑定过,它分配的绑定被一个索引取代。glBindAttribLocation甚至能在顶点着色器被链接到一个项目对象前使用。这意味着这个调用能被使用去绑定任何属性名字。属性名字不存在或者没激活的绑定在项目里被忽略。segmentfault
void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name)
另外一种选择是让GLES绑定属性变量名到一个普通的属性索引。在连接阶段GLES2为每一个属性变量执行下面的步骤:检查每一个属性变量是否已经过glBindAttribLocation绑定。若是已绑定,指定的属性索引将被使用;若是没有,编译工具将产生一个通常的顶点属性索引。而这个分配依赖工具的不一样而不一样,咱们可使用glGetAttribLocation去获取这个分配的值。api
GLint glGetAttribLocation(GLuint program, const GLchar *name)
指定顶点属性常量数组
void glVertexAttrib1f(GLuint index, GLfloat x); void glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y); void glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z); void glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); void glVertexAttrib1fv(GLuint index, const GLfloat *values); void glVertexAttrib2fv(GLuint index, const GLfloat *values); void glVertexAttrib3fv(GLuint index, const GLfloat *values); void glVertexAttrib4fv(GLuint index, const GLfloat *values);
index是要装载的顶点属性索引,x y z values是要填充的值。glVertexAttrib?f和glVertexAttrib?fv都是装载一个vec4的值。介绍Shader语言时说过它们都会存储为具备4个份量的存储单元。填充时最后一个会为1.0,中间不足的为0.0。如glVertexAttrib1fv填充1,那么index最终的值为{x,0.0,0.0,1.0}。注意到GLES2只支持了浮点型的设置属性常量api。less
顶点数组ide
void glVertexAttribPointer( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *ptr)
要装在数组到顶点属性,使用glVertexAttribPointer,index是顶点属性的索引,size是数组里组成元素的大小(例如只是指定二维的位置那么只须要x,y那么赋值为2),type是数据格式,normalized用于指定非浮点数据格式转变成浮点型数据时是否标准化,strides是顶点属性数据的存储间隔,0表示无间隔,连续存储的。ptr就是咱们要放进去的数据了。正如第二节例子里的:工具
// _vPositionHandle的值就来自于glGetAttribLocation获取获得的索引 glVertexAttribPointer(_vPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
出了加载数据,咱们还要为属性启用属性数组。oop
// 启用 void glEnableVertexAttribArray(GLuint index); // 不启用 void glDisableVertexAttribArray(GLuint index); // index就是前面的属性索引值
接着之前的项目,这里咱们主要修改Director里的内容:代码看里面的lesson5的tagui
想声明着色器和全局数据
// 顶点着色器,声明俩个着色器属性,分别放位置和颜色,易变变量做为输出将传给片断着色器 static const char gVertexShader[] = "attribute vec4 a_position;\n" "attribute vec4 a_color;\n" "varying vec4 v_color;\n" "void main()\n" "{\n" " v_color = a_color;\n" " gl_Position = a_position;\n" "}\n"; // 片断着色器,接收颜v_color传来的颜色 static const char gFragmentShader[] = "varying vec4 v_color;\n" "void main()\n" "{\n" " gl_FragColor = v_color;\n" "}\n"; // 和之前的同样的三角形数据 const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f }; // 接下来用给a_color的 const GLfloat gColor[4] = { 1.0f, 1.0f, 0.0f, 1.0f };
在mainloop循环中修改
void Director::mainLoop() { static float grey; grey += 0.01f; if (grey > 1.0f) { grey = 0.0f; } glClearColor(grey, grey, grey, 1.0f); glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glVertexAttrib4fv(0, gColor); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices); glEnableVertexAttribArray(1); glBindAttribLocation(_glProgram->getProgramHandle(), 0, "a_color"); glBindAttribLocation(_glProgram->getProgramHandle(), 1, "a_position"); glDrawArrays(GL_TRIANGLES, 0, 3); }
查看效果,能够看到咱们设置的黄色三角形: