顶点属性声明
一个属性可以声明在一个顶点着色器,但如果它不使用,那么它是不被激活的。你能使用glGetActiveAttrib查询一个被激活的属性内容。GL_ACTIVE_ATTRIBUTES
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是着色器声明的属性变量的名字。
顶点着色器中使用glBindAttribLocation绑定一个普通的顶点属性索引到属性变量,这个绑定在项目下次链接时有效,在当前链接的项目里不会改变。如果一个名字前面被绑定过,它分配的绑定被一个索引取代。glBindAttribLocation甚至能在顶点着色器被连接到一个项目对象前使用。这意味着这个调用能被使用去绑定任何属性名字。属性名字不存在或者没激活的绑定在项目里被忽略。
void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name)
另一种选择是让GLES绑定属性变量名到一个普通的属性索引。在链接阶段GLES2为每个属性变量执行下面的步骤:检查每个属性变量是否已通过glBindAttribLocation绑定。如果已绑定,指定的属性索引将被使用;如果没有,编译工具将产生一个一般的顶点属性索引。而这个分配依赖工具的不同而不同,我们可以使用glGetAttribLocation去获取这个分配的值。
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。
顶点数组
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);
出了加载数据,我们还要为属性启用属性数组。
// 启用
void glEnableVertexAttribArray(GLuint index);
// 不启用
void glDisableVertexAttribArray(GLuint index);
// index就是前面的属性索引值
栗子
接着以前的项目,这里我们主要修改Director里的内容:代码看里面的lesson5的tag
想声明着色器和全局数据
// 顶点着色器,声明俩个着色器属性,分别放位置和颜色,易变变量作为输出将传给片段着色器
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);
}
查看效果,可以看到我们设置的黄色三角形:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。