GLKit 框架详细解析(二)—— 一个详细示例和说明(一)

版本记录

版本号 时间
V1.0 2018.08.10

前言

GLKit框架的设计目标是为了简化基于OpenGL或者OpenGL ES的应用开发。 接下来几篇我们就解析一下这个框架。感兴趣的看下面几篇文章。
1. GLKit 框架详细解析(一)—— 基本概览

简介

如果您对图形编程感兴趣,那么您可能已经阅读过OpenGL,它仍然是从硬件和软件角度来看最常用的API。 Apple开发了一个名为GLKit的框架,以帮助开发人员创建利用OpenGL的应用程序并抽象样板代码。 它还允许开发人员专注于绘图,而不是开启项目。 您将在这个适用于iOS的GLKit教程中了解所有这些是如何工作的。

GLKit在以下四个方面提供功能:

  • Views and View Controllers - 视图和视图控制器:这些抽象出大部分是GLKit用于设置基本OpenGL ES(嵌入式系统)项目的样板代码。
  • Effects - 效果:这些实现了常见的着色行为,是设置基本光照,着色,反射映射和天空盒效果的便捷方式。
  • Math - 数学:为常见的数学例程提供帮助和函数,如向量和矩阵操作。
  • Texture Loading - 纹理加载:使图像作为要在OpenGL中使用的纹理加载更容易。

注意:您将使用OpenGL ES 3.0,可在iPhone 5S及更高版本,iPad Mini 2及更高版本以及iPad 5及更高版本上使用。

本文章的目标是让您快速了解使用OpenGL和GLKit的基础知识,假设您以前没有任何经验。 您将构建一个应用程序,将立方体绘制到屏幕并使其旋转。

打开Xcode并创建一个全新的项目。 选择iOS \ Application \ Single View App模板。将产品名称设置为OpenGLKit,将语言设置为Swift。 确保未选中任何复选框。 单击“下一步”,选择要在其中保存项目的文件夹,然后单击“创建”。

Build并运行。 你会看到一个简单的空白屏幕:


Introducing GLKView and GLKViewController - 引入GLKView和GLKViewController

您需要导入GLKit,您的view controller需要是GLKViewController的子类。

import GLKit

class ViewController: GLKViewController {

}

Interface Builder支持GLKit,因此这是设置它的最佳方式。 现在就这样做。

打开Main.storyboard并删除storyboard的内容。 然后,从对象库中将GLKit View Controller拖到scene中。

Identity检查器中,将类更改为ViewController。 在Attributes 检查器中,选中Is Initial View Controller复选框。

最后,将Preferred FPS更改为60:

打开Attributes检查器后,单击画布中的GLKView,并注意颜色,深度和模板格式以及多重采样multisampling的一些设置。如果你正在做一些高级的事情,你需要改变这些,本教程使用默认设置就可满足需求。

您的OpenGL上下文有一个缓冲区buffer,用于存储将显示在屏幕上的颜色。您可以使用Color Format属性为缓冲区中的每个像素设置颜色格式。

默认值为GLKViewDrawableColorFormatRGBA8888,这意味着缓冲区中的每个颜色分量使用8位(每个像素总共4个字节)。这是最佳选择,因为它可以为您提供最广泛的颜色范围,这意味着应用程序看起来更高质量。

这就是你在storyboard中需要做的所有设置。您的视图控制器设置了GLKView以绘制OpenGL内容,并且它还被设置为GLKViewDelegate用于更新和绘制调用。

回到ViewController.swift,添加以下变量和方法:

private var context: EAGLContext?

private func setupGL() {
  // 1
  context = EAGLContext(api: .openGLES3)
  // 2
  EAGLContext.setCurrent(context)

  if let view = self.view as? GLKView, let context = context { 
    // 3
    view.context = context
   // 4 
    delegate = self
  }
}

以下是此方法中发生的情况:

  • 1)要使用OpenGL执行任何操作,您需要创建EAGLContext

EAGLContext管理iOS需要使用OpenGL绘制的所有信息。它类似于需要Core Graphics上下文与Core Graphics一起做任何事情。创建上下文时,指定要使用的API版本。在本文中要使用OpenGL ES 3.0。

  • 2)指定刚刚创建的呈现上下文rendering context是在当前线程中使用的呈现上下文。

OpenGL上下文不应该跨线程共享,因此您必须确保只从您用来调用此方法setupGL()的任何线程中与此上下文进行交互。

  • 3)这将设置GLKView的上下文。解包必要的变量后,将GLKView的上下文设置为您创建的此OpenGL ES 3.0上下文。

  • 4)这将当前类(ViewController)设置为GLKViewController的代理。每当需要进行状态和逻辑更新时,将调用glkViewControllerUpdate(_ controller :)方法。

完成此操作后,添加以下内容以实现vi​​ewDidLoad()以调用此方法:

override func viewDidLoad() {
  super.viewDidLoad()
  setupGL()
}

所以现在你知道哪个线程称为setupGL() - 它是主线程,它是专门用于与UIKit交互的特殊线程,当系统调用viewDidLoad()时它被系统使用。

此时,您可能会注意到有错误。 这是因为你还没有遵循GLKViewControllerDelegate。 继续,通过添加以下扩展名使其符合要求:

extension ViewController: GLKViewControllerDelegate {
  func glkViewControllerUpdate(_ controller: GLKViewController) {
  }
}

接下来,将以下方法添加到ViewController主类定义中:

override func glkView(_ view: GLKView, drawIn rect: CGRect) {
  // 1
  glClearColor(0.85, 0.85, 0.85, 1.0) 
  // 2
  glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
}

