3D绘图一些基本概念
基本元素
一个3D图形是由一些小的基本元素(顶点,边,面,多边形)构成,每个元素可以单独来操作。如图 1.1、图 1.2、图 1.3所示。
图 1.1 顶点
图 1.2 边
图 1.3 面
传统渲染流程(pipeline)
图 1.4 传统渲染流程
如图 1.4所示,一个传统的渲染流程包括几何处理阶段(Geometry Stage)和光栅化阶段(Rasterization Stage)。
几何处理阶段
几何处理阶段又称为T&L(transforming & lighting)阶段,主要负责将三维坐标系中的顶点(vertex)转换成二维坐标系中的点(transforming阶段)、对顶点做初步光照计算(lighting阶段)。由于目前显示器只能以二维方式显示,所以要将各个点做坐标系的转换。如图 1.5所示,三维坐标系中的三个顶点根据观察的方向(screen position)投影到二维坐标系中,从而得到了这三个点的二维坐标。
图 1.5 坐标系转换
接着GPU根据程序规定好的这些点之间的关系,将这些点连接起来,这样一个物体就有了外形了,如图 1.6、图 1.7所示。
图 1.6 顶点生成
图 1.7 多边形生成
完成上述工作后,接下来就要进入初步贴图(Vertex Texture)和初步光照计算(Vertex Lighting)阶段。如图 1.8所示:
图 1.8 初步贴图和打光阶段
光栅化阶段
经过几何阶段处理可以得到二维平面中的图像。但是要将这个二维图像在显示器上显示出来,还必须要将图像转换为一系列的片元(fragment),片元在接下来的处理中有可能变成最终图像中的像素。如图 1.9、图 1.10所示。
图 1.9 光栅化三角形
图 1.10 光栅化三角形并进行插值着色
一个片元就是一个数据结构,这个数据结构中包含位置、颜色、深度等信息。然后对这些片元进行贴图融合、光照计算、或者雾化等其他操作以形成最终图片中的像素。之后对这些像素做最后的缩放和抗锯齿处理,形成最终的图像,将这些图像数据输出到系统中的frambuffer就能在显示器上看到图像了。
可编程着色器(Programmable Shader)
在传统渲染流程中,人们对像素的操作实际上仅仅能够称之为染色,对特效的处理只能通过固定的单元来实现,每一代图形API所能够实现的特定的特效,都需要通过预先将其固化成固定指令的形式出现在硬件中。而对于像素的处理,也仅能局限与固化指令所能够允许的范围内,一旦像素进入pipeline,程序员就失去了对它的控制。为了解决这一局面,可编程着色器诞生了。如图 1.12、图 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)语言。
统一着色器架构(Unfied Shader Architecture)
在传统的硬件中,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.16、图 1.17
图 1.16 分离着色架构
图 1.17 统一着色架构
IMX6Q基于OpenGL ES下的渲染流程
OpenGL ES渲染流程
OpenGL ES 1.x版本是传统的固定pipeline渲染,而2.x版本往后是可编程着色pipeline渲染,如图 2.1、图 2.2所示。
图 2.1 OpenGL ES 1.x渲染流程
图 2.2 OpenGL ES 2.x渲染流程
基于OpenGL ES2下的IMX6Q GPU工作流程
如图 2.3所示,为imx6q中gpu在opengl es2下的渲染流程。
图 2.3 IMX6Q GPU工作流程
原文地址:http://blog.51cto.com/11080845/2062702