#Unity shader学前准备之CG语言(1)

       学习Unity shaderlab的时候,总有种力不从心的感觉,到处百度到处翻资料,其实我突然觉悟,是自己shader语言没有学好,基础不牢,地动山摇。所以,我准备真的粗略学习一下CG语言,并把大量心得搬运至此(也许绝大部分内容都是抄书)。
       我的参考书是半山工作室的康玉之先生所写的《GPU 编程与 CG 语言之阳春白雪下里巴人》,虽然有些老,但目的是为了入门CG语言,并在U3D shaderlab中使用,在此也要对康玉之老师做出感谢。

##GPU历史概述        其实一开始让我写概述,我是拒绝的,因为概述这东西本来也没啥人看,而且GPU历史和CG语言无关,而且差不多各路硬件发烧友应该都有所了解,康先生主要介绍了2009年以前的GPU历史,我推荐zol在线2013年有一系列文章,视觉时代的回响 GPU十年历史追忆,介绍了2003年到2013年的历史,如果只看看这些年有影响力的芯片架构,我觉得还是可以的,链接如下:

视觉时代的回响 GPU十年历史追忆(上)

视觉时代的回响 GPU十年历史追忆(中)

视觉时代的回响 GPU十年历史追忆(下)

视觉时代的回响 GPU十年历史追忆完结篇

视觉时代的回响 GPU十年历史追忆拾遗篇

       我先纠正一下他这一系列文章中的一些错误,首先这个人应该是个N粉,NV亏损完全是为了技术架构铺路,而ATI/AMD就算盈利也是技术错误前提下迎合市场的结果。
       首先,图形API并非只有directX一种,openGL,SDL(底层还是dx+openGL)都是非常不错的图形API,他自己也提到了java的图形API。directX也不仅仅是图形API,directX的核心部分direct3D是3D图形API,除此之外还有direct2D,音频,网络,窗体控制等众多功能,可以粗略的认为功能上,directX=openGL+openAL+socket+TK。
       就算图形卡的主要客户都只计算windows用户了,但也要考虑到那些openGL用户,openGL和direct3D的渲染管线(也可以说流程)是有区别的,当然随着图形API发展,两者越来越接近,如openGL2.0和dx9,openGL4.3和dx11,而在GDC2015上的两位主角vulkan(原来叫GL next)和dx12更是直接使用了mantle的很多东西(也有说法是全部,嘛,反正只有微软和AMD知道了)。但接近只是接近,不同还是不同的。流水线设计的十分接近dx的渲染流程(流水线的相关只是可以去看一下计算机组成原理中的CPU指令流水线),也就意味openGL那边照顾就要少一些,相信mantle这个AMD量身定制的API表现已经不用多说了,最保险的方法,就算都是相对灵活的可变设计,而这种设计还有一个优势,就是通用计算。全部可编程的设计,应该已经是A/N两家的在桌面级服务器的发展方向,相反,在移动方向,更要贴近图形API(比如苹果的A7芯片和metal,sony PS3中的cell和libgcm)。
       然后是他对于dx10的一些说法,dx10的设计非常激进而且先进,而且DX10和DX9微软非常风险的第一次让DX不能向下兼容。稍微有点shader model和hlsl学习经验的人应该都知道,DX11倒是能部分向下兼容DX10。DX10一直活不起来,或者说他认为的那个GPU黑暗时代,个人认为问题来自微软没错,但不是DX10的问题,而是windows Vista的问题,vista设计上个人认为没有问题,相反,还超越时代,硬件需求的过于超前导致市场不叫座,没人有DX10,又谈何发展。
       然后是我个人对于他所说的那个黑暗时代的质疑,那个时代,恰恰是PS3和Xbox360走进人们视野的时代,新的光影技术,更好的即时渲染引擎,物理引擎改进,现代游戏引擎完善,建模软件改进,那是游戏业腾飞的时代,PC画面水平完全落伍于主机的一个时代,那个时代只能说桌面平台不给力,并不能说图形技术不进步。

##GPU图形绘制管线

       图形绘制管线描述 GPU渲染流程,即“给定视点、三维物体、光源、照明模式,和纹理等元素,如何绘制一幅二维图像”。本章内容涉及 GPU 的基本流程和 实时绘制技术的根本原理,在这些知识点之上才能延伸发展出基于 GPU 的各项 技术,所以本章的重要性怎么说都不为过。欲登高而穷目,勿筑台于浮沙!
       在《实时计算机图形学》一书中,将图形绘制管线分为三个主要阶段:应用程序阶段、几何阶段、光栅阶段。

  1. 应用程序阶段,使用高级编程语言(C、C++、JAVA 等)进行开发,主要和CPU、内存打交道,诸如碰撞检测、场景图建立、空间八叉树更新、视锥裁剪等经典算法都在此阶段执行。在该阶段的末端,几何体数据(顶点坐标、法向量、纹理坐标、纹理等)通过数据总线传送到图形硬件(时间瓶颈);数据总线是一个可以共享的通道,用于在多个设备之间传送数据;端口是在两个设备之间传送 数据的通道;带宽用来描述端口或者总线上的吞吐量,可以用每秒字节(b/s) 来度量,数据总线和端口(如加速图形端口,Accelerated Graphic Port,AGP)将不同的功能模块“粘接”在一起。由于端口和数据总线均具有数据传输能力,因此通常也将端口认为是数据总线(实时计算机图形学 387 页)。
  2. 几何阶段,主要负责顶点坐标变换、光照、裁剪、投影以及屏幕映射(实时计算机图形学234页),该阶段基于GPU进行运算,在该阶段的末端得到了经过变换和投影之后的顶点坐标、颜色、以及纹理坐标(实时计算机图形学 10 页)。
  3. 光栅阶段,基于几何阶段的输出数据,为像素(Pixel)正确配色,以便绘制完整图像,该阶段进行的都是单个像素的操作,每个像素的信息存储在颜色缓冲 器(color buffer 或者 frame buffer)中。

    值得注意的是:光照计算属于几何阶段,因为光照计算涉及视点、光源和物体的世界坐标,所以通常放在世界坐标系中进行计算;而雾化以及涉及物体透明度的计算属于光栅化阶段,因为上述两种计算都需要深度值信息(Z 值),而深度值是在几何阶段中计算,并传递到光栅阶段的。

GPU 处理流程

GPU 处理流程

###Z buffer与Z值        Z buffer 应该是大家最为熟悉的缓冲区类型,又称为 depth buffer,即深度缓 冲区,其中存放的是视点到每个像素所对应的空间点的距离衡量,称之为 Z 值或者深度值。可见物体的 Z 值范围位于【0,1】区间,默认情况下,最接近眼睛的顶点(近裁减面上)其 Z 值为 0.0,离眼睛最远的顶点(远裁减面上)其 Z 值为 1.0。使用 z buffer可以用来判断空间点的遮挡关系,著名的深度缓冲区算 法(depth-buffer method,又称 Z缓冲区算法)就是对投影平面上每个像素所对 应的 Z 值进行比较的。

       GPU中对Z值的计算公式描述为: