GLKit简介
GLKit 框架的设计目标是为了简化基于OpenGL / OpenGL ES 的应用开发 。它的出现加快了OpenGL ES或OpenGL应用程序开发。 使用数学库,背景纹理加载,预先创建的着⾊器效果,以及标准视图和视图控制器来实现渲染循环。
GLKit框架提供了功能和类,可以减少创建新的基于着⾊器的应⽤程序所需的工作量, 或者支持依赖早期版本的OpenGL ES或OpenGL提供的固定函数顶点或片段处理的现有应用程序。
总的来说,GLKit就是用更友好的语法便于开发者开发基于OpenGL / OpenGL ES 的应用。
EGL & EAGL 简介
OpenGL ES 命令需要渲染上下文和绘制表面才能完成图形图像的绘制,由于OpenGL ES API 没有提供创建渲染上下文或者上下文连接到原生窗口系统,于是就有了EGL。EGL是Khronos 渲染API(如OpenGL ES) 和原⽣窗口系统之间的接口。
iOS支持OpenGL ES但却不⽀持EGL。Apple 为iOS提供⾃己的EGL API,称为EAGL。
EGL的主要功能如下:
- 和本地窗⼝系统(native windowing system)通讯;
- 查询可⽤的配置;
- 创建OpenGL ES可⽤用的“绘图表面”(drawing surface);
- 同步不同类别的API之间的渲染,⽐如在OpenGL ES和OpenVG之间同步,或者在OpenGL和本地窗口的绘图命令之间;
- 管理“渲染资源”,⽐如纹理映射(rendering map)。
说明
这次要做的东西,效果看起来很简单,就只是加载一张图片到屏幕上。当然,如果用UIImageView来加载,那就没有写这篇文章的必要的。这次是用GLKit加载图片。
GLKit加载图片.png初始化
1. 创建viewController,继承UIViewController
2. import
#import <GLKit/GLKit.h>
#import <OpenGLES/ES3/gl.h>
#import <OpenGLES/ES3/glext.h>
3. 变量声明
这里声明属性也是可以的。
@interface GLKitViewController ()<GLKViewDelegate>
{
//绘制视图内容时使⽤用的OpenGL ES 上下⽂文
EAGLContext *context;
//⼀种简单光照/着⾊系统,⽤于基于着⾊器OpenGL 渲染
GLKBaseEffect *effect;
}
@end
4. 创建EAGLContext并设置当前的context
context = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES3];
if (!context) {
return;
}
[EAGLContext setCurrentContext:context];
5. 创建GLKView 并且initWithContext并且遵循GLKViewDelegate
GLKView *view = [[GLKView alloc]initWithFrame:self.view.bounds context:context];
view.delegate = self;
self.view = view;
6. 设置背景颜色
一般情况,我们为一个View设置背景颜色都是直接view.backgroundColor
,
但是对于GLKView并不管用,正确的使用方式是我们在前几篇文章中经常用到的一个方法glClearColor(r,g,b,a)
glClearColor(0.8, 0.8, 0.8, 1);
设置顶点数据
1.顶点数组
开发者可以选择设定函数指针,在调用绘制方法的时候,直接由内存传入顶点数据,也就是说这部分数据之前是存储在内存当中的,被称为顶点数组。
每一行的前三个数据代表一个顶点坐标(x,y,z)。
后两个数据代表纹理坐标。
纹理坐标系取值范围为[0,1],原点是左下角(0,0);
故而(0,0)是纹理图像的左下角, 点(1,1)是右上角。
这次要绘制的图形是一个方形,一个方形由两个三角形组成,两个三角形则有6个顶点组成。
GLfloat vertexData[] = {
0.5, -0.25, 0.0f, 1.0f, 0.0f, //右下
0.5, 0.25, -0.0f, 1.0f, 1.0f, //右上
-0.5, 0.25, 0.0f, 0.0f, 1.0f, //左上
0.5, -0.25, 0.0f, 1.0f, 0.0f, //右下
-0.5, 0.25, 0.0f, 0.0f, 1.0f, //左上
-0.5, -0.25, 0.0f, 0.0f, 0.0f, //左下
};
2.开辟顶点缓冲区
//(1).创建顶点缓冲区标识符
GLuint bufferID;
glGenBuffers(1, &bufferID);
//(2).绑定顶点缓冲区
glBindBuffer(GL_ARRAY_BUFFER, bufferID);
//(3).将顶点数组的数据copy到顶点缓冲区中
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
3.读取顶点数据、纹理数据
glEnableVertexAttribArray(GLuint index)
在iOS中, 默认情况下,出于性能考虑,所有顶点着色器的属性(Attribute)变量都是关闭的。
意味着我们使用glBufferData方法,将顶点数据从内存拷贝到顶点缓冲区中,顶点数据在着色器中是不可用的。
所以, 必须由glEnableVertexAttribArray 方法打开通道。指定访问属性.才能让顶点着色器能够访问到从CPU复制到GPU的数据。
glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid ptr)
这个方法百度百科有介绍,可以点这里看看
-
功能:
上传顶点数据到显存的方法(设置合适的方式从buffer里面读取数据) -
参数说明:
- index:指定要修改的顶点属性的索引值,这里与
glEnableVertexAttribArray
中的参数保持一致即可。 - size:每次读取数量。如position是由3个(x,y,z)组成,而颜色是4个(r,g,b,a),纹理则是2个
- type:指定数组中每个组件的数据类型。可用的符号常量有
GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED,GL_FLOAT
,初始值为GL_FLOAT
- normalized:指定当被访问时,固定点数据值是否应该被归一化(GL_TRUE)或者直接转换为固定点值(GL_FALSE),一般直接用GL_FALSE
- stride :指定连续顶点属性之间的偏移量。可以理解为从第一个x坐标到第二个x坐标要跨越几个参数,例如在本案例中,就需要跨越5个参数。
- ptr:指定一个指针,指向数组中第一个顶点属性的第一个组件。可以这么理解,我们当前读取的是顶点坐标,那么顶点坐标从第一个就开始了,就是0,如果要读取的是纹理坐标,那么就是3
- index:指定要修改的顶点属性的索引值,这里与
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE,sizeof(GLfloat)* 5,(GLfloat *)NULL + 0);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)* 5, (GLfloat *)NULL + 3);
tips:参数务必老老实实照着写,要不然就会不出效果...
读取并设置纹理
相关属性
1.获取纹理(图片)路径
NSString *path = [[NSBundle mainBundle]pathForResource:@"test" ofType:@"png"];
2.设置纹理属性
纹理坐标原点是左下角,但是图片显示原点应该是左上角。
NSDictionary *option = @{GLKTextureLoaderOriginBottomLeft:@(YES)};
3.通过GLKTextureLoader加载GLKTextureInfo
GLKTextureInfo : OpenGL 纹理信息
- name : OpenGL 上下文中纹理名称
- target : 纹理绑定的⽬目标
- height : 加载的纹理高度
- width : 加载纹理的宽度
- textureOrigin : 加载纹理中的原点位置
- alphaState: 加载纹理中alpha分量状态
- containsMipmaps: 布尔值,加载的纹理是否包含mip贴图
GLTextureLoader :从各种资源文件中加载纹理(相对于OpenGL加载方便了非常多)
//从⽂件加载2D纹理图像并从数据中创建新的纹理
GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:path options:dic error:nil];
4.使用GLKit 提供GLKBaseEffect 完成着色器工作(顶点/片元)
effect = [[GLKBaseEffect alloc]init];
effect.texture2d0.enabled = GL_TRUE;
effect.texture2d0.name = textureInfo.name;
GLKViewDelegate
绘制视图的内容
GLKView对象使其OpenGL ES上下文成为当前上下文,并将其framebuffer绑定为OpenGL ES呈现命令的目标。然后,委托方法应该绘制视图的内容。
glDrawArrays(GLenum mode, GLint first, GLsizei count)
参数说明
- mode:绘制方式,OpenGL2.0以后提供以下参数:
GL_POINTS、GL_LINES、GL_LINE_LOOP、GL_LINE_STRIP、GL_TRIANGLES、GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN
- first:从数组缓冲中的哪一位开始绘制,一般为0。
- count:数组中顶点的数量。
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
//清除缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//准备绘制
[effect prepareToDraw];
//绘制
glDrawArrays(GL_TRIANGLES, 0, 6);
}
以上,便是用GLKit加载图片的全部流程。
网友评论