一、什么是OpenGL ES
OpenGL ES
(OpenGL for Embedded Systems) 是 OpenGL三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。
在 OpenGL ES 苹果官方文档中有这样一段话:
The Open Graphics Library (OpenGL) is used for visualizing 2D and 3D data. It is a multipurpose open-
standard graphics library that supports applications for 2D and 3D digital content creation, mechanical
and architectural design, virtual prototyping, flight simulation, video games, and more. You use OpenGL to
configure a 3D graphics pipeline and submit data to it. Vertices are transformed and lit, assembled into
primitives, and rasterized to create a 2D image. OpenGL is designed to translate function calls into
graphics commands that can be sent to underlying graphics hardware. Because this underlying hardware is
dedicated to processing graphics commands, OpenGL drawing is typically very fast.
OpenGL for Embedded Systems (OpenGL ES) is a simplified version of OpenGL that eliminates redundant
functionality to provide a library that is both easier to learn and easier to implement in mobile graphics
hardware.
OpenGL ES
开放式图形库(OpenG
L的)⽤于可视化的⼆维和三维数据。它是一个多功能开放标准图形库,支持2D和3D数字内容创建,机械和建筑设计,虚拟原型设计,⻜行模拟,视频游戏等应⽤用程序。您可以使用OpenGL
配置3D图形管道并向其提交数据。顶点被变换和点亮,组合成图元,并光栅化以创建2D图像。OpenGL
旨在将函数调用转换为可以发送到底层图形硬件的图形命 令。由于此底层硬件专⽤于处理理图形命令,因此OpenGL
绘图通常⾮常快。
OpenGL for Embedded Systems(OpenGL ES)
是OpenGL
的简化版本,它消除了冗余功能,提供了一个既易于学习⼜更易于在移动图形硬件中实现的库。
二、OpenGL ES
使用过程
1.顶点着色器(vertex shader)
在OpenGL ES
中顶点着色器通常包含如下的函数/代码段:
- 着⾊器程序—描述顶点上执⾏行操作的顶点着⾊器程序源代码/可执行⽂件
2.顶点着⾊器输入(属性) — 用顶点数组提供每个顶点的数据
3.统⼀变量(
uniform
)—顶点/⽚元着⾊器使⽤的不变数据- 采样器—代表顶点着⾊器使⽤纹理的特殊统一变量类型.
顶点着色器的业务内容:
- 矩阵变换位置
- 2.计算光照公式⽣成逐顶点颜⾊
- 3.⽣成/变换纹理坐标
总结: 它可以⽤于执行⾃自定义计算,实施新的变换,照明或者传统的固定功能所不允许 的基于顶点的效果。
顶点着色器代码:
attribute vec4 position;
attribute vec2 textCoordinate; uniform mat4 rotateMatrix; varying lowp vec2 varyTextCoord; void main()
{
varyTextCoord = textCoordinate;
vec4 vPos = position;
vPos = vPos * rotateMatrix;
gl_Position = vPos;
}
2.图元装配
顶点着⾊器之后,下⼀个阶段就是图元装配.
图元(Primitive
): 点,线,三⻆角形等.
图元装配: 将顶点数据计算成⼀个个图元.在这个阶段会执⾏裁剪、透视分割和 Viewport
变换操作。
图元类型和顶点索确定将被渲染的单独图元。对于每个单独图元及其对应的顶点,图元装配阶段执行的操作包括:将顶点着⾊器的输出值执⾏裁剪、透视分割、视⼝变换后进⼊入光栅化阶段。
3.光栅化
在这个阶段绘制对应的图元(点/线/三角形). 光栅化就是将图元转化成⼀组二维片段 的过程.⽽这些转化的⽚段将由⽚元着⾊器处理.这些⼆维⽚段就是屏幕上可绘制的像素。
4.片源着色器(fragment shader)
在OpenGL ES
中片源着色器通常包含如下的函数/代码段:
- 着⾊器程序—描述⽚段上执行操作的⽚元着⾊器程序源代码/可执行⽂文件
2.输⼊变量— 光栅化单元⽤插值为每个⽚段⽣成的顶点着⾊器输出
3.统⼀变量(
uniform
)—顶点/⽚元着⾊器使⽤的不变数据- 采样器—代表⽚元着⾊器使⽤纹理的特殊统⼀变量类型。
片源着色器的业务内容:
- 1.计算颜色
- 获取纹理值
- 往像素点中填充颜⾊值(纹理值/颜色值);
总结: 它可以⽤于图片/视频/图形中每个像素的颜⾊填充(⽐如给视频添加滤镜,实际上就是将视频中每个图⽚的像素点颜⾊填充进行修改.)
片源着色器代码:
varying lowp vec2 varyTextCoord; uniform sampler2D colorMap;
void main() {
gl_FragColor = texture2D(colorMap, varyTextCoord);
}
5.逐片段操作:
- 像素归属测试: 确定帧缓存区中位置(Xw,Yw)的像素⽬前是不是归属于
OpenGL ES
所 有. 例如,如果一个显示OpenGL ES
帧缓存区View
被另外一个View
所遮蔽.则窗口系统可以确定被遮蔽的像素不属于OpenGL ES
上下文.从而不全显示这些像素.而像素归属测试是OpenGL ES
的⼀部分,它不由开发者开人为控制,⽽是由OpenGL ES
内部进⾏. - 裁剪测试: 裁剪测试确定(Xw,Yw)是否位于作为
OpenGL ES
状态的⼀部分裁剪矩形范围内.如果该⽚段位于裁剪区域之外,则被抛弃. - 深度测试: 输⼊片段的深度值进步⽐较,确定⽚段是否拒绝测试
- 混合: 混合将新生成的⽚段颜色与保存在帧缓存的位置的颜色值组合起来.
- 抖动: 抖动可⽤于最⼩化因为使⽤有限精度在帧缓存区中保存颜⾊值⽽产生的伪像.
三、EGL (Embedded Graphics Library )
OpenGL ES
在各个iOS、安卓、Linux等各个移动端都可以使用,但是OpenGL ES
和各个平台间的对接需要由各个平台自己来提供和维护,OpenGL ES
只负责底层的渲染。
- OpenGL ES 命令需要渲染上下文和绘制表⾯才能完成图形图像的绘制.
- 渲染上下文: 存储相关
OpenGL ES
状态. - 绘制表面: 是⽤用于绘制图元的表⾯面,它指定渲染所需要的缓存区类型,例如颜色缓存 区,深度缓冲区和模板缓存区.
-
OpenGL ES
API 并没有提供如何创建渲染上下文或者上下⽂如何连接到原⽣生窗⼝口系统.EGL
是Khronos
渲染API(如OpenGL ES
) 和原⽣窗⼝系统之间的接⼝. 唯⼀支持OpenGL ES
却不支持EGL
的平台是iOS. Apple 提供⾃己的EGL API
的iOS实现,称为EAGL
- 因为每个窗⼝系统都有不同的定义,所以
EGL
提供基本的不透明类型—EGLDisplay
, 这个类型封装了所有系统相关性,⽤于和原生窗⼝和系统接⼝.
由于OpenGL ES
是基于C的API,因此它⾮常便便携且受到⼴泛支持。作为C API,它与Objective-C Cocoa Touch
应⽤程序无缝集成。OpenGL ES
规范没有定义窗口层; 相反,托管操作系统必须提供函数来创建⼀个接受命令的OpenGL ES
渲染上下文和一个帧缓冲区,其中写入任何绘图命令的结果。在iOS上使⽤OpenGL ES需要使⽤iOS类来设置和呈现绘图表面,并使⽤平台中立的API来呈现其内容。
四、什么是GLKit?
GLKit
框架的设计目标是为了简化基于OpenGL / OpenGL ES
的应用开发. 。它的出现加快OpenGL ES
或OpenGL
应用程序开发。 使用数学库,背景纹理加载,预先创建的着色器效果,以及标准视图和视图控制器来实现渲染循环。
GLKit
框架提供了功能和类,可以减少创建新的基于着⾊器的应用程序所需的⼯作量,或者⽀持依赖早期版本的OpenGL ES
或OpenGL
提供的固定函数顶点或⽚段处理的现有应用程序。
两个重要的类:
-
GLKView
:提供绘制场所(View) -
GLKViewController
:(扩展于标准的UIKit
设计模式. ⽤于绘制视图内容的管理与呈现.)
虽然苹果弃⽤
OpenGL ES
转为Metal
,但iOS开发者可以继续使用
GLKit 功能
- 加载纹理
- 提供高性能的数学运算
- 提供常见的着⾊器
- 提供视图以及视图控制器.
1.GLKit 纹理加载
1).GLKTextureInfo
创建OpenGL
纹理信息
@interface GLKTextureInfo : NSObject <NSCopying>
{
@private
GLuint name;
GLenum target;
GLuint width;
GLuint height;
GLuint depth;
GLKTextureInfoAlphaState alphaState;
GLKTextureInfoOrigin textureOrigin;
BOOL containsMipmaps;
GLuint mimapLevelCount;
GLuint arrayLength;
}
@property (readonly) GLuint name;
@property (readonly) GLenum target;
@property (readonly) GLuint width;
@property (readonly) GLuint height;
@property (readonly) GLuint depth;
@property (readonly) GLKTextureInfoAlphaState alphaState;
@property (readonly) GLKTextureInfoOrigin textureOrigin;
@property (readonly) BOOL containsMipmaps;
@property (readonly) GLuint mimapLevelCount;
@property (readonly) GLuint arrayLength;
@end
GLKTextureInfo
对象里面有很多属性,常用的如下:
name
: OpenGL 上下文中纹理名称target
: 纹理绑定的目标height
: 加载的纹理⾼度width
: 加载纹理的宽度textureOrigin
: 加载纹理中的原点位置alphaState
: 加载纹理中alpha分量状态containsMipmaps
: 布尔值,加载的纹理是否包含mip贴图
2.GLTextureLoader
简化从各种资源文件中加载纹理
GLTextureLoader是用来加载纹理的,初始化方法如下:
初始化方式:
- initWithSharegroup
: 初始化⼀一个新的纹理理加载到对象中
- initWithShareContext
: 初始化⼀一个新的纹理理加载对象
常见的加载方式如下:
-
从⽂件中加载纹理
+ textureWithContentsOfFile:options:errer:
从⽂件加载2D纹理图像并从数据中
创建新的纹理
- textureWithContentsOfFile:options:queue:completionHandler:
从⽂件中异步
加载2D纹理图像,并根据数据创建新纹理
-
从URL加载纹理
- textureWithContentsOfURL:options:error:
从URL加载2D纹理图像并从数据创
建新纹理
- textureWithContentsOfURL:options:queue:completionHandler:
从URL异步
加载2D纹理图像,并根据数据创建新纹理.
-
从内存中表示创建纹理理
+ textureWithContentsOfData:options:errer:
从内存空间加载2D纹理图像,并根
据数据创建新纹理
- textureWithContentsOfData:options:queue:completionHandler:
从内存空间
异步加载2D纹理图像,并从数据中创建新纹理
-
从CGImages创建纹理理
- textureWithCGImage:options:error:
从Quartz图像加载2D纹理图像并从数据创
建新纹理
- textureWithCGImage:options:queue:completionHandler:
从Quartz图像异步
加载2D纹理理图像,并根据数据创建新纹理
-
从URL加载多维创建纹理理
+ cabeMapWithContentsOfURL:options:errer:
从单个URL加载⽴方体贴图纹理
图像,并根据数据创建新纹理
- cabeMapWithContentsOfURL:options:queue:completionHandler:
从单个
URL异步加载⽴方体贴图纹理图像,并根据数据创建新纹理
-
从⽂件加载多维数据创建纹理
+ cubeMapWithContentsOfFile:options:errer:
从单个文件加载⽴方体贴图纹理
对象,并从数据中创建新纹理理
- cubeMapWithContentsOfFile:options:queue:completionHandler:
从单个⽂件
异步加载⽴方体贴图纹理对象,并从数据中创建新纹理
+ cubeMapWithContentsOfFiles:options:errer:
从⼀系列文件中加载⽴方体贴图
纹理图像,并从数据总创建新纹理
- cubeMapWithContentsOfFiles:options:options:queue:completionHandler:
从一系列文件异步加载⽴方体贴图纹理图像,并从数据中创建新纹理
2.GLKit OpenGL ES
视图渲染
-
GLKView
使用OpenGL ES
绘制内容的视图默认实现
- 初始化视图
- initWithFrame:context:
初始化新视图
delegate
视图的代理理- 配置帧缓存区对象
drawableColorFormat
颜⾊渲染缓存区格式
drawableDepthFormat
深度渲染缓存区格式
drawableStencilFormat
模板渲染缓存区的格式
drawableMultisample
多重采样缓存区的格式- 帧缓存区属性
drawableHeight
底层缓存区对象的⾼度(以像素为单位)
drawableWidth
底层缓存区对象的宽度(以像素为单位)- 绘制视图的内容
context
绘制视图内容时使⽤用的OpenGL ES
上下文
- bindDrawable
将底层FrameBuffer
对象绑定到OpenGL ES
enableSetNeedsDisplay
布尔值,指定视图是否响应使得视图内容⽆效的消息
- display
⽴即重绘视图内容
snapshot
绘制视图内容并将其作为新图像对象返回- 删除视图
FrameBuffer
对象
- deleteDrawable
删除与视图关联的可绘制对象
-
GLKViewDelegate
⽤于GLKView
对象回调方法
绘制视图的内容
- glkView:drawInRect:
绘制视图内容 (必须实现代理)
-
GLKViewController
管理OpenGL ES
渲染循环的视图控制器
- 更新
- (void) glkViewControllerUpdate:
- 配置帧速率
preferredFramesPerSecond
视图控制器调⽤视图以及更新视图内容的速率
framesPerSencond
视图控制器器调用视图以及更新其内容的实际速率- 配置
GLKViewController
代理
delegate
视图控制器的代理- 控制帧更新
paused
布尔值,渲染循环是否已暂停
pausedOnWillResignActive
布尔值,当前程序重新激活动状态时视图控制器是
否⾃动暂停渲染循环
resumeOnDidBecomeActive
布尔值,当前程序变为活动状态时视图控制是否⾃动
恢复呈现循环- 获取有关View 更更新信息
frameDisplayed
视图控制器⾃创建以来发送的帧更新数
timeSinceFirstResume
自视图控制器第一次恢复发送更新事件以来经过的时间量
timeSinceLastResume
自上次视图控制器恢复发送更新事件以来更新的时间量
timeSinceLastUpdate
⾃上次视图控制器调⽤委托⽅法以及经过的时间量
glkViewControllerUpdate:
timeSinceLastDraw` 自上次视图控制器调用视图display 方法以来经过的时间量
-
GLKViewControllerDelegate
渲染循环回调⽅法
处理更新事件
- glkViewControllerUpdate:
在显示每个帧之前调用
暂停/恢复通知
- glkViewController : willPause:
在渲染循环暂停或恢复之前调⽤
-
GLKBaseEffect
一种简单光照/着⾊系统,⽤于基于着⾊器OpenGL
渲染
- 命名Effect
label
给Effect(效果)命名- 配置模型视图转换
transform
绑定效果时应⽤于顶点数据的模型视图,投影和纹理变换- 配置光照效果
lightingType
⽤于计算每个⽚段的光照策略略,GLKLightingType
GLKLightingType
GLKLightingTypePerVertex
表示在三⻆形中每个顶点执行光照计算,然后在三⻆形进⾏插值
GLKLightingTypePerPixel
表示光照计算的输⼊入在三⻆形内插⼊,并且在每个片段执行光照计算- 配置光照
lightModelTwoSided
布尔值,表示为基元的两侧计算光照
material
计算渲染图元光照使用的材质属性
lightModelAmbientColor
环境颜⾊色应用效果渲染的所有图元.
light0
场景中第一个光照属性light1
场景中第二个光照属性light2
场景中第三个光照属性- 配置纹理理
texture2d0
第⼀个纹理属性texture2d1
第二个纹理属性
textureOrder
纹理应用于渲染图元的顺序- 配置雾化
fog
应⽤于场景的雾属性
配置颜⾊信息
colorMaterialEnable
布尔值,表示计算光照与材质交互时是否使⽤颜色顶点属性
useConstantColor
布尔值,指示是否使用常量颜色
constantColor
不提供每个顶点颜⾊数据时使⽤常量颜⾊- 准备绘制效果
- prepareToDraw
准备渲染效果
五、案例解析
1.使用GLKit
实现修改当前view
的backgroundColor
前面已经了解了GLKit中有两个重要的类GLView
和GLViewController
,所以我们在使用的时候就将当前的view
继承与GLView
或者当前VC
继承于GLViewController
。
案例中我们使用的storyboard
,所以只需将当前VC
的view
继承于GLView
即可:
然后来到.m
文件
- 引入相关库头文件,并定义一个
EAGLContext
成员变量:
#import <OpenGLES/ES3/gl.h>
#import <OpenGLES/ES3/glext.h>
@interface ViewController ()
{
EAGLContext *context;
@end
-
viewDidLoad
方法:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//1.初始化上下文&设置当前上下文
/*
EAGLContext 是苹果iOS平台下实现OpenGLES 渲染层.
kEAGLRenderingAPIOpenGLES1 = 1, 固定管线
kEAGLRenderingAPIOpenGLES2 = 2,
kEAGLRenderingAPIOpenGLES3 = 3,
*/
context = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES3];
//判断context是否创建成功
if (!context) {
NSLog(@"Create ES context Failed");
}
//设置当前上下文
[EAGLContext setCurrentContext:context];
//2.获取GLKView & 设置context
GLKView *view =(GLKView *) self.view;
view.context = context;
//3.设置背景颜色
glClearColor(0, 0, 1, 1.0);
}
- 实现
GLView
代理方法
//绘制视图的内容
/*
GLKView对象使其OpenGL ES上下文成为当前上下文,并将其framebuffer绑定为OpenGL ES呈现命令的目标。然后,委托方法应该绘制视图的内容。
*/
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClear(GL_COLOR_BUFFER_BIT);
}
ok,接下来看下效果:
完美!!!
2.使用GLKit
加载图片纹理并显示到view
上
- 在案例1的基础上新增一个成员变量:
@interface ViewController ()
{
EAGLContext *context;
GLKBaseEffect *cEffect;
}
@end
- 初始化
OpenGL ES
-(void)setUpConfig
{
//1.初始化上下文&设置当前上下文
/*
EAGLContext 是苹果iOS平台下实现OpenGLES 渲染层.
kEAGLRenderingAPIOpenGLES1 = 1, 固定管线
kEAGLRenderingAPIOpenGLES2 = 2,
kEAGLRenderingAPIOpenGLES3 = 3,
*/
context = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES3];
//判断context是否创建成功
if (!context) {
NSLog(@"Create ES context Failed");
}
//设置当前上下文
[EAGLContext setCurrentContext:context];
//2.获取GLKView & 设置context
GLKView *view =(GLKView *) self.view;
view.context = context;
/*3.配置视图创建的渲染缓存区.
(1). drawableColorFormat: 颜色缓存区格式.
简介: OpenGL ES 有一个缓存区,它用以存储将在屏幕中显示的颜色。你可以使用其属性来设置缓冲区中的每个像素的颜色格式。
GLKViewDrawableColorFormatRGBA8888 = 0,
默认.缓存区的每个像素的最小组成部分(RGBA)使用8个bit,(所以每个像素4个字节,4*8个bit)。
GLKViewDrawableColorFormatRGB565,
如果你的APP允许更小范围的颜色,即可设置这个。会让你的APP消耗更小的资源(内存和处理时间)
(2). drawableDepthFormat: 深度缓存区格式
GLKViewDrawableDepthFormatNone = 0,意味着完全没有深度缓冲区
GLKViewDrawableDepthFormat16,
GLKViewDrawableDepthFormat24,
如果你要使用这个属性(一般用于3D游戏),你应该选择GLKViewDrawableDepthFormat16
或GLKViewDrawableDepthFormat24。这里的差别是使用GLKViewDrawableDepthFormat16
将消耗更少的资源
*/
//3.配置视图创建的渲染缓存区.
view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
view.drawableDepthFormat = GLKViewDrawableDepthFormat16;
//4.设置背景颜色
glClearColor(0, 0, 1, 1.0);
}
和案例一相比,这一步增加视图创建的颜色缓冲区和深度缓冲区:
3.配置视图创建的渲染缓存区.
view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888; view.drawableDepthFormat = GLKViewDrawableDepthFormat16;
- 创建顶点数据
-(void)setUpVertexData
{
//1.设置顶点数组(顶点坐标,纹理坐标)
/*
纹理坐标系取值范围[0,1];原点是左下角(0,0);
故而(0,0)是纹理图像的左下角, 点(1,1)是右上角.
*/
GLfloat vertexData[] = {
0.5, -0.5, 0.0f, 1.0f, 0.0f, //右下
0.5, 0.5, 0.0f, 1.0f, 1.0f, //右上
-0.5, 0.5, 0.0f, 0.0f, 1.0f, //左上
0.5, -0.5, 0.0f, 1.0f, 0.0f, //右下
-0.5, 0.5, 0.0f, 0.0f, 1.0f, //左上
-0.5, -0.5, 0.0f, 0.0f, 0.0f, //左下
};
/*
顶点数组: 开发者可以选择设定函数指针,在调用绘制方法的时候,直接由内存传入顶点数据,也就是说这部分数据之前是存储在内存当中的,被称为顶点数组
顶点缓存区: 性能更高的做法是,提前分配一块显存,将顶点数据预先传入到显存当中。这部分的显存,就被称为顶点缓冲区
*/
//2.开辟顶点缓存区
//(1).创建顶点缓存区标识符ID
GLuint bufferID;
glGenBuffers(1, &bufferID);
//(2).绑定顶点缓存区.(明确作用)
glBindBuffer(GL_ARRAY_BUFFER, bufferID);
//(3).将顶点数组的数据copy到顶点缓存区中(GPU显存中)
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
//3.打开读取通道.
/*
(1)在iOS中, 默认情况下,出于性能考虑,所有顶点着色器的属性(Attribute)变量都是关闭的.
意味着,顶点数据在着色器端(服务端)是不可用的. 即使你已经使用glBufferData方法,将顶点数据从内存拷贝到顶点缓存区中(GPU显存中).
所以, 必须由glEnableVertexAttribArray 方法打开通道.指定访问属性.才能让顶点着色器能够访问到从CPU复制到GPU的数据.
注意: 数据在GPU端是否可见,即,着色器能否读取到数据,由是否启用了对应的属性决定,这就是glEnableVertexAttribArray的功能,允许顶点着色器读取GPU(服务器端)数据。
(2)方法简介
glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
功能: 上传顶点数据到显存的方法(设置合适的方式从buffer里面读取数据)
参数列表:
index,指定要修改的顶点属性的索引值,例如
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)
stride,指定连续顶点属性之间的偏移量。如果为0,那么顶点属性会被理解为:它们是紧密排列在一起的。初始值为0
ptr指定一个指针,指向数组中第一个顶点属性的第一个组件。初始值为0
*/
//顶点坐标数据
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);
}
这一步我们是为了创建显示图片的顶点数据,确定图片显示到view
的那个位置。
图片是正方形,我们由两个三角形拼起来,所以需要6个顶点。
值得一提的是:我们定义顶点坐标使用的是一维数组,我们在前面就讲过,在
OpenGL
中习惯使用一维数组,所以OpenGL ES
也是一样的。
- 加载图片纹理并显示
-(void)setUpTexture
{
//1.获取纹理图片路径
NSString *filePath = [[NSBundle mainBundle]pathForResource:@"Jessica Alba" ofType:@"jpg"];
//2.设置纹理参数
//纹理坐标原点是左下角,但是图片显示原点应该是左上角.
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:@(1),GLKTextureLoaderOriginBottomLeft, nil];
GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
//3.使用苹果GLKit 提供GLKBaseEffect 完成着色器工作(顶点/片元)
cEffect = [[GLKBaseEffect alloc]init];
cEffect.texture2d0.enabled = GL_TRUE;
cEffect.texture2d0.name = textureInfo.name;
}
- 实现
GLKViewDelegate
代理方法
//绘制视图的内容
/*
GLKView对象使其OpenGL ES上下文成为当前上下文,并将其framebuffer绑定为OpenGL ES呈现命令的目标。然后,委托方法应该绘制视图的内容。
*/
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
//1.
glClear(GL_COLOR_BUFFER_BIT);
//2.准备绘制
[cEffect prepareToDraw];
//3.开始绘制
glDrawArrays(GL_TRIANGLES, 0, 6);
}
-
viewDidLoad
调用
- (void)viewDidLoad {
[super viewDidLoad];
//1.OpenGL ES 相关初始化
[self setUpConfig];
//2.加载顶点/纹理坐标数据
[self setUpVertexData];
//3.加载纹理数据(使用GLBaseEffect)
[self setUpTexture];
}
ok,运行一下
注意:使用
GLKit
是一定要注意GLKViewDelegate
代理的实现
觉得不错记得点赞哦!听说看完点赞的人逢考必过,逢奖必中。ღ( ´・ᴗ・` )比心