美文网首页
iOS开发之初识OpenGL

iOS开发之初识OpenGL

作者: 番茄炒西红柿啊 | 来源:发表于2020-07-03 15:04 被阅读0次

    什么是OpenGL

    • OpenGL (Open Graphics Library)是一个跨编程语言、跨平台的编程图形程序接口,它将计算机的资源抽象称为一个OpenGL的对象,对这些资源的操作抽象为⼀个的OpenGL指令
    • OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的⼦集,针对手机、 PDA和游戏主机等嵌入式设备⽽设计,去除了许多不必要和性能较低的API接⼝。我们做移动端开发的主要关注的就是这个
    • Metal : Apple为游戏开发者推出了新的平台技术 Metal,该技术能够为 3D 图 像提高 10 倍的渲染性能.Metal 是Apple为了解决3D渲染⽽推出的框架
      此处引用cc原文章,点我跳转
    图1.png
    作为一名iOS移动端开发人员,平时我们接触的大部分和CoreGraphics, CoreAnimation, CoreImage等相关处理的API时,其实里面就是通过OpenGL ES实现的.不过后来苹果研发了自己的一套Metal框架将其替换掉了.

    既然有了Metal我们是否还有学习OpenGL ES的必要呢.我个人认为暂时还是有必要的.OpenGL /OpenGL ES/ Metal 在任何项目中解决问题的本质就是利用GPU芯片来⾼效渲染图形图像.所以它们底层的原理相近,首先了解OpenGL之后再去了解Metal会更加容易, 其二OpenGL是跨平台的框架.保不齐以后会在其他的地方用到,所谓技多不压身.毕竟不可能保证一直都做苹果开发吧.

    OpenGL 专有名词

    上下文 context (状态机)

    • 在应⽤程序调⽤任何OpenGL的指令之前,需要安排首先创建⼀一个OpenGL的 上下⽂。这个上下文是⼀一个⾮常庞⼤大的状态机,保存了了OpenGL中的各种状态,这也是OpenGL指令执⾏行行的基础
    • OpenGL的函数不管在哪个语⾔言中,都是类似C语⾔言一样的面向过程的函 数,本质上都是对OpenGL上下文这个庞大的状态机中的某个状态或者对象 进⾏行操作,当然你得⾸先把这个对象设置为当前对象。因此,通过对 OpenGL指令的封装,是可以将OpenGL的相关调用封装成为一个⾯面向对象的 图形API的
    • 由于OpenGL上下文是一个巨大的状态机,切换上下⽂往往会产生较⼤的开 销,但是不同的绘制模块,可能需要使⽤完全独⽴的状态管理理。因此,可 以在应用程序中分别创建多个不同的上下⽂,在不同线程中使⽤不同的上 下文,上下⽂之间共享纹理、缓冲区等资源。这样的⽅案,会比反复切换 上下文,或者大量量修改渲染状态,更加合理⾼效的.
      此处引用cc原文章,点我跳转

    理论枯燥且乏味, 但是我们联想一下flutter开发中用到的context, iOS开发中CoreGraphics里也有用到context. 是不是此时心中就有了一定的答案.我个人理解其设计模式大同小异. 顾名思义我们能够通过context拿到很多必要的状态和数据.

    渲染 (Rendering)

    渲染指的就是将图形/图像数据转换成2D空间图像的操作.比如:我们App中将一个按钮展示在屏幕上, 一张图片展示在屏幕, 再或者视频在屏幕上的播放. 这些都叫做渲染.

    顶点数组(VertexArray) 和 顶点缓冲区 (VertexBuffer)

    首先需要了解,OpenGL中的图像都是由图元组成. 在OpenGL ES中有三种图元: 点, 线, 三角. 其他的图形都是基于这三种图元组合而成.

    比如需要显示一个正方形, 则需要两个正等边三角形图元来完成

    图二.png
    用来存放图元的顶点的数组就叫做顶点数组, 比如这个正方形由2个三角形组成, 一个三角形有3个顶点, 所以这个正方形的顶点数组里存放有6个顶点.

    为了读取效率起见, 提前分配一块显存, 将顶点数组存放在显存中. 这部分显存就叫做顶点缓冲区

    管线

    OpenGL渲染的过程中会经历很多节点. 这些节点串起来就是管线.

    固定管线/存储着色器

    如果不过分纠结专业术语的话可以比较粗暴的理解为: OpenGL内部封装好的API供开发者直接调用.比如: 光照、坐标变换、裁剪等操作,都有封装好的API直接使用,开发者只需要传递对应的参数就可以完成图形渲染.不需要关注内部的实现.

    着色器

    和我们平时iOS开发类似的.并不是所有系统封装好的UI控件都能满足业务需求,有时我们需要自定义UI控件. 同理:固定管线或存储着⾊器⽆法完成每一个业务,这时将相关部分开放成可编程, 供我们开发者自定义一些操作

    常见的着⾊器主要有: 顶点着⾊器(VertexShader), ⽚段着⾊器(FragmentShader), 几何着⾊(GeometryShader), 曲⾯细分着⾊器(TessellationShader)

    OpenGL ES 中只⽀持顶点着⾊器片段着⾊器.

    • 顶点着色器 (VertexShader): 用来处理顶点的一些操作,如:旋转/平移/投影等. 每个顶点数据都会执⾏一次顶点着⾊器.多个顶点为并行执行.每个顶点都只能处理自己的数据,无法访问其他顶点的数据.
    • 片段着色器 (FragmentShader): 用来处理片段(像素)的操作.如:像素点的颜色计算填充等. 同顶点着色器一样, 每一个像素都为执行一次片段着色器程序, 多个像素也是并行执行的.

    GLSL(OpenGL Shading Language)

    OpenGL着色语言(OpenGL Shading Language)是用来在OpenGL中着色编程的语言,也即开发人员写的短小的自定义程序,他们是在图形卡的GPU (Graphic Processor Unit图形处理单元)上执行的,代替了固定的渲染管线的一部分,使渲染管线中不同层次具有可编程性。比如:视图转换、投影转换等。GLSL(GL Shading Language)的着色器代码分成2个部分:Vertex Shader(顶点着色器)和Fragment(片断着色器)
    此处引用cc原文章,点我跳转

    光栅化 Rasterization

    光栅化就是把顶点数据转换为片元的过程。片元中的每一个元素对应于帧缓冲区中的一个像素。

    如果把渲染比作是画画, 那么顶点着色器操作相当与确定画的内容的框架. 而之后往框架里填充内容的过程就是光栅化.

    填充好内容之后就是片元着色器操作像素点填充颜色等操作

    这里附上一张流程图:


    图三

    纹理 (Texture)

    纹理可以理解为图⽚。 在渲染图形时需要在顶点围成的区域中填充图⽚,使得场景更加逼真。⽽这⾥使⽤的图⽚,就是常说的纹理。只是在OpenGL,我们更加习惯叫纹理,⽽不是图⽚。

    混合 (Blending)

    在测试阶段之后,如果像素依然没有被剔除,那么像素的颜色将会和帧缓冲区中颜色附着上的颜色进行混合,混合的算法可以通过OpenGL的函数进行指定。但是OpenGL提供的混合算法是有限的,如果需要更加复杂的混合算法,一般可以通过像素着色器进行实现,当然性能会比原生的混合算法差一些。
    此处引用cc原文章,点我跳转

    矩阵

    • 变换矩阵 (Transformation) : 例如图形想发⽣平移、缩放、旋转等变换,就需要使用变换矩阵。
    • 投影矩阵 (Projection) : ⽤于将3D坐标转换为⼆维屏幕坐标,实际线条也将在二维坐标下进行绘制。

    渲染上屏/交换缓冲区 (SwapBuffer)

    渲染缓冲区一般映射的是系统的资源比如窗口。如果将图像直接渲染到窗口对应的渲染缓冲区,则可以将图像显示到屏幕上。

    但是,值得注意的是,如果每个窗口只有一个缓冲区,那么在绘制过程中屏幕进行了刷新,窗口可能显示出不完整的图像。

    为了解决这个问题,常规的OpenGL程序至少都会有两个缓冲区。显示在屏幕上的称为屏幕缓冲区,没有显示的称为离屏缓冲区。在一个缓冲区渲染完成之后,通过将屏幕缓冲区和离屏缓冲区交换,实现图像在屏幕上的显示。

    由于显示器的刷新一般是逐行进行的,因此为了防止交换缓冲区的时候屏幕上下区域的图像分属于两个不同的帧,因此交换一般会等待显示器刷新完成的信号,在显示器两次刷新的间隔中进行交换,这个信号就被称为垂直同步信号,这个技术被称为垂直同步

    使用了双缓冲区和垂直同步技术之后,由于总是要等待缓冲区交换之后再进行下一帧的渲染,使得帧率无法完全达到硬件允许的最高水平。为了解决这个问题,引入了三缓冲区技术,在等待垂直同步时,来回交替渲染两个离屏的缓冲区,而垂直同步发生时,屏幕缓冲区和最近渲染完成的离屏缓冲区交换,实现充分利用硬件性能的目的。

    相关文章

      网友评论

          本文标题:iOS开发之初识OpenGL

          本文链接:https://www.haomeiwen.com/subject/oymdqktx.html