什么是Shader?
1.Shader的概念:
Shader,即着色器,是一种运行在GPU上的程序,用来对三维物体进行着色处理、光和影的计算、纹理颜色的呈现等,从而将一个个作为抽象的几何数据存在的模型、场景和特效,以近似于真实世界的光与影的形式呈现出来。(简单点的理解就是:利用GPU编程使得构件出来的对象近似于真实世界中的对象呈现出来的处理)通过Shader可以改变物体的形状、大小、位置以及旋转等。
2.Shader和Material的关系:
Shader负责将输入的Mesh(网格)以指定的方式和输入的贴图或者颜色等组合起来输出,绘图单元可以依据这个输出来将图像绘制在屏幕之上。输入的贴图或颜色,加上对应的Shader和Shader的特定参数设置,这些打包存储在一起就得到了一个Material。
3.以面向对象的思想理解Shader:
假设把Shader当做一个类,那么在对某个物体使用此Shader时,就需要实例化此Shader,得到一个对象,而Material就相当于是一个Shader的对象。
4.Shader的分类:
Shader的基础类型有两种:顶点Shader和片段Shader,它们的特点:
- 顶点Shader:具有可以处理、变换,最终会渲染到屏幕上的网格物体的顶点位置的功能,但它不能生成新的顶点;
- 片段Shader:会对一个片段(预备像素)进行各种测试,如Z深度测试、Alpha比较测试,能通过各种测试的片段,最终会被写入渲染的输出帧中,从而成为屏幕上的一个可见像素。
GPU编程和Shader的编程语言
1.GPU编程简介:
GPU——Programmable Graphics Processing Unit,即可编程图形处理单元,也成为可编程图形硬件,至于GPU上的编程,实质上就是GPU允许应用程序指定一个序列的指令进行顶点操作控制
2.Shader的编程语言:
GPU与CPU是截然不同的,这不仅仅再其硬件结构的差异上,这也就决定了在两者运行环境下的编程过程也是不同的。目前面向GPU的编程,有3种高级图像语言,分别是:
- 微软的 HLST (High Level Shading Language),是通过Direct3D图形软件库来写Shader程序的语言;
- OpenGL提供的 GLSL (OpenGL Shading Language)来写Shader程序;
- NVIDIA提供的 Cg (C for graphics)语言(以HLST为基础,很相似),兼容Direct3D和OpenGL图形接口;
考虑到最大化的跨平台支持,选择使用兼容性最高的 Cg 作为编写Shader的语言,但假如只针对Unity 3D引擎,也可以选择 GLSL。
如何使用Cg编写Shader:
在开始进行实际的编程之前,我们应该先清楚实现步骤,这就需要我们了解一下GPU进行图形绘制的操作步骤。
1.GPU图形绘制:
用图形绘制管线描述GPU渲染流程,即“给定视点、三维物体、光源、照明模式和纹理等元素,如何绘制一幅二维图像”。图像绘制其实分为三个阶段:应用程序阶段、几何阶段和光栅阶段:
- 应用程序阶段:使用高级语言(C、C++等)进行开发,主要和CPU、内存打交道,诸如:碰撞检测、场景图建立、空间八叉树更新、视锥裁剪等经典算法都在此阶段。在该阶段末端,几何体数据(顶点坐标、法向量、纹理等)通过数据总线传送给图形硬件。
- 几何阶段:主要负责顶点坐标变换、光照、裁剪、投影以及屏幕映射,该阶段基于GPU进行计算。在该阶段末端,得到经过变换和投影之后的顶点坐标、颜色、以及纹理坐标。
- 光栅阶段:基于几何阶段的输出数据,为像素(Pixel)正确配色,以便绘制完整图像,该阶段进行的都是单个像素的操作,每个像素的信息存储在颜色缓冲器(color buffer或者frame buffer)中。
(例如:光照计算属于几何阶段、雾化以及涉及物体透明度的计算属于光栅阶段、深度信息(Z值)的计算属于几何阶段并传递给光栅阶段。)
2.Unity中使用Cg写Shader:
基本步骤如下:
- 定义一些属性,用于指定此Shader将有哪些输入;
- 定义一个或者多个子着色器,每个着色器中包含一个或者多个Pass;
- 指定一个回滚,用于处理所有SubShader都不能运行的情况。