opengl只负责图片渲染过程,不负责窗口管理及上下文环境管理,因此要自己为OpenGL搭建上下文环境来管理窗口
在opengl渲染的过程中,各个硬件的用途
内存:有一个包含所有图片像素点数据的数组
显卡 : 像素点组成了帧缓冲区的形式 (帧缓冲区需要关联到渲染缓冲区)通过glFramebufferRenderbuffer
进行关联
窗口: 用户看到的画面(内容来自于显卡),通过renderbufferStorage
方法将渲染缓冲区和layer关联起来
上下文环境: 包含CAEAGLLayer和渲染缓冲区,帧缓冲区
渲染图片实际是将图片数据加载到纹理对象中
- 首先要有帧缓冲区(FrameBuffer)和渲染缓冲区(renderbuffer)
(在显卡中,像素点组成了帧缓冲区的形式),搭建上下文环境,问openGl提供展示的环境
帧缓冲区(FrameBuffer):
用来保存数据,控制屏幕上所有像素的颜色和强度所需要的全部信息
创建方式
void glGenFramebuffers (GLsizei n, GLuint* framebuffers)
//创建帧缓冲区 _displayFramebuffer可以看做被赋值了的缓冲区标识
glGenFramebuffers(1, &_displayFramebuffer);
//创建帧缓冲区
glGenRenderbuffers(1, &_renderbuffer);
2.将缓冲区和渲染区数据绑定到缓冲区和渲染区域
允许您创建或使用命名的帧缓冲对象。 调用glBindFramebuffer并将目标设置为GL_FRAMEBUFFER,将framebuffer设置为新的绑定了帧缓冲区对象名称的帧缓冲区对象。 绑定帧缓冲区对象时,先前的绑定会自动中断。帧缓冲区对象名称是无符号整数。 保留值零以表示由窗口系统提供的默认帧缓冲区。 帧缓冲区对象名称和相应的framebuffer对象内容对于当前GL渲染上下文的共享对象空间是本地的。
void glBindFramebuffer (GLenum target, GLuint framebuffer)
glBindFramebuffer(GL_FRAMEBUFFER, _displayFramebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer);
给渲染区域分配存储空间,
为了创建一个可以呈现给屏幕的renderbuffer,您可以绑定renderbuffer,然后通过调用此方法为其分配共享存储空间。此方法调用是为了替换正常情况下的glRenderbufferStorage方法(对于非iOS平台的其他平台)。其存储已分配了此方法的renderbuffer可以随后通过调用glRenderbufferStorage函数来显示数据。
- (BOOL)renderbufferStorage:(NSUInteger)target fromDrawable:(nullable id<EAGLDrawable>)drawable
当使用renderbufferStorage给渲染缓冲区设置drawable后,就可以通过glGetRenderbufferParameteriv
获取渲染缓冲区的宽高了
[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];
当渲染区域分配存储空间完成后,可以通过glGetRenderbufferParameteriv
获取绘制缓冲区宽高,实际跟上面设置的layer
的宽高一致
//“获取绘制缓冲区的像素宽度”
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_backingWidth);
//“获取绘制缓冲区的像素宽高度
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight);
//绘制缓冲区绑定到帧缓冲区
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _renderbuffer);
OpenGL编译着色器程序,编译着色器程序之后就可以通过glGetAttribLocation
和glGetUniformLocation
方法获取着色器程序里面的变量,进行赋值操作
着色器程序是opengl es渲染到页面的方式,“Vertex Shader(顶点着色器)用来替换顶点处理阶段。”
Fragment Shader(片元着色器,又称像素着色器)用来替换片元处理阶段
创建显卡执行程序
GLuint glCreateProgram(void);
创建着色器程序
GLuint glCreateShader (GLenum type)
未创建的shader添加源代码
void glShaderSource (GLuint shader, GLsizei count, const GLchar* const *string, const GLint* length)
编译着色器程序
void glCompileShader (GLuint shader)
将着色器程序附着到显卡执行程序中
void glAttachShader (GLuint program, GLuint shader)
链接程序
void glLinkProgram (GLuint program)
用于name指定的属性变量,并返回绑定到该属性变量的通用顶点属性的索引,在调用glLinkProgram
之前,属性绑定不会生效。 成功链接程序对象后,属性变量的索引值将保持固定,直到发生下一个链接命令。 如果链接成功,则只能在链接后查询属性值。 glGetAttribLocation返回上次为指定程序对象调用glLinkProgram时实际生效的绑定。 glGetAttribLocation不返回自上次链接操作以来指定的属性绑定
int glGetAttribLocation (GLuint program, const GLchar* name)
获取着色器程序中,指定为uniform类型变量的id
int glGetUniformLocation (GLuint program, const GLchar* name)
操作纹理对象(通过对纹理进行一些设置,可以添加一些现实效果,比如锯齿状,增加对比度等)
产生n个纹理id存储到textures中, 纹理可以用来表示图像、照片、视频画面等数据
void glGenTextures (GLsizei n, GLuint* textures)
glBindTexture
改变了OpenGL的这个状态,它告诉OpenGL下面对纹理的任何操作都是对它所绑定的纹理对象的,比如glBindTexture(GL_TEXTURE_2D,1)告诉OpenGL下面代码中对2D纹理的任何设置都是针对索引为texture
的纹理的。
void glBindTexture (GLenum target, GLuint texture)
设置纹理过滤方式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//将该纹理的s轴和t轴的坐标设置为GL_CLAMP_TO_EDGE类型
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
渲染
使用shader程序
void glUseProgram (GLuint program)
设置清除颜色
void glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
根据清除颜色设置窗口颜色,和glClearColor组合使用
void glClear (GLbitfield mask)
用于启用各种功能。功能由参数决定。与glDisable相对应。glDisable是用来关闭的。两个函数参数取值是一至的。
void glEnable (GLenum cap)
glEnable(GL_BLEND);//启用色彩混合
颜色混合模式 https://www.jianshu.com/p/b1544b0fc72c
void glBlendFunc (GLenum sfactor, GLenum dfactor)
指定对索引为_inputTexture的纹理进行操作
glBindTexture(GL_TEXTURE_2D, _inputTexture);
将png素材内容放置到显卡中去
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)frameWidth, (GLsizei)frameHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaFrame);
glVertexAttribPointer
给顶点着色器设置数据
static const GLfloat imageVertices[] = { //物体坐标
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
};
GLfloat noRotationTextureCoordinates[] = { //纹理坐标
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
/**
第一个参数index 指定从索引index开始取数据。
第二个参数指定顶点属性大小。 指定每个顶点属性的组件数量(由于是2D,因此position只需要2个) (如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a))
第三个参数指定数据类型。 GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, 和 GL_FLOAT,初始值为GL_FLOAT
第四个参数定义是否希望数据被标准化(归一化),只表示方向不表示大小。
第五个参数是步长(Stride)指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0。
第六个 指定第一个组件在数组的第一个顶点属性中的偏移量。该数组与GL_ARRAY_BUFFER绑定,储存于缓冲区中。初始值为0
*/
//指定了渲染时索引值为 index 的顶点属性数组的数据格式和位置。
glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, 0, 0, imageVertices);
glEnableVertexAttribArray(filterPositionAttribute);
glVertexAttribPointer(filterTextureCoordinateAttribute, 2, GL_FLOAT, 0, 0, noRotationTextureCoordinates);
glEnableVertexAttribArray(filterTextureCoordinateAttribute);
//指定激活哪一个纹理句柄 (句柄可以理解为一个对象或者系统的唯一标识)
glActiveTexture(GL_TEXTURE0);
设置渲染方式
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
在渲染准备工作都准备就绪后,就可以使用presentRenderbuffer
进行
图片渲染,将渲染区的图片绘制到layer上
[_context presentRenderbuffer:GL_RENDERBUFFER];
网友评论