OpenGL ES(绘制api)

把数据从CPU的内存传入GPU内存有两种
一种直接将CPU的数据赋值给GPU对应变量。另一种是CPU的数据打包,在GPU中创建一个buffer object,将打包数据传给buffer对象,GPU对这个buffer进行访问和使用。
通常使用第二种,更节省时间和空间。原因:1打包数据一次性传送,GPU只需要根据buffer对象的数据偏移,将buffer对象中的某块分配个某个变量,另外一快分配给另一个变量。2一套顶点颜色在被多次绘制时,会被GPU使用多次,第一种方式每次绘制都赋值一次。如果用buffer对象,只有buffer对象不被删除,GPU可一直使用。

void glGenBuffers(GLsizei n, GLuint * buffers);
void glBindBuffer(GLenum target, GLuint buffer);

第一个函数创建buffer object的name。生成第一个参数n个buffer对象的名字(无须连续的数字,是uint型,0被预留,因此一定是大于0的整数),保存在第二个参数。
第二个函数常见buffer object。第一个参数指定buffer object的类型(GL_ARRAY_BUFFER 或者 GL_ELEMENT_ARRAY_BUFFER,对应VBO vertex buffer对象和IBO index buffer 对象),
第二个参数为buffer object name。输入0为解绑当前VBO或IBO

关联之后指定某个buffer对象的name时相当于指定这个buffer对象,新创建的buffer对象是一个空间为0,初始态为默认值/GL_STATIC_DRAW的buffer。创建的buffer对象即为当前GPU使用的VBO或IBO,若再次传入相同buffer对象的name,只是把该buffer作为当前使用的VBO或IBO,之前的VBO和IBO不再使用。即GPU可存放大量的buffer对象,但同一时间一个线程的一个context只能使用一个buffer
当VBO与buffer object name不为0的buffer object绑定后,GPU中对shader的attribute的赋值将通过VBO,而非直接通过CPU内存的数据复制。

void glBufferData(GLenumtarget, GLsizeiptr size, const GLvoid * data, GLenum usage);

把CPU端保存的数据传递给GPU的指定buffer对象
第一个参数是指定buffer对象的类型(GL_ARRAY_BUFFER 或者 GL_ELEMENT_ARRAY_BUFFER)。第二个和第三个输入参数的意思是:data 是 CPU 中一块指向保存实际数据的内存,而 size 为 data 以机器单元为单位的大小,size 不能为负。如果data为null,依然会给buffer对象size大小的内存,但不进行初始化,即其中的值为undefine。第四个参数指buffer object 的 usage,即 buffer object 的数据存储方式。buffer对象的初始状态下为GL_STATIC_DRAW(程序暗示这个buffer对象只会被赋值一次,然后在GPU中可能多次调用),除此外,GL_DYNAMIC_DRAW(程序暗示这个 buffer object 可能会被赋值多次,且在 GPU 中可能会多次读取调用)GL_STREAM_DRAW(程序暗示这个 buffer object 只会被赋值一次, 然后在 GPU 中也只会被读取调用少量的几次)
usage不影响使用功能,无论哪个,buffer对象都可以被正常使用,只是暗示GPU选择更好的存储buffer的方式和位置,以优化buffer的读写效率。
如果在执行这个 API 之前 buffer object 中就存有数据,那么会先把之前的数据全部删掉,再把新的数据装入 buffer object 中

void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);

给buffer对象的一部分传入数据
第一个参数与glBufferData一样,二三四参数为:以buffer对象的开始为起点,进行offset个位置的偏移,从偏移位置开始长度为size个单位的空间用来储存data指向的CPU数据。offset和size单位都是机器单元。
更新buffer对象中的全部内容。优先使用offset为0,size为GL_BUFFER_SIZE,data指向新的数据的glBufferSubData,不会重新分配内存,使用glBufferData会涉及内存的重新分配

void glDeleteBuffers(GLsizei n, const GLuint * buffers);

删除n个buffer object。buffers为保存的buffer object变量名。
如果被删除的 buffer 正在处于 bind 状态,那么就相当于先执行了一次 glBindBuffer 把对应的 binding 变成 binging 0,也就相当于什么都没有 bind 了,然后再进行删除。

void glBindAttribLocation(GLuint program, GLuint index, const GLchar *name);

