Unity中的Shader学习(三)——Vertex/Fragment Shader

Vertex/Fragment Shader 流程图

作为Unity着色器系列课程的入门,这篇主要介绍的是顶点/片元着色器,因为它是一切的基础。下面我们就具体拆解这个Shader的实现流程。

第一步:数据引入



在世界三维空间中,一开始传入Shader处理的数据其实就是网格数据(Mesh Data)。
在演示应用按T键,切换到下面的画面效果。



但是一般情况下,光是网格数据不能满足我们处理画面的需求,这时就需要引入一些常数属性数据(Properties)。点击打开“常数属性数据”窗口。



这些“属性”就是Shader的变量,可以有资源(Assets)、脚本(Scripts)和动画数据(Animation Data)来驱动表现效果,甚至是粒子系统(Particle System)也能作用(详见《Unity粒子遇上着色器》),而这些数据可在顶点(Vertex)函数和片元(Fragment)函数中使用。

属性的声明规则如下:
_Name(“Display Name”, type) = defaultValue[{options}]

1._Name 是属性的名字,也就是变量名,在之后整个Shader代码中将使用这个名字来获取该属性的内容 ,切记要添加下划线。
2.Display Name 这个字符串将显示在Unity的Inspector中作为Shader的使用者可读的内容 ,即显示的名称。
3.type 属性的类型。常用的有这个几种:Color颜色,一般为RGBA的数组;2D纹理,宽高为2的幂次尺寸;Rect纹理,对应非2的幂次尺寸;Cube立方体,即6张2D纹理组成;Float和Range,都是浮点数,但是Range要求定义最大值和最小值,以Range(min,max)形式显示;Vector四维数。


4.defaultValue 默认值,与类型直接挂钩。一开始赋予该属性的初始值,但是在检视窗口中调整过属性值之后,不在有效。Color 以0~1定义的rgba颜色,比如(1,1,1,1);2D/Rect/Cube,对于纹理来说,默认值可以为一个代表默认tint颜色的字符串,可以是空字符串或者“white”,“black”等中的一个;Float和Range 为某个指定的浮点数;同样,Vector的是一个四维数值,写为(x,y,z,w)的形式。
5.Options 可选项,它只对2D,Rect或者Cube纹理有关,一般填入OpenGL中TexGen的模式,这篇的内容暂未涉及,就先以{}形式。

这样我们可以尝试解读上图中的那些属性声明的是什么了。比如_MainTex(“A Texture”, 2D) = “”{},就是声明了一个变量名为_MainTex的2次幂尺寸纹理,它在检视窗口中显示的名称是A Texture,默认是空的。

点击打开“网格数据”



Mesh网格如上图右边所示,它的数据需要组织成结构体(Struct)形式输入给顶点函数(Vertex Function)。而左边的就是输入结构体appdata,可以根据需要命名变量与类型,当然不能忘记添加冒号以及后面的语义。

语义是什么,语义(Semantics)是附加到着色器输入或输出的字符串,其传达关于参数的预期使用的信息。 对于在着色器级之间传递的所有变量,都需要语义。通常,在流水线级之间传递的数据是完全通用的,并且不被系统唯一地解释;允许任意语义没有特殊意义。 详细请看https://msdn.microsoft.com/en-us ... sktop/bb509647.aspx

将右边图片向上滑动:




如果要将网格数据直接渲染出来,我们应该可以看到像上图右边机器人顶点显示的效果。

第二步:顶点函数

点击“顶点函数”:



顶点函数是用来“构建”对象的,输入的是appdata,即组织好的网格数据。经过一定处理后,输出的将是顶点到片元结构体,即Vertex to Fragment,一般简称v2f。当然,这里的结构体与用于输入顶点函数的结构体都可以随便命名,只不过这里习惯以这种命名方式。

输入的顶点数据是需要从对象空间转换到屏幕空间,而顶点渲染到屏幕空间上就会以上图右边的情况显示出来。在Unity 5早期版本一般使用 mul(UNITY_MATRIX_MVP, IN.vertex)方式去处理,即 Model * View * Projection获得顶点对应到屏幕上的位置。但是这种方式效率不高,现在使用UnityObjectToClipPos函数方式直接处理顶点(vertex)信息。调用这个方法一般需要引入UnityCG.cginc预定义文件,通过#include “UnityCG.cginc”实现。向左滑动可以看到这个函数的具体实现方式。

第三步:顶点到片元结构体

点击“顶点到片元结构体”



这个结构体是中间数据,用于存储从顶点函数(Vertex Function)输出到片元函数(Fragment Function)输入的数据。这个结构体也可以添加其他的变量,比如normalAngle,calculatedLightingColor等。

向左滑动:



到这里你们应该会发现,用在Shader中的变量有些特殊,比如float就有float4,float3,float2等。数字就对应的维度数量,像float4代表这是一个四维的浮点数变量,对应的四个值可以分别对应X,Y,Z,W,或者是颜色值R,G,B,A。

再向左滑动:



浮点数也因精度的不同可以设置不同的变量。float是高精度的,一般为32位;half是中精度的,一般为16位;fixed是低精度的,一般为11位。在实际开发中,会根据性能需要选用合适的精度。比如颜色值RGBA,每个值域是0~1,而fixed值域是0~2,因此使用fixed4足够表现所有颜色值。

第四步:片元函数

点击“片元函数”:



片元函数(Fragment Function),通常用于将对象描绘到屏幕上,它输入的是v2f结构体数据,而输出的就是像素点。使用CG方法tex2D,输入参数纹理及UV坐标,就可以获得每个UV对应点的纹理的颜色。最后我们就可以看到如上图右边的机器人效果了。

猜你喜欢

转载自www.cnblogs.com/dongzee/p/9002588.html