一个3D图形是由一些小的基本元素(顶点,边,面,多边形)构成,每一个元素能够单独来操做。如图 1.一、图 1.二、图 1.3所示。程序员
图 1.1 顶点编程
图 1.2 边数据结构
图 1.3 面架构
图 1.4 传统渲染流程优化
如图 1.4所示,一个传统的渲染流程包括几何处理阶段(Geometry Stage)和光栅化阶段(Rasterization Stage)。spa
几何处理阶段又称为T&L(transforming & lighting)阶段,主要负责将三维坐标系中的顶点(vertex)转换成二维坐标系中的点(transforming阶段)、对顶点作初步光照计算(lighting阶段)。因为目前显示器只能以二维方式显示,因此要将各个点作坐标系的转换。如图 1.5所示,三维坐标系中的三个顶点根据观察的方向(screen position)投影到二维坐标系中,从而获得了这三个点的二维坐标。orm
图 1.5 坐标系转换图片
接着GPU根据程序规定好的这些点之间的关系,将这些点链接起来,这样一个物体就有了外形了,如图 1.六、图 1.7所示。ip
图 1.6 顶点生成工作流
图 1.7 多边形生成
完成上述工做后,接下来就要进入初步贴图(Vertex Texture)和初步光照计算(Vertex Lighting)阶段。如图 1.8所示:
图 1.8 初步贴图和打光阶段
通过几何阶段处理能够获得二维平面中的图像。可是要将这个二维图像在显示器上显示出来,还必需要将图像转换为一系列的片元(fragment),片元在接下来的处理中有可能变成最终图像中的像素。如图 1.九、图 1.10所示。
图 1.9 光栅化三角形
图 1.10 光栅化三角形并进行插值着色
一个片元就是一个数据结构,这个数据结构中包含位置、颜色、深度等信息。而后对这些片元进行贴图融合、光照计算、或者雾化等其余操做以造成最终图片中的像素。以后对这些像素作最后的缩放和抗锯齿处理,造成最终的图像,将这些图像数据输出到系统中的frambuffer就能在显示器上看到图像了。
在传统渲染流程中,人们对像素的操做实际上仅仅可以称之为染色,对特效的处理只能经过固定的单元来实现,每一代图形API所可以实现的特定的特效,都须要经过预先将其固化成固定指令的形式出如今硬件中。而对于像素的处理,也仅能局限与固化指令所可以容许的范围内,一旦像素进入pipeline,程序员就失去了对它的控制。为了解决这一局面,可编程着色器诞生了。如图 1.十二、图 1.13所示为固定pipeline和可编程pipeline渲染的球的对比。
图 1.12 固定pipeline渲染的几种球
图 1.13 可编程pipeline渲染下的球
图 1.14 可编程的渲染流程
如图 1.14所示,可编程渲染流程与传统渲染流程不一样的是,顶点着色器(Vertex Shader)和片元着色器(Fragment Shader)是可编程的。片断着色器在有的图形API中叫作像素着色器(Pixel Shader)。顶点着色器主要负责顶点的几何关系运算,像素着色器主要负责像素颜色计算等。
着色器是用来实现图像渲染的,用来代替固定pipeline的一段可编辑程序。Vertex Shader和Fragment Shader是彻底分离的两组程序,它们在GPU中拥有不一样的寄存器要求,不一样的指令格式以及不一样的运算器要求。Vertex Shader程序能够被GPU中的可编程顶点处理单元(Programmable Vertex Processor)处理,一样,Fragment Shader程序能够被GPU中的可编程片元处理单元(Programmable Fragment Processor)处理。
Vertex Shader程序和Fragment Shader程序都是着色程序(Shader Program)。用来编写着色程序的语言就被称为着色器语言(Shader Language)。目前主流的着色器语言有三种:基于OpenGL的GLSL(OpenGL Shading Language),基于Direct3D的HLSL(High Level Shading Language),还有Nvidia的Cg(C for Graphic)语言。
在传统的硬件中,GPU厂商使用固定比例的Vertex Shader单元和Fragment Shader单元,好比经典的1:3黄金渲染架构,即Vertex Shader单元和Fragment Shader单元比例为1:3。这种固定比例的作法有时会致使严重的单元利用率低问题。好比一段着色程序中仅包含10%的Vertex Shader指令,剩下的90%都是Fragment Shader指令,那么当Fragment Shader单元在全力运行的时候Vertex Shader是处于空闲的状态,反之亦然。而一段实际的着色程序不可能彻底按照硬件的的Shader比例来作到指令密度的平均优化。如图 1.15所示,上部分表示顶点着色单元满负荷运行像素着色单元空闲的状况,下部分正好相反。
图 1.15 Shader负载不均衡
为了解决这种状况,统一着色架构诞生了,统一架构将传统的Vertex Shader和Fragment Shader从软件和硬件层面上予以统一。着色程序内部再也不须要严格按照格式区分Vertex/Pixel。硬件上Shader单元也从过去的分离式固定功能变成了更增强大完整且统一的通用ALU。如图 1.1六、图 1.17
图 1.16 分离着色架构
图 1.17 统一着色架构
OpenGL ES 1.x版本是传统的固定pipeline渲染,而2.x版本日后是可编程着色pipeline渲染,如图 2.一、图 2.2所示。
图 2.1 OpenGL ES 1.x渲染流程
图 2.2 OpenGL ES 2.x渲染流程
如图 2.3所示,为imx6q中gpu在opengl es2下的渲染流程。
图 2.3 IMX6Q GPU工做流程