program:指定要在其中建立关联的程序对象的句柄。
index:指定要绑定的通用顶点属性的索引。可以为9,不能大于或者等于 GL_MAX_VERTEX_ATTRIBS 的值
name:指定一个以空终止符结尾的字符串,其中包含要绑定索引的顶点着色器属性变量的名称。即保存program对应的vertex shader中的一个attribute变量名。
matrix 可能需要不止一个 location,例mat4 就需要 4 个 location,而且是需要 4 个连续的 location,那么第二个参数 index 就是matrix第一列的location,index + 1就是matrix第二列自动绑定的location,index + 2 就是 matrix 第三列自动绑定的 location,index + 3 就是 matrix 第四列自动绑定的 location,如果没有 4 个连续的 location,linkprogram 也有可能会失败。
在调用glLinkProgram之前,属性绑定不会生效。成功链接程序对象后,通用属性的索引值保持固定(并且可以查询它们的值),直到发生下一个链接命令。
这个api会在下次link program生效,若link之前attribute自动分配的location为1,则在link前,OpenGL ES仍要用location1访问,知道program重新link后,才用这个api绑定的location访问。
该api可以在attachshader前执行。因为函数只关心第三个参数是否不为gl_前缀,不关心program对应shader是否存在。若attribute未active的话,linkprogram时忽略这次绑定。

void glGetActiveAttrib( GLuint program, GLuint index, GLsizei bufsize,GLsizei *length, GLint *size, GLenum *type, GLchar *name)

查询active的attribute

GLint glGetAttribLocation(GLuint program, const GLchar*name);

获取VS中某个attribute的位置,获取位置来对这个attribute进行其他操作。
第二个参数为attribute的变量名。
输出为location,若attribute是一个matrix,则返回第一列的location。错误返回-1(因为0也是合法的location)

void glEnableVertexAttribArray(GLuint index);

获取的attribute未enable的话,attribute值无法被访问。
输入为attribute的location
默认状态下所有自定义的attribute都是disable的,使用前一定要先enable

void glDisableVertexAttribArray (GLuint index);

绘制结束后,可以把没用的attribute进行disable。关闭后,在绘制时GPU就无法访问attribute对应值

void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer);

从OpenGL ES向VS传值。赋值后的attribute代表着若干个顶点的坐标或者颜色等其他信息。
第一个参数是attribute的location,第二个参数是在顶点数组中为该顶点属性所指定的分量数量,有效值为1-4。默认为4。(如果想要绘制一个三角形,则要传入三个单元,每个单元4个值,即通过api传入12个值)。第三个参数指定存储数据的type。GL_HALF_FLOAT、GL_FLOAT、GL_FIXED、GL_INT_2_10_10_10_REV、GL_UNSIGNED_INT_2_10_10_10_REV。默认是GL_FLOAT。第四个参数用来表示当非浮点值转为浮点值时是否进行规范化处理。带符号的值转为(-1,1),不带符号的转为(0,1)。true为需要归一化。第五个参数指定了两个相邻索引间数据的位移(每个顶点的由size指定的顶点属性的分量是顺序储存的。如画三角形,传入12个值,可创建12个值的数组传入,也可传入15个值的数组。其中5,10,15为无用值。则size为4,stride为5.GPU则会视5个值为一个单元进行读取,前四个为有效值,对attribute进行赋值)简单说就是从这个属性第二次出现的地方到整个数组0位置之间有多少字节(例,紧密排列的4float的size数组传0或者4 * sizeof(float))。第六个参数:若实际数据在CPU中,即使用的是顶点数组,则表示指向保存顶点数据的缓冲区的指针。若数据保存在GPU的VBO中,即顶点缓冲对象,则表示缓冲区内的偏移量,意思为从VBO的某一位开始,从之后的数据读取stride或size为一个单元,将size个数据作为有效数据。
即通过glBindBuffer当VBO与buffer name不为0的对象绑定后,GPU中对shader的赋值是通过VBO而非CPU
可通过glGet传入GL_ARRAY_BUFFER_BINDING 查询VBO邦德buffer对象的name,也可通过glGetVertexAttribiv 传入GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING查询。

void glVertexAttrib1f(    GLuint index,GLfloat v0);
void glVertexAttrib2f(    GLuint index,GLfloat v0, GLfloat v1);
void glVertexAttrib3f(    GLuint index,GLfloat v0,GLfloat v1,GLfloat v2);
void glVertexAttrib4f(    GLuint index,GLfloat v0,GLfloat v1,GLfloat v2,GLfloat v3);
void glVertexAttrib1fv(    GLuint index,const GLfloat *v);
void glVertexAttrib2fv(    GLuint index,const GLfloat *v);
void glVertexAttrib3fv(    GLuint index,const GLfloat *v);
void glVertexAttrib4fv(    GLuint index,const GLfloat *v);

