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

0.325字数 2016阅读 3570

版本记录

版本号 时间
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应用开发的关键领域:

  • GLKViewGLKViewController类提供一个标准的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效果的实现,GLKReflectionMapEffectGLKBaseEffect基础上包括反射映射支持。

GLKView和OpenGL ES绘制过程

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

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

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

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

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

后记

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

湖泊

推荐阅读更多精彩内容