OpenGL 图形库使用(一) —— 概念基础

OpenGL ES基础
OpenGL ES是一套多功能开放标准的用于嵌入系统的C-based的图形库,用于2D和3D数据的可视化。OpenGL被设计用来转换一组图形调用功能到底层图形硬件(GPU),由GPU执行图形命令,用来实现复杂的图形操作和运算,从而能够高性能、高帧率利用GPU提供的2D和3D绘制能力。
OpenGL ES规范本身不定义绘制表面和绘制窗口,因此ios为了使用它必须提供和创建一个OpenGL ES的呈现环境,创建和配置存储绘制命令结果的framebuffer 及创建和配置一个或多个呈现目标。在 iOS中使用EAGL提供的EAGLContext类 来实现和提供一个呈现环境,用来保持OpenGLES使用到的硬件状态。 EAGL是一个Objective-C API,提供使OpenGL ES与Core Animation和UIKIT集成的接口。
在调用任何OpenGL ES 功能之前必须首先初始化一个EAGLContext 对象。每一个iOS应用的每一个线程都有一个当前context,在调用OpenGLES函数时,使用或改变此context中的状态。EAGLContext的类方法setCurrentContext:用来设置当前线程的当前context。EAGLContext 的类方法currentContext返回当前线程的当前context。在切换相同线程的两个上下文之前,必须调用glFlush函数来确保先前已提交的命令被提交到图形硬件中。
可以采用不同的方式使用OpenGL ES以便呈现OpenGL ES内容到不同的目标:GLKit和CAEAGLLayer。为了创建全屏幕的视图或使OpenGL ES
内容与UIKit视图集成,可以使用GLKit。在使用GLKit时,GLKit提供的类GLKView类本身实现呈现目标及创建和维护一个framebuffer。
为了使OpenGL ES内容作为一个Core Animation层的部分内容时,可以使用CAEAGLLayer 作为呈现目标,并需要另外创建framebuffer以及自己实现和控制整个绘制流程。
GLKit是一组objective-c 类,为使用OpenGL ES 提供一个面向对象接口,用来简化OpenGL ES应用的开发。GLKit支持四个3D应用开发的关键领域:

GLKView 和GLKViewController类提供一个标准的OpenGL ES视图和相关联的呈现循环。GLKView可以作为OpenGL ES内容的呈现目标,GLKViewController提供内容呈现的控制和动画。视图管理和维护一个framebuffer,应用只需在framebuffer进行绘画即可。

GLKTextureLoader 为应用提供从iOS支持的各种图像格式的源自动加载纹理图像到OpenGL ES 图像环境的方式,并能够进行适当的转换,并支持同步和异步加载方式。
数学运算库,提供向量、矩阵、四元数的实现和矩阵堆栈操作等OpenGL ES 1.1功能。

Effect效果类提供标准的公共着色效果的实现。能够配置效果和相关的顶点数据,然后创建和加载适当的着色器。GLKit 包括三个可配置着色效果类:GLKBaseEffect实现OpenGL ES 1.1规范中的关键的灯光和材料模式,GLKSkyboxEffect提供一个skybox效果的实现,GLKReflectionMapEffect 在GLKBaseEffect基础上包括反射映射支持。

GLKView和OpenGL ES绘制过程
使用GLKView和OpenGLES进行绘制过程:

创建一个GLKView对象。
GLKView 对象可以编程或使用Interface Builder来创建和配置。在采用编程方式时,首先创建一个context然后调用initWithFrame:context:方法。使用Interface Builder方式时,在从storyboard加载一个GLKView后,创建一个context和设置它作为视图的context属性。在iOS中GLKit的使用需要创建OpenGL ES 2.0以上的图形环境context。GLKit视图自动创建和配置它所有的OpenGLES framebuffer对象和renderbuffers,可以通过修改视图的drawable属性来控制这些对象的属性。

绘制OpenGL内容(发布绘制命令)
使用GLKit视图绘制OpenGL内容需要三个子步骤:

准备OpenGL ES基础;
发布绘制命令;
呈现显示内容到Core Animation。

GLKit类本身已经实现了第一个和第三个步骤,用户只需实现第二个步骤,在视图的方法drawRect或视图的代理对象的glkView:drawInRect:中调用适当的OpenGL ES绘制命令进行内容绘制。GLKViewController类维护一个animation呈现循环(包含两个方法update和display),用来实现连续的动画复杂的场景。animation 呈现循环的交替速率由GLKViewController的属性framesPerSecond指示,并使用preferredFramesPerSecond 属性来修改它。

OpenGL ES版本
iOS系统默认支持OpenGl ES1.0、ES2.0以及ES3.0 3个版本,三者之间并不是简单的版本升级,设计理念甚至完全不同,在开发OpenGL项目前,需要根据业务需求选择合适的版本。在学习OpenGL代码的时候也需要知道它对应着哪个版本,在ES1中执行ES2代码是看不到任何效果的,你可以在初始化EAGLContext时指定ES版本号。
指定版本方法如下所示。
EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];

OpenGL ES坐标系
OpenGL ES坐标系和UI的坐标系是不同的,具体如下所示。

OpenGL ES 坐标系

UI是以左上角为原点的,而OpenGL ES 坐标系是以屏幕中心为原点的。除了方向,还有一点需要注意,默认情况各个方向坐标值范围为(-1,1),而不是UIKit中的(0,320)。当绘制点(320,0)时,它并不会出现在屏幕右上角。在ES1中,可以通过以下代码将坐标系转化为熟悉的(320,480)。下面我们看代码。

  • (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
    {
    glViewport(0, 0, rect.size.width * 2, rect.size.height * 2);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthof(0, 320, 0, 480, -1024, 1024);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    }

几个重要的类
下面介绍几个重要的类。

  1. GLKViewController & GLKView
    为了方便大家更快的开发,系统为OpenGL提供了简单的封装,继承GLKViewController定义自己的ViewController,GLKViewController的view为GLKView类,GLKView的delegate定义了绘制回调函数。
  • (void)glkView:(GLKView *)view drawInRect:(CGRect)rect

GLKViewController定义数据刷新函数,当子类实现-(void)update方法,glkViewControllerUpdate方法将不再被调用。

  • (void)glkViewControllerUpdate:(GLKViewController *)controller

需要补充一点,默认情况下,GLKViewController渲染RunLoop并非NSRunLoopCommonModes,而是NSDefaultRunLoopMode,因此在UIKit中使用GLKViewController,当滑动界面时,OpenGL是不会渲染的。
2. EAGLContext
在介绍选择版本时已经提到EAGLContext,与UIKit中CGContextRef相似,EAGLContext相当于OpenGL绘制句柄或者上下文,在绘制试图之前,需要指定使用创建的上下文绘制。
[EAGLContext setCurrentContext:view.context];

当一个APP可能存在多个EAGLContext时,需要处理并存冲突等问题,比如大家所熟知的GPUImage,都会使用到EAGLContext。因此,在使用中要记得及时释放。有兴趣的朋友可以看看这篇文章。
这里还需要记住的是:当App退到后台时, 切记暂停OpenGL绘制,否则可能导致crash。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值