这是GLKViewDelegate的一部分,它在每一帧上绘制内容。 这是它的作用:

  • 1)调用glClearColor指定清除屏幕时要使用的RGB和alpha(透明度)值。 在这里,你把它设置为浅灰色。

  • 2)调用glClear来实际执行清除。 可以有不同类型的缓冲区,如您现在正在显示的渲染/颜色render/color缓冲区,以及其他depth or stencil缓冲区。 在这里,您使用GL_COLOR_BUFFER_BIT标志指定要清除当前渲染/颜色render/color缓冲区。

Build并运行应用程序。 注意屏幕颜色是如何变化的:


Creating Vertex Data for a Simple Square - 为简单方块创建顶点数据

是时候开始在屏幕上画一个正方形的过程了! 首先,您需要创建定义正方形的顶点vertices。 顶点(多个顶点)只是定义要绘制的形状轮廓的点。

您将按如下方式设置顶点:

只能使用OpenGL渲染三角形几何体。 但是,您可以创建一个带有两个三角形的正方形,如上图所示:一个三角形顶点(0,1,2)和一个三角形顶点(2,3,0)。

OpenGL ES的一个好处是你可以保持你的顶点数据有条理。 对于此项目,您将使用Swift结构体来存储顶点位置和颜色信息,然后使用您将用于绘制的每个顶点的顶点数组。

右键单击Project导航器中的OpenGLKit文件夹,选择New File ...转到iOS \ Swift File,然后单击Next。 将文件命名为Vertex,然后单击Create。 用以下内容替换文件的内容:

import GLKit

struct Vertex {
  var x: GLfloat
  var y: GLfloat
  var z: GLfloat
  var r: GLfloat
  var g: GLfloat
  var b: GLfloat
  var a: GLfloat
}

对于具有位置(x,y,z)和颜色(r,g,b,a)的变量的顶点,这是非常简单的Swift结构体。 GLFloat是Swift Float的类型别名,但是在使用OpenGL时,它是推荐使用浮点数的方法。 您可能会看到类似的模式,其中您将OpenGL类型用于您创建的其他变量。

返回到ViewController.swift中。 在控制器中添加以下代码:

var Vertices = [
  Vertex(x:  1, y: -1, z: 0, r: 1, g: 0, b: 0, a: 1),
  Vertex(x:  1, y:  1, z: 0, r: 0, g: 1, b: 0, a: 1),
  Vertex(x: -1, y:  1, z: 0, r: 0, g: 0, b: 1, a: 1),
  Vertex(x: -1, y: -1, z: 0, r: 0, g: 0, b: 0, a: 1),
]

var Indices: [GLubyte] = [
  0, 1, 2,
  2, 3, 0
]

在这里,您使用Vertex结构体创建用于绘制的顶点数组。 然后,您创建一个GLubyte值数组。 GLubyte只是旧的UInt8的类型别名,此数组指定绘制构成三角形的三个顶点中的每一个的顺序。 也就是说,前三个整数(0,1,2)表示通过使用第0个,第1个,最后是第2个verex来绘制第一个三角形。 后三个整数(2,3,0)表示使用第2个,第3个和第0个顶点绘制第二个三角形。

因为三角形共享顶点,这节省了资源:您只创建一个包含所有四个顶点的数组,然后使用单独的数组通过引用这些顶点来定义三角形。 因为指向顶点的数组索引占用的内存少于顶点本身,所以这可以节省内存。

完成后,您将获得传递给OpenGL以绘制正方形所需的所有信息。


Creating Vertex Buffer Objects and a Vertex Array Object - 创建顶点缓冲区对象和顶点数组对象

向OpenGL发送数据的最佳方式是通过名为Vertex Buffer Objects的方法。 这些是OpenGL对象,可以为您存储顶点数据的缓冲区。

这里有三种类型的对象需要注意:

  • Vertex Buffer Object (VBO) - 顶点缓冲区对象(VBO):跟踪每个顶点数据本身,就像Vertices数组中的数据一样。

  • Element Buffer Object (EBO) - 元素缓冲区对象(EBO):跟踪定义三角形的索引,例如存储在Indices数组中的索引。

  • Vertex Array Object (VAO) - 顶点数组对象(VAO):此对象可以像顶点缓冲区对象一样绑定。 在绑定顶点数组对象之后,您所做的任何未来顶点属性调用都将存储在其中。 这意味着你只需要调用一次配置顶点属性指针然后 - 每当你想绘制一个对象时 - 你绑定相应的VAO。 这有助于并加速绘制具有不同配置的不同顶点数据。

ViewController.swift的顶部,添加以下Array扩展以帮助获取VerticesIndices数组的大小(以字节为单位):

extension Array {
  func size() -> Int {
    return MemoryLayout<Element>.stride * self.count
  }
}

这里一个重要的微妙之处在于,为了确定数组占用的内存,我们需要将其组成元素的步幅stride加起来,而不是大小size。 根据定义,元素的步幅是元素在数组中时占用的内存量。 由于填充,这可能比元素的大小更大,这基本上是extra memory that we use up to keep the CPU happy的技术术语。

接下来,在ViewController中添加以下变量:

private var ebo = GLuint()
private var vbo = GLuint()
private var vao = GLuint()

这些是元素缓冲区对象,顶点缓冲区对象和顶点数组对象的变量。 所有都是GLuint类型,UInt32的类型别名。

后记

本篇主要讲述了一个详细示例和说明,感兴趣的给个赞或者关注~~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容