0%

OpenGL名词解释

为了更好的学习 OpenGL,我们需要对部分专业属于有一些基本认识,本文介绍在计算机图形学常用的一些专业名词

图形API

OpenGL(Open Graphics Library)是⼀个跨编程语⾔、跨平台的编程图形程序接⼝,它将计算机的资源抽象称为⼀个OpenGL的对象,对这些资源的操作抽象为⼀个个的OpenGL指令

OpenGL ES(OpenGL for Embedded Systems)是OpenGL的API子集,针对⼿机、PDA和游戏主机等嵌⼊式设备⽽设计,去除了许多不必要和性能较低的API接⼝

DirectX是Windows平台的多媒体处理工具,包含图形API,功能比较多,按性质分类,可以分为四⼤部分,显示部分、声⾳部分、输⼊部分和⽹络部分

Metal是Apple为游戏开发者推出了新的平台技术,苹果宣称该技术能够为 3D 图像提⾼ 10 倍的渲染性能,是Apple为了解决3D渲染⽽推出的框架

图形API的作用

图形API用于实现图形的底层渲染,最终输出到显示屏上,例如,图形从点线面,再到3D图形,最终渲染称屏幕上看到的2D图像这个过程

  • ⽐如在游戏开发中,对于游戏场景/游戏⼈物的渲染
  • ⽐如在⾳视频开发中,对于视频解码后的数据渲染
  • ⽐如在地图引擎,对于地图上的数据渲染
  • ⽐如在动画中,实现动画的绘制
  • ⽐如在视频处理中,对于视频加上滤镜效果

OpenGL /OpenGL ES/ Metal 在任何项⽬中解决问题的本质就是利⽤GPU芯⽚来⾼效渲染图形图像,开发者可以通过这些图形API间接利用GPU

OpenGL只是协议层,而具体的实现是由硬件厂商完成的,不同厂商实现上有差异,通常都是高度优化过的

OpenGL上下⽂(Context)

在使用OpenGL操作之前,需要先创建一个OpenGL上下文,这是一个状态机,保存了各种用于描述OpenGL如何运行的状态,例如拍照的时候开启滤镜等,上下文是OpenGL所有操作的基础

  • OpenGL API是面向过程的,本质上是对OpenGL上下文状态机的某个状态或对象进行操作
  • 应用程序中可以创建多个不同的上下文,他们分别在各自的线程中使用。上下文之间共享纹理,缓冲区等资源,采用这中方案更为高效,因为它避免了反复切换上下文,或者大量修改渲染状态所造成的较大的开销。

iOS中的CoreGraphics里面的API就与OpenGL的API有些类似,面向过程

假设当我们想告诉OpenGL去画线段而不是三角形的时候,我们通过改变一些上下文变量来改变OpenGL状态,从而告诉OpenGL如何去绘图。一旦我们改变了OpenGL的状态为绘制线段,下一个绘制命令就会画出线段而不是三角形。

  • 上下文OpenGL指令执⾏的基础,所有绘制操作都需要通过上下文进行
  • OpenGL上下文对象切换操作开销大
  • OpenGL的函数虽然是面向过程的,但可以把相关的调用封装为面向过程的图形API。

OpenGL状态机

状态机描述了⼀个对象在其⽣命周期内的各种状态变化,和响应事件,体现在代码中就是上下文

  • 状态,能保存当前的状态
  • 输⼊输出,根据输⼊的内容和⾃⼰的原先状态,修改⾃⼰当前状态,并且可以有对应输出
  • 关闭,当进⼊特殊状态(停机状态)的时候,就不再接收输⼊,停⽌⼯作

渲染(Rendering)

将图形/图像数据转换成3D空间图像操作,从图元到图像的过程

图元

图元可以理解为组成图形的基本单元,比如点、线、三角形。 我们可以通过一系列函数或顶点数据帮助我们实现多种多样的图形

OpenGL ES有三种图元:线三角形,其他所有图形都是由这三种图形组合而成的

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

顶点数组用于描述图形的轮廓(如三个顶点可以描述一个三角形),图元是由顶点组成的,顶点数组通常存放在显存上(性能更高),而这部分内存称为顶点缓冲区

管线

在OpenGL下渲染图形,就会有经历⼀个⼀个节点步骤,⽽这样的操作可以理解管线。管线是⼀个抽象的概念,之所以称之为管线是因为显卡在处理数据的时候是按照⼀个固定的顺序来的,⽽且严格按照这个顺序。就像⽔从⼀根管⼦的⼀端流到另⼀端,这个顺序固定的不能修改

固定管线

在早期的OpenGL版本中,封装了很多API,用于完成特定的功能,例如光照,坐标变换,裁切等,这些API被称为固定管线,而对于一些特殊需求的场景,固定管线无法实现,这部分可以通过可编程管线来实现

固定管线在实际开发中用的少,大多已经废弃,基本都是通过编程来实现需求

着⾊器程序(Shader)

固定渲染管线架构变为可编程渲染管线

