- 这一篇主要介绍CG代码,也就是shader最核心的代码,CGPROGRAM ENDCG 块,它是CG程序的开始和结束,比如说定点处理,着色处理,都在里面,下面就开始每一行解释:
- #pragma surface surf Standard fullforwardshadows
这是一个编译指令,这个编译指令有具体的格式,可以从Unity官方手册中了解一下有关的内容,其格式为:
“#pragma surface surfaceFunction lightModel [optionalparams]。”- #pragma:是一个关键字,声明的作用。
- surface:表示声明一个表面着色器,作用是声明一个什么类型的着色的,可以写成#pragma vertex 顶点着色器,#pragma fragment 片段着色器、
- surfaceFunction:这就很好理解了,代表着色器的方法名称,比如说surface默认为surf、vertex定点默认为vert、fragment片段默认为frag,最好还是用官方的吧。
- lightModel:光照模型,Standard 是一个光照模型函数,unity内置的还有Lambert(漫反射),Phone、BlinnPhong。
- [optionalparams]:表示其他的一些选项,比如上面代码中的Standard fullforwardshadows,表示使用standard光照模型的fullforwardshadows功能。看的出来这是一个阴影的功能,他还可以写成Standard addshadow。这都是unity内置的,具体怎么用可以自己查资料,楼主现目前也不知道啊(还在学习中)。
- #pragma target 3.0:表示我们将要对这个着色器使用硬件的“shader model 3.0”的能力,硬件的“shader model”是硬件一个用于着色处理的基础的指令范围和能力,值越高表示能使用越高级的功能,如果没有使用“#pragma target 3.0”这句指令,默认使用的是“shader model 2.0”。
- sampler2D _MainTex:这个东西和Properties属性里面的2D类型对应,在CG中,sampler2D就是和texture2D所绑定的一个数据容器接口,然后在我们的CG代码块,如果要使用外部传入的_MainTex贴图,那么就需要在CG代码块里面定义一次。
- #include “Lighting.cginc”:这是包含文件,主要是方便我们编写shader,内置了很多方法。下面还有一些包含文件:
- Ligghting.cginc 包含了各种内置光照模型,如果编写SurfaceShader的话,会被自动包含进来
- UnityCG.cginc 包含最常用的帮助函数(三角函数计算、弧度、角度,顶点位置等函数)、宏和结构体。
- UnityShaderVariables.cginc:在编译UnityShader时,会被自动包含进来。包含了许多内置的全局变量,如UNITY_MATRIX_MVP等
- HLSLSupport.cginc:在编译UnityShader时,会自动包含进来。声明了很多用于跨平台编译的宏和定义
- struct Input 字面意思,这是一个输入的结构体,用来干啥,这就要结合刚刚定义的surf表面着色器的函数了,这个函数是CG规定的,所以参数是不能变的,我们得按照它得来:void surf (Input IN, inout SurfaceOutputStandard o),第一个是input输入参数,第二个是inout输出参数,其中输入参数的结构我们可以自定义,输出的SurfaceOutputStandard就是unity规定的,如下:
- struct SurfaceOutput {
**half3 Albedo; // 该像素的反射率,反应了像素的基色
half3 Normal; // 该像素的法线方向
half3 Emission; // 该像素的自发光颜色,使得即便没有光照也可以物体本身也可以发出光
half Specular; // 该像素的高光指数
half Gloss; // 该像素的高光光滑度,值越大高光反射越清晰,反之越模糊
half Alpha; // 该像素的不透明度
};
- struct SurfaceOutput {
- 这里面的:float2 uv_MainTex指的是什么呢,首先float是个数据类型,比如:half , fixed4,float2 :这些就是数据类型,这里做了详细说明CG中的数据类型
- 接着,如果你对3D开发稍有耳闻的话,一定不会对uv这两个字母感到陌生。UV mapping的作用是将一个2D贴图上的点按照一定规则映射到3D模型上,是3D渲染中最常见的一种顶点处理手段。在CG程序中,我们有这样的约定,在一个贴图变量(在我们例子中是_MainTex)之前加上uv两个字母,就代表提取它的uv值(其实就是两个代表贴图上点的二维坐标 )。我们之后就可以在surf程序中直接通过访问uv_MainTex来取得这张贴图当前需要计算的点的坐标值了。
- 看到这里就只有一步之遥了,最后的surf函数,在计算输出时Shader会多次调用surf函数,每次给入一个贴图上的点坐标,来计算输出。
- 这里用到了一个tex2d函数,这是CG程序中用来在一张贴图中对一个点进行采样的方法,返回一个float4。这里对_MainTex在输入点上进行了采样,并将其颜色的rbg值赋予了输出的像素颜色,将a值赋予透明度。于是,着色器就明白了应当怎样工作:即找到贴图上对应的uv点,直接使用颜色信息来进行着色。(未完待续。。)。
- #pragma surface surf Standard fullforwardshadows
- FallBack "Diffuse" 遍历所有的subshader,这块显卡都不支持时,用于回滚到一指定的shader,如“Diffuse”。
其实FallBack还有一个作用,就是影响阴影的投射,unity会在本shader中找一个阴影投射pass,这当然这并不需要我们去实现这个pass,如果你设置了FallBack,那么FallBack会使用unity内置的一个通用阴影pass,所以设置FallBack的设置是很重要的。