2.0api
指定通用顶点属性的值(一个常量顶点属性对于一个图元的所有顶点都是相同的,所以只需指定一次值就可以了)
第一个参数为要修改的通用顶点属性的索引
v0、v1、v2、v3(如x,y,z,w)指定要用于顶点的新值
v指定要用于通用顶点属性的值数组的指针
如:glVertexAttrib1f和glVertexAttrib1fv会加载(x, 0.0, 0.0, 1.0),glVertexAttrib2f和glVertexAttrib2fv会加载(x, y, 0.0, 1.0)。未传入的值使用默认值
常量顶点属性提供了和uniform等价的功能(因为该函数设置的attribute变量值对每个点都是一样的,uniform即是如此)

GLint glGetUniformLocation(GLuint program, const GLchar *name);

获取uniform的location(glLinkProgram的时候,会给未指定的index的attribute分配location,也会把开发者自定义的active的uniform初始化为0并分配地址。)
若 compiler 和 linker 认为 unform 会被使用或者不确定是否会被使用,都会认为 uniform 是 active ,且一旦被load,program开始使用后除非再次relink,会一直保持

void glUniform1f(GLint location,  GLfloat v0); 
void glUniform2f(GLint location,  GLfloat v0,  GLfloat v1); 
void glUniform3f(GLint location,  GLfloat v0,  GLfloat v1,  GLfloat v2);
void glUniform4f(GLint location,  GLfloat v0,  GLfloat v1,  GLfloat v2,  GLfloat v3); 
void glUniform1i(GLint location,  GLint v0); 
void glUniform2i(GLint location,  GLint v0,  GLint v1); 
void glUniform3i(GLint location,  GLint v0,  GLint v1,  GLint v2); 
void glUniform4i(GLint location,  GLint v0,  GLint v1,  GLint v2,  GLint v3); 

为当前程序对象指定Uniform变量的值。主要用于float、int、vec类型的uniform,且不是array。

void glUniform1fv(GLint location,  GLsizei count,  const GLfloat *value); 
void glUniform2fv(GLint location,  GLsizei count,  const GLfloat *value); 
void glUniform3fv(GLint location,  GLsizei count,  const GLfloat *value); 
void glUniform4fv(GLint location,  GLsizei count,  const GLfloat *value); 
void glUniform1iv(GLint location,  GLsizei count,  const GLint *value);
void glUniform2iv(GLint location,  GLsizei count,  const GLint *value);
void glUniform3iv(GLint location,  GLsizei count,  const GLint *value);
void glUniform4iv(GLint location,  GLsizei count,  const GLint *value); 

第一个参数指明uniform变量的位置,
第二个参数指明要更改的元素个数,若uniform不为数组,则为1,否则大于等于1
第三个指定一个有count个值的数组指针,来更新uniform变量
主要用于给float、int、vec,和array的uniform赋值

void glUniformMatrix2fv(GLint location,  GLsizei count,  GLboolean transpose,  const GLfloat *value); 
void glUniformMatrix3fv(GLint location,  GLsizei count,  GLboolean transpose,  const GLfloat *value); 
void glUniformMatrix4fv(GLint location,  GLsizei count,  GLboolean transpose,  const GLfloat *value); 

count:要更改的矩阵个数
transpose:是否要转置矩阵,并作为uniform的值, 必须为 GL_FALSE(因为矩阵赋值是以列为单位赋值,第一列赋值完才第二列,使用别的参数会报错)
value:指向count个元素的指针

虽然 attribute 和 uniform 都支持 matrix 类型,但是通过 glVertexAttribPoint 或者 glVertexAttrib 给 attribute 传值的时候,一次虽然可以传递多个单元,但是每个单元最多只能传递 4 个 float,而 glUniform 可以直接传入一个 matrix 类型的值。

glUniform1i 和 glUniform1iv,分别用于给 sample 以及 sample 数组赋值,sample是特殊的uniform,相当于int类型的uniform

这些 uniform 会保持这些赋予的值,直到 program 再次被 link,因为再次 link 的时候,这些 uniform 值又会被初始化为 0。

void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);

设定绘制区域(EGL通过eglCreateWindowSurface创建的绘制buffer为屏幕分辨率的大小,实际绘制的时候不一定按这个大小绘制)
x,y表示绘制区域左下角在整个绘制buffer的位置,初始为(0,0)。后两个参数为绘制区域的宽高,出师未屏幕分辨率的尺寸
glVertexAttribPoint给shader传入表示顶点坐标的attribute值时,归一化的值是根据设定的绘制区域来换算的,例如传入的是中点位置,则实际为绘制区域的中点,而非整个屏幕分辨率的中点