OpenGL在实际调⽤绘制函数之前,还需要指定⼀个由shader编译成的着⾊器程序。常⻅的着⾊器主要有

  • 顶点着⾊器(VertexShader)
  • ⽚段着⾊器/像素着⾊器(FragmentShader/PixelShader)
  • ⼏何着⾊器(GeometryShader)
  • 曲⾯细分着⾊器(TessellationShader)。

OpenGL ES只⽀持了顶点着⾊器⽚段着⾊器两个着⾊器

着色器程序处理流程

  1. OpenGL在处理shader时,和其他编译器⼀样。通过编译、链接等步骤,⽣成了着⾊器程序(glProgram),着⾊器程序同时包含了顶点着⾊器和⽚段着⾊器的运算逻辑
  2. 在OpenGL进⾏绘制的时候,⾸先由顶点着⾊器对传⼊的顶点数据进⾏运算。再通过图元装配,将顶点转换为图元
  3. 然后进⾏光栅化,将图元这种⽮量图形,转换为栅格化数据
  4. 将栅格化数据传⼊⽚段着⾊器中进⾏运算。⽚段着⾊器会对栅格化数据中的每⼀个像素进⾏运算,并决定像素的颜⾊

顶点着⾊器(VertexShader)

  • ⼀般⽤来处理图形每个顶点变换(旋转/平移/投影等),顶点坐标由⾃身坐标系转换到归⼀化坐标系的运算
  • 顶点着⾊器是OpenGL中⽤于计算顶点属性的程序。顶点着⾊器是逐顶点运算的程序,这个过程是并⾏的,并且顶点着⾊器运算过程中⽆法访问其他顶点的数据

过程

  1. 确定位置
  2. 缩放/平移/旋转位置换算
  3. 3D图形数据->2D(投影换算)

⽚段着⾊器/片元着色器(FragmentShader)

  • ⼀般⽤来处理图形中每个像素点颜⾊计算和填充
  • ⽚段着⾊器是OpenGL中⽤于计算⽚段(像素)颜⾊的程序。⽚段着⾊器是逐像素运算的程序,也就是说每个像素都会执⾏⼀次⽚段着⾊器,也是并⾏的

GLSL(OpenGL Shading Language)

GLSL是OpenGL着⾊语⾔,是⽤来在OpenGL中着⾊编程的语⾔,运行在GPU上,代替了固定的渲染管线的⼀部分,⽐如:视图转换、投影转换等。GLSL(GL Shading Language)的着⾊器代码分成2个部分:

  • Vertex Shader(顶点着⾊器)
  • Fragment Shader(⽚断着⾊器/片元着色器)

光栅化(Rasterization)

栅格化或者像素化,就是把矢量图形转化成像素点的过程,该过程包含了两部分的工作

  1. 决定窗口坐标中的哪些整型栅格区域被基本图元占用
  2. 分配一个颜色值和一个深度值到各个区域。光栅化过程产生的是片元。

纹理(Texture)

纹理可以理解为图⽚,在OpenGL习惯叫纹理

混合(Blending)

不同图层进行颜色混合,例如组透明度(例如将两个图层(透明度0.2的红色图层和透明度0.5的绿色图层)混合叠加在一起,这个过程就叫做混合),OpenGL提供的默认的混合算法混合算法,如果需要更加复杂的混合算法,⼀般可以通过像素着⾊器进⾏实现,当然性能会⽐原⽣的混合算法差⼀些

变换矩阵(Transformation)

用于对图形进行平移,缩放,旋转变换操作时使用

投影矩阵(Projection)

⽤于将3D坐标转换为⼆维屏幕坐标时使用

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

  1. 渲染缓冲区⼀般映射的是系统的资源⽐如窗⼝。如果将图像直接渲染到窗⼝对应的渲染缓冲区,则可以将图像显示到屏幕上。
  2. 但是,如果每个窗⼝只有⼀个缓冲区,那么在绘制过程中屏幕进⾏了刷新,窗⼝可能显示出不完整的图像,前后两次绘制重叠
  3. 为了解决这个问题,常规的OpenGL程序⾄少都会有两个缓冲区。显示在屏幕上的称为屏幕缓冲区,没有显示的称为离屏缓冲区。在⼀个缓冲区渲染完成之后,通过将屏幕缓冲区和离屏缓冲区交换,实现图像在屏幕上的显示,就是双缓冲
  4. 由于显示器的刷新⼀般是逐⾏进⾏的,因此为了防⽌交换缓冲区的时候屏幕上下区域的图像分属于两个不同的帧,因此交换⼀般会等待显示器刷新完成的信号,在显示器两次刷新的间隔中进⾏交换,这个信号就被称为垂直同步信号(VSync),这个技术被称为垂直同步
  5. 使⽤了双缓冲区和垂直同步技术之后,由于总是要等待缓冲区交换之后再进⾏下⼀帧的渲染,使得帧率⽆法完全达到硬件允许的最⾼⽔平。为了解决这个问题,引⼊了三缓冲区技术,在等待垂直同步时,来回交替渲染两个离屏的缓冲区,⽽垂直同步发⽣时,屏幕缓冲区和最近渲染完成的离屏缓冲区交换,实现充分利⽤硬件性能的⽬的