1. iOS操作系统不会不会让应用向前帧缓存和后帧缓存绘图,也不会让应用直接控制前帧缓存和后帧缓存之间的切换。操作系统为自己保留了这些操作,以便它可以随时使用Core Animation合成器来控制显示的最终外观。
2.Core Animation 合成器使用OpenGLES来尽可能高效地控制GPU、混合层和切换帧缓存。图形程序员经常使用术语混合(composite)来描述混合图像以形成一个合成结果的过程。所有显示的动画都是通过Core Animation合成器来完成的,因此最终都设计OpenGLES。
3.帧缓存会保存OpenGLES的渲染结果,因此为了渲染到一个Core Animation层上,程序需要一个连接到某个层的帧缓存。简言之,每个程序用足够的内存配置一个层来保存像素颜色数据,之后创建一个使用层的内存来保存渲染的图像的帧缓存。
以上内容为阅读OpenGLES 应用开发实践指南iOS卷第二章起始部分的总结。
渲染各个步骤函数解释:
VBO:vertex buffer object
1.
GLuintvertexBufferID;
//step1
glGenBuffers(1, &vertexBufferID);
voidglGenBuffers(GLsizei n, GLuint* buffers)
为缓存生成一个标识符,第一个参数为要生成的标识符的数量,第二个参数为一个指针指向要存储标识符的地址。
2.
//step2
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
voidglBindBuffer(GLenum target, GLuint buffer)
绑定用于指定标识符的缓存到当前缓存。OpenGLES 保存不同类型的缓存标识符到当前上下文的不同部位。但是在任意时刻每种类型都只能绑定一个缓存。
第一个参数是常量,用于指定哪一种类型的缓存。openGLES2.0在这个函数中只支持两种:GL_ARRAY_BUFFER和GL_ELEMENT_ARRAY_BUFFER。第二个参数是要绑定的缓存的标识符。
3.
//step3
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
voidglBufferData(GLenum target,GLsizeiptr size,constGLvoid* data, GLenum usage);
第一个参数target可以为GL_ARRAY_BUFFER或GL_ELEMENT_ARRAY。第二个参数size为待传递数据字节数量。第三个参数为源数据数组指针,如data为NULL,则VBO仅仅预留给定数据大小的内存空间。最后一个参数usage标志位VBO的另一个性能提示,它提供缓存对象将如何使用:static、dynamic或stream、与read、copy或draw。
VBO为usage标志指定9个枚举值:
(1)GL_STATIC_DRAW
(2)GL_STATIC_READ
(3)GL_STATIC_COPY
(4)GL_DYNAMIC_DRAW
(5)GL_DYNAMIC_READ
(6)GL_DYNAMIC_COPY
(7)GL_STREAM_DRAW
(8)GL_STREAM_READ
(9)GL_STREAM_COPY
”static“表示VBO中的数据将不会被改动(一次指定多次使用),”dynamic“表示数据将会被频繁改动(反复指定与使用),”stream“表示每帧数据都要改变(一次指定一次使用)。”draw“表示数据将被发送到GPU以待绘制(应用程序到GL),”read“表示数据将被客户端程序读取(GL到应用程序),”copy“表示数据可用于绘制与读取(GL到GL)。
注意,仅仅draw标志对VBO有用,copy与read标志对顶点/帧缓存对象(PBO或FBO)更有意义,如GL_STATIC_DRAW与GL_STREAM_DRAW使用显卡内存,GL_DYNAMIC使用AGP内存。_READ_相关缓存更适合在系统内存或AGP内存,因为这样数据更易访问。
4.
//step4
glEnableVertexAttribArray(GLKVertexAttribPosition);
void glEnableVertexAttribArray (GLuint index);
启动顶点缓存渲染操作。OpenGLES所支持的每一个渲染操作都可以单独地使用保存在当前OpenGLES的上下文中的设置来开启和关闭。
默认情况下,出于性能考虑,所有顶点着色器的属性(Attribute)变量都是关闭的,意味着数据在着色器端是不可见的,哪怕数据已经上传到GPU,由glEnableVertexAttribArray启用指定属性,才可在顶点着色器中访问逐顶点的属性数据。glVertexAttribPointer或VBO只是建立CPU和GPU之间的逻辑连接,从而实现了CPU数据上传至GPU。但是,数据在GPU端是否可见,即,着色器能否读取到数据,由是否启用了对应的属性决定,这就是glEnableVertexAttribArray的功能,允许顶点着色器读取GPU(服务器端)数据。
那么,glEnableVertexAttribArray应该在glVertexAttribPointer之前还是之后调用?答案是都可以,只要在绘图调用(glDraw*系列函数)前调用即可。
5.
//step5
glVertexAttribPointer(GLKVertexAttribPosition,3,GL_FLOAT,GL_FALSE,sizeof(SceneVertex),NULL);
void glVertexAttribPointer (GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const GLvoid* ptr);
告诉OpenGLES在接下来的渲染中是否使用缓存中的数据。
参数:
index
指示当前绑定的缓存包含每个顶点的位置信息。
size
指定每个顶点属性的组件数量。必须为1、2、3或者4。初始值为4。(如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))
type
指定数组中每个组件的数据类型。可用的符号常量有GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT。
normalized
告诉OpenGLES小数点固定数据是否可以被改变。
指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE)。
stride
指定每个顶点的保存需要多少字节。换句话,步幅指定了GPU从一个顶点的内存开始位置转移到下一个顶点的内存开始位置需要跳过多少字节。
指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。
pointer
指定第一个组件在数组的第一个顶点属性中的偏移量。该数组与GL_ARRAY_BUFFER绑定,储存于缓冲区中。初始值为0;
6.
//step6
glDrawArrays(GL_TRIANGLES,0,3);
void glDrawArrays (GLenum mode,GLint first,GLsizei count);
第一个参数会告诉GPU怎么处理在绑定的顶点缓存内的顶点数据。第二个参数指定缓存内需要渲染的第一个顶点的位置。第三个参数指定需要渲染的缓存数量。
告诉OpenGLES使用当前绑定并启用的缓存中的数据渲染整个场景或某个场景的一部分。
参数说明:
mode,绘制方式,OpenGL2.0以后提供以下参数:GL_POINTS、GL_LINES、GL_LINE_LOOP、GL_LINE_STRIP、GL_TRIANGLES、GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN。
first,从数组缓存中的哪一位开始绘制,一般为0。
count,数组中顶点的数量。
其他函数解释:
glClearColor(0.0f,0.0f,0.0f,1.0f);
void glClearColor (GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha);
清除颜色缓冲区的,并且都被归一化在(0,1)之间的值,其实就是清空当前的所有颜色。设置当前上下文颜色(清除颜色)。