美文网首页
第二弹 OpenGL 快速理解 图形API(一)

第二弹 OpenGL 快速理解 图形API(一)

作者: Mr_Lxh | 来源:发表于2019-05-14 12:50 被阅读0次

    快速了解图形API

    图形API简介(定义)

    • OpenGL(Open Graphics Library)是一个跨编程语言、跨平台的编程图形程序接口,它将计算机的资源成为一个OpenGL的对象。对这些资源的操作抽象为一个个的OpenGL指令

    • OpenGL ES(OpenGL for Embedded System)是OpenGL 三维图形API的子集,针对手机PDA和游戏主机等嵌入式设备而设计,去除了许多不必要和性能较低的API接口

    • DirectX 是属于Windows上的一个多媒体处理框架,它由很多API组成,DirectX并不是一个单纯的API ,它并不支持Windows以外的平台,所以不是跨平台框架,按照性质分类可以分为四大部分,显示部分、声音部分、输入部分和网络部分

    • Metal :是Apple为了解决3D渲染而退出的框架。该框架能够为3D图像提高10倍的渲染性能, 苹果底层渲染是由Metal来实现的(笔者14年做过AR开发 当时所用SDK 为metaio公司开发的metaioSDK 后 metaio公司被苹果收购 推测Metal ARkit 由此演变而来)

    • OpenGL和OpenGL ES 的区别是什么?(OpenGL ES 只是比OpenGL 减少了一部分子集)

    图形API目的是解决什么问题 ?

    简单来说就是实现图形的底层渲染 
    a、比如在游戏开发中,对于游戏场景/游戏人物的渲染
    b、比如音视频开发中,对于视频解码后的数据渲染
    c、比如在地图引擎对于地图上的数据渲染
    d、比如在动画中,实现动画的绘制
    e、比如在视频处理中,对于视频加上滤镜效果
    

    OpenGL/OpenGL ES /Metal在任何项目中解决问题的本质就是利用GPU来搞笑渲染图形图像。图形API是开发者唯一接近GPU的方式

    OpenGL 专业名词解析

    OpenGL 上下文(context)
    • 在应用程序调用任何OpenGL的指令之前,需要首先创建一个OpenGL 的上下文 。这个上下文是一个非常庞大的状态机。保存了OpenGL中的各种状态,这也是OpenGL 指令执行的基础
    • OpenGL 的函数不管在哪个语言中,都是类似C语言一样的面向过程的函数,本质上都是对Open GL 上下文这个庞大的状态机中的某个状态或者对象进行操作 当然,首先你得吧这个对象设置为当前对象。因此,通过对OpenGL 的指令封装。是可以将OpenGL 的相关调用封装成为一个面向对象的图形API的
    • 由于OpenGL 上下文是一个巨大的状态机,切换上下文往往会产生较大的开销。但是不同的绘制模块,可能需要使用完全独立的状态管理。因此,可以在应用程序中分别创建多个不同的上下文,在不同的线程中使用不同的上下文,上下文之间共享纹理、缓冲区等资源。这样的方案,会比反复切换上下文,或者大量修改渲染状态,更加的合理高效
    OpenGL 状态机
    • 状态机是理论上的一种机器。它描述了一个对象在其生命周期内所经历的各种状态,状态间的转变,发生转变的动因,条件及转变中所执行的活动,来说明对象在其生命周期中响应事件所经历的状态序列以及对那些状态事件的响应。
    • 状态机具有以下特点:
        * 有记忆功能,能记住当前的状态
        * 可以接收输入,根据输入的内容和自己的原先状态,修改自己当前状态。并且可以有对应输出
        * 当进入特殊状态(停机状态)的时候,便不再接收输入,停止工作
    
    状态机和上下文的理解:
    可以这样理解吧 
    就比如说 我写了一本小说 
    小说里面有一个人物  
    我要描述这个人物
    我就离不开这个小说 
    然后我需要人物做什么事情
    肯定就只能在这本小说里面去执行  
    而且小说里面记录的这个人物做了什么事情  
    这个人物有什么性格
    有什么状态
    其实也就是说这个小说就是一个状态机  
    也可以说小说其实就是上下文
    
    渲染
    计算机将存储在内存中的形状转换成实际绘制在屏幕上的对应的过程
    
    顶点数组(VertexArray)和顶点缓冲区(VertexBuffer)
    * 画图一般是先画好图像的骨架,然后再往骨架里填充颜色,这对于OpenGL 也是一样的。顶点数据就是要画的图像的骨架,和现实中不同的是,OpenGL中的图像都是由图元组成,在OpenGL ES中,有3种类型的图元:点、线、三角形。那这些顶点数据最终是存储在哪里的呢?开发者可以选择设定函数指针,在调用绘制方法的时候,直接由内存传入顶点数据,也就是说这部分数据之前是存储在内存当中的,被称为顶点数组。而性能更高的做法是,提前分配一块显存,将顶点的数据预先传入到显存当中。这部分的显存,就被称为顶点缓冲区
    * 顶点指的是我们在绘制一个图形时,它的顶点位置数据,而这个数据可以直接存储在数组中或者将其缓存到GPU内存中 所以顶点数据是由GPU处理的
    
    管线

    在OpenGL下渲染图形就会经历一个一个节点,而这样的操作可以理解为管线。类似于流水线 每个任务严格按照既定顺序依次执行。就像水从一根管子的一端流到另一端,这个顺序是不能打破的。

    固定管线/存储着色器

    在早期的Open GL版本,它封装了很多种着色器程序块内置的一段包含了光照,坐标变换、裁剪等等诸多功能的固定shader程序来完成,来帮助开发者来完成图形的渲染。而开发者只需要传入相应的参数,就能快速完成图形的渲染。类似于iOS会封装很多API 而我们只需要调用,就可以实现功能。不需要关注底层实现原理
    但是由于OpenGL 的使用场景非常丰富,固定管线或存储着色器无法完成每一个业务,这时将相关部分开放成可编程 这叫做可编程管线

    光栅化

    光栅化就是将数据转化成可见像素的过程 具有将图转化为一个个栅格组成的图像的作用 特点是每个元素对应帧缓冲区中的一个像素

    什么是GPU 图形渲染流水线(Pipeline)
    opengl-graphics-pipeline.png

    程序按照固定的顺序执行,且不能更改顺序,称为管线,这个翻译非常不友好,不好理解,容易有歧义,叫流程、流水线更好。
    GPU 图形渲染流水线的具体实现可分为六个阶段,如下图所示。

    顶点着色器(Vertex Shader)
    形状装配(Shape Assembly),又称 图元装配
    几何着色器(Geometry Shader)
    光栅化(Rasterization)
    片段着色器(Fragment Shader),又称 片元着色器
    测试与混合(Tests and Blending)
    帧缓冲区(Framebuffer)

    第一阶段:顶点着色器。该阶段的输入是 顶点数据(Vertex Data) 数据,比如以数组的形式传递 3 个 3D 坐标用来表示一个三角形。顶点数据是一系列顶点的集合。
    第二阶段:图元生成。该阶段将顶点着色器输出的所有顶点作为输入,并将所有的点装配成指定图元的形状。图中则是一个三角形。图元(Primitive) 用于表示如何渲染顶点数据,如:点、线、三角形。
    第三阶段:几何着色器。该 新顶点构造出新的(或是其它的)图元来生成其他形状。例子中,它生成了另一个三角形。
    第四阶段:光栅化。该阶段会把图元映射为最终屏幕上相应的像素,生成片段。片段(Fragment) 是渲染一个像素所需要的所有数据。
    第五阶段:片段着色器。该阶段首先会对输入的片段进行 裁切(Clipping)。裁切会丢弃超出视图以外的所有像素,用来提升执行效率。
    第六阶段:测试与混合。该阶段会检测片段的对应的深度值(z 坐标),判断这个像素位于其它物体的前面还是后面,决定是否应该丢弃。此外,该阶段还会检查 alpha 值( alpha 值定义了一个物体的透明度),从而对物体进行混合。因此,即使在片段着色器中计算出来了一个像素输出的颜色,在渲染多个三角形的时候最后的像素颜色也可能完全不同。
    最后阶段,帧缓冲区(未在图中标明)。是由像素组成的二维数组,每一个存储单元对应屏幕上的一个像素,整个帧缓冲对应一帧图像即当前屏幕画面。帧缓冲通常包括:颜色缓冲,深度缓冲,模板缓冲和累积缓冲。这些缓冲区可能是在一块内存区域,也可能单独分开。

    什么是着色器(Shader)
    着色器.png
    着色器

    想象一下给方块上色,画阴影,画线条。上色、画图的这个工具叫着色器。

    在OpenGL中的着色器可以着很多东西,比如这三个
    • 二维着色器
      二维着色器处理的是数字图像,也叫纹理,着色器可以修改它们的像素。

    • 像素着色器
      像素着色器(英语:pixel shader)也叫片段着色器(英语:fragment shader),用于计算“片段”的颜色和其它属性,此处的“片段”通常是指单独的像素。最简单的像素着色器只有输出颜色值;复杂的像素着色器可以有多个输入输出。像素着色器既可以永远输出同一个颜色,也可以考虑光照、做凹凸贴图、生成阴影和高光,还可以实现半透明等效果。像素着色器还可以修改片段的深度,也可以为多个渲染目标输出多个颜色。
      像素着色器还可以处理管线中间过程中的任何二维图像,包括精灵和纹理。因此,如果需要在栅格化后进行后期处理,像素着色器是唯一选择。

    • 三维着色器
      三维着色器处理的是三维模型或者其它几何体,可以访问用来绘制模型的颜色和纹理。

    下面几种都属于三维着色器
    * 顶点着色器(VertexShader)
    

    顶点着色器是最早的三维着色器,顶点着色器处理每一个顶点,将顶点坐标投影在屏幕上,即计算顶点的二维坐标,同时还可以计算深度坐标。
    一般用于处理每个顶点变换(旋转/平移/投影等)
    * 几何着色器
    几何着色器可以在着色器中生成新的顶点;
    * 细分曲面着色器
    细分曲面着色器(英语:tessellation shader)则可以向一组顶点中添加细节。这些着色器都会被安排在流水线(管线)中的。

    纹理

    纹理,简单的理解就是一副图像。而把一副图像映射到图形上的过程,叫做纹理映射。

    混合

    在OpenGL中,物体透明技术通常被叫做混合(Blending)。透明是物体的混合色,这种颜色来自于不同浓度的自身颜色和它后面的物体颜色。
    什么是矩阵、变换矩阵、投影矩阵
    首先要明白什么是矩阵,然后要明白矩阵的变换,之后就会明白什么是投影矩阵。

    矩阵

    下图就是矩阵,是初中二年级学的内容,图中包含三个坐标xyz。

    矩阵.png
    A:1,0,5
    B:0,-1,2
    C:0,0,1
    
    矩阵变换
    矩阵变换.png
    矩阵变换即是矩阵和矩阵的计算,比如加减乘除等。
    计算结果后得到一个新的矩阵。
    
    投影矩阵

    也就是很多矩阵在一起被计算成投影到屏幕的坐标。

    实际上是将要绘制的对象带入到了不同的坐标系中。我们注意到有这样几个坐标系:

    • 模型坐标系:主要用以定义描述绘制对象;

    • 世界坐标系:将要绘制的对象放置到世界坐标系中。所有的绘制对象需要一个共同的坐标系来决定对象之间的相对位置。正如一个杯子的坐标,只是用来描述杯子本身的形体,我们还需要把它们放到世界空间中,在它的旁边,可能还有茶壶、桌子等等。

    • 视坐标:也叫照相机坐标系,你可以想象我们在那个方向、那个位置放置了一个照相机,也可以说,那是我们眼睛的位置。

    • 裁剪坐标系:将区域进行裁剪,有些东西可能在视线之外,就需要裁掉;

    • 归一化坐标系:OpenGL 认为它所绘制的区域是一个正方形,每个方向上范围在[-1,1]之间。

    • 屏幕坐标系:或者说是窗口坐标系,就是将归一化坐标系投射到实际屏幕上。

    更加形象的过程,如下图所示:

    坐标变换流程.png
    渲染上屏/交换缓冲区
    离屏渲染/交换缓冲区.png

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

    什么是GLSL

    GLSL - OpenGL Shading Language 也称作 GLslang,是一个以C语言为基础的高阶着色语言。它是由 OpenGL ARB所建立,提供开发者对绘图管线更多的直接控制,而无需使用汇编语言或硬件规格语言。

    • GLSL 顶点着色器的简单范例
    void main(void){
        gl_Position = ftransform();
    }
    
    • GLSL 片断着色器的简单范例
    void main(void){
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
    

    OpenGL状态机

    程序跑起来后需要去修改、设置、添加各种不同的状态,使图像按照我们的想法显示出来。状态机中保存了对象的生命周期、响应事件、状态事件等等
    

    参考:
    http://chuquan.me/2018/08/26/graphics-rending-principle-gpu/

    https://blog.yuegs.com/2018/03/06/Android-opengl-matrix/

    相关文章

      网友评论

          本文标题:第二弹 OpenGL 快速理解 图形API(一)

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