收藏夹OpenGLiOS-直播技术

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

2017-07-22  本文已影响613人  刀客传奇

版本记录

版本号 时间
V1.0 2017.07.22

前言

OpenGL 图形库项目中一直也没用过,最近也想学着使用这个图形库,感觉还是很有意思,也就自然想着好好的总结一下。首先要给大家介绍个学习网站。
1. 欢迎来到OpenGL的世界
2.系列教程
3.教程代码
4.落影简书

OpenGL ES基础

OpenGL

OpenGL ES是一套多功能开放标准的用于嵌入系统的C-based的图形库,用于2D3D数据的可视化。OpenGL被设计用来转换一组图形调用功能到底层图形硬件(GPU),由GPU执行图形命令,用来实现复杂的图形操作和运算,从而能够高性能、高帧率利用GPU提供的2D3D绘制能力。

OpenGL ES规范本身不定义绘制表面和绘制窗口,因此ios为了使用它必须提供和创建一个OpenGL ES的呈现环境,创建和配置存储绘制命令结果的framebuffer 及创建和配置一个或多个呈现目标。在 iOS中使用EAGL提供的EAGLContext类 来实现和提供一个呈现环境,用来保持OpenGLES使用到的硬件状态。 EAGL是一个Objective-C API,提供使OpenGL ESCore AnimationUIKIT集成的接口。

在调用任何OpenGL ES 功能之前必须首先初始化一个EAGLContext 对象。每一个iOS应用的每一个线程都有一个当前context,在调用OpenGLES函数时,使用或改变此context中的状态。EAGLContext的类方法setCurrentContext:用来设置当前线程的当前contextEAGLContext 的类方法currentContext返回当前线程的当前context。在切换相同线程的两个上下文之前,必须调用glFlush函数来确保先前已提交的命令被提交到图形硬件中。

可以采用不同的方式使用OpenGL ES以便呈现OpenGL ES内容到不同的目标:GLKitCAEAGLLayer。为了创建全屏幕的视图或使OpenGL ES
内容与UIKit视图集成,可以使用GLKit。在使用GLKit时,GLKit提供的类GLKView类本身实现呈现目标及创建和维护一个framebuffer

为了使OpenGL ES内容作为一个Core Animation层的部分内容时,可以使用CAEAGLLayer 作为呈现目标,并需要另外创建framebuffer以及自己实现和控制整个绘制流程。

GLKit是一组objective-c 类,为使用OpenGL ES 提供一个面向对象接口,用来简化OpenGL ES应用的开发。GLKit支持四个3D应用开发的关键领域:


GLKView和OpenGL ES绘制过程

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

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


OpenGL ES版本

iOS系统默认支持OpenGl ES1.0ES2.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定义自己的ViewControllerGLKViewControllerviewGLKView类,GLKViewdelegate定义了绘制回调函数。

- (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,与UIKitCGContextRef相似,EAGLContext相当于OpenGL绘制句柄或者上下文,在绘制试图之前,需要指定使用创建的上下文绘制。

[EAGLContext setCurrentContext:view.context];

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

后记

这篇主要是基本的介绍和几个基础概念,后面还会继续给大家扩展,毕竟基础的部分是固定的。未完,待续~~~

湖泊
上一篇 下一篇

猜你喜欢

热点阅读