void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);

设定清理绘制buffer的颜色(通过egl创建的绘制buffer,即内存,不会被初始化,可能有别的数据)

void glClear(GLbitfield mask);

使用预设值(glClearColor设定的颜色)清理绘制buffer
输入的mask值是指定绘制buffer哪块被清理(color buffer、depth buffer、stencil buffer)
传入GL_COLOR_BUFFER_BIT清理color buffer
glClearDepth:GL_DEPTH_BUFFER_BIT
glClearStencil:GL_STENCIL_BUFFER_BIT

void glColorMask(GLboolean red,	GLboolean green, GLboolean blue, GLboolean alpha);

控制color buffer RGBA通道的写入权限
PS结束后,Mask可以限制color,depth,stencil是否可写入对应buffer。
参数传入GL_TRUE可写,初始默认可写。

void glDrawArrays(GLenum mode, GLint first, GLsizei count);

使用传入的顶点信息,在绘制buffer中真正进行绘制。选择要进行绘制的顶点(被赋值过的attribute变量保存的信息),且如何进行图元装配
first和count:GPU保存的顶点中,从第first个顶点,到first+count个顶点结束,进行绘制。其他顶点会被忽略
mode:
GL_POINTS:把顶点绘制成一个个点
GL_LINE_STRIP:第一个点为第一条线起点,第二个点为第一条线终点和第二条起点,以此类推。
GL_LINE_LOOP:与GL_LINE_STRIP类似,但最后一个点会与第一个点相连
GL_LINES:1、2点相连,3、4点相连,若多余一个点忽略。GL_TRIANGLE_STRIP
OpenGL ES(绘制api)_第1张图片
GL_TRIANGLES:多余的一个或2个点忽略
GL_TRIANGLE_STRIP:从0开始,第3个之后的顶点分别与前两个点画三角。顺序:点为奇:n-1,n-2,n。点为偶n-2,n-1,n。即(0,1,2)(2,1,3)(2,3,4)。顺序不可变,为了保证所有三角形绘制方向相同 (图形学会通过这种顺时针还是逆时针来判断该图元为正面还是背面,之后会被用于剔除使用)
GL_TRIANGLE_FAN:从0开始,第3个点之后画三角。顺序:1,n-1,n。即(0,1,2)(0,2,3)(0,3,4)

绘制图片的其他信息如法向量等,如果为被赋值或为被设置enable,都会使用默认值参与绘制

void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices);

与glDrawArrays类似,选取绘制顶点的方式不同(glDrawArrays取的是连续的顶点)
count:绘制顶点个数
type:存放顶点index内存中,所使用的变量类型为type。必须为GL_UNSIGNED_BYTE或者GL_UNSIGNED_SHORT
indices:若实际数据在CPU中,即使用的是顶点数组,则表示指向保存顶点数据的缓冲区的指针。若数据保存在GPU的IBO中,即索引缓冲区,则表示缓冲区内的偏移量,意思为从IBO的某一位开始,从之后的数据读取count个数据作为有效数据。

VBO为顶点缓冲区对象,用于存储顶点坐标/顶点uv/顶点法线/顶点颜色,也可以用于其他用途,比如tangent
BO为索引缓冲区,里面的值可以是unsigned int或者unsigned short。
IBO和VBO原理类似,只不过IBO是缓存了VBO绘制时的Indices。

void glLineWidth(GLfloat width);

设置光栅化线段的粗细(若IglDrawArrays和glDrawElements设置的model为line,则光栅化出来的是线段)
输入默认为1,必须大于0。实际线宽为floor(width),若1.9为1.但若是0.8,floor为0,实际宽度仍是1.
(支持的线宽尺寸由硬件决定,可通过glGet传入GL_ALIASED_LINE_WIDTH_RANGE查询)

void glFrontFace(GLenum mode);
void glCullFace(GLenum mode);

剔除一些不绘制的三角(若IglDrawArrays和glDrawElements设置的model为三角。光栅化的三角也会受其他影响)

glFrontFace:设置三角形为front或者back。参数只能传GL_CCW(默认参数)或者GL_CW,通常前者逆时针为front,顺时针为back,后者相反
glCullFace:选择剔除三角形类型。参数只能传GL_FRONT, GL_BACK(默认), and GL_FRONT_AND_BACK(所有三角都被剔除,只绘制点和线)
剔除这个功能,则是通过glEnable和glDisable这两个API通过传入 GL_CULL_FACE 来开关,默认关闭剔除功能

你可能感兴趣的:(OpenGL,ES,学习笔记,opengles)