iOS OpenGL开发(三)- OpenGL渲染架构解析

756 阅读5分钟

OpenGL

前言

前两篇文章中给大家解析过了什么是OpenGL的一些常用名词,掌握一些常用的名词,可以更加方便我们后面的学习和理解,也方便我们后面在遇到之后更加容易去查找。然后讲了着色器的渲染流程,我们基本上把大致是怎么玩儿的也弄清楚了。那么这一片文章就从OpenGL的渲染架构开始,带大家聊了解一下OpenGL的渲染架构到底是怎么组成的。

OpenGL渲染架构

首先我们来看一张架构图:

着色器渲染架构图
解释一下什么叫做客户端,什么叫做服务端

  • 客户端:我们编写的代码,或者是说调用的OpenGL的API,客户端是存储在CPU存储器中的,并且在应用程序中执行,或者再主系统内存的驱动程序中执行。
  • 服务端:就是计算机图形硬件厂商所提供的OpenGL的实现。我们编写的GLSL代码也是在服务端去运行的,简单来说就是操作的GPU。

服务端和客户端在功能上是异步的,也就是说他们是各自独立的软件块或者硬件块,或者软硬件都有,为了获得最佳的性能,我们希望两方面都尽可能不停地工作。客户端不断地将数据块和命令块组合到一起送到缓冲区,然后这些缓冲区会发送到服务端执行。服务端将执行这些缓冲区的内容,与此同时客户端又做好了发送下一个用于渲染的数据或者信息的准备,如果服务端停止工作等待客户端,或者客户端停止了工作来等待服务端做好接受更多命令和数据的准备,我们就把这情况称为管线停滞

从上面的图,我们也能看出。客户端只会向服务端传递三种数据,分别是:

1、属性值(Attributes)

  • 就是一个对每个顶点都要做改变的数据元素。实际上,顶点位置本身就是一个属性。属性值可以使浮点数、整数或布尔数据。
  • 属性总是以四维向量的形式进行内部存储的,即使我们不会使用到所有4个分量。例如,一个顶点位置可能存储为一个x值,一个y值和一个z值,将占用4个分量中的3个。OpenGL会将第4个(w分量)设为1。实际上,如果我们在二维平面上面绘图的话,那么第3个分量就会自动设为0,第4个分量依旧设为1。
  • 属性会从本地客户端内存中复制存储在图形硬件中的一个缓冲区上。这些属性只供顶点着色器使用,对于片元着色器来说没有意义。
  • 这些属性对每个顶点都要做改变,并不意味着他们的值不能重复,而只是说明每个顶点都有一个实际存储值。当然,通常情况下他们都是不同的,但是也有可能会与整个数组都是同一个值得情况。但是这种情况很浪费。

2、Uniform值

  • Uniforms值本质上跟属性一样,但是跟属性值不同的是,顶点着色器和片元着色器中都可以有Uniform变量。
  • 所谓属性就是一个对每个顶点都要做改变的数据元素。实际上,顶点位置本身就是一个属性。属性是不变的。
  • 我们通常设置完Uniform变量就紧接着发出渲染一个图元批次的命令。Uniform实际上可以无次数限制的使用,我们可以设置一个应用于整个表面的单个颜色值,还可以设置一个时间值,在每次渲染某种类型的顶点动画时修改它。
  • Uniform变量一个常见的应用是在顶点渲染中设置变换矩阵。

3、纹理数据(Texture Data)

  • 从顶点着色器和片元着色器中都可以对纹理值进行采样和筛选。典型情况下,片元着色器对一个纹理进行采样,并在一个三角形的表面上应用图形数据,但是,纹理数据的作用并不仅仅是表现图形。很多图形文件格式都是以无符号字节形式对颜色分量进行存储的,但是我们仍然可以设置浮点纹理。
  • 任何大型浮点数据块(例如消耗资源很大的函数的大型查询表)都可以通过这种方式传递给着色器。

步骤: 1、三个值都可以通过三个通道分别传到顶点着色器中,顶点着色器处理从客户机输入的数据、应用变换、进行其他的类型的数学运算来计算关照效果、位移、颜色值等等。(为了渲染共有3个顶点的三角形,顶点着色器将执行3次,也就是为了每个顶点执行一次)在目前的硬件上有多个执行单元同时运行,就意味着所有的3个顶点可以同时进行处理; 2、顶点着色器处理完成之后,就会经过图元合成,将顶点组合在一起变成图元,然后裁剪、转换窗口坐标、进行光栅化; 3、接着将数据输入到片元着色器,计算片元最终颜色以及深度,然后传递到片元测试模块以及混合模块,由片元着色器输出我们将屏幕上看到的最终颜色值。

注意:

  • Attributes属性值是不能直接传递给片元着色器的,只能通过顶点着色器去传递。但是Uniforms和纹理数据是可以的。