Unity5的Shader体系简析
1.标准表面着色器(Standard Surface Shader)模板源码解析在Unity中,我们若要实现新的表面着色器时,可以根据这个模板,进行一步添加子着色器和新的参数与特性。
这个Shader模板的脉络很清晰,先是定义一些属性,然后在SubShader中设置渲染模式,层次细节LOD的值,然后开启一个CG编程语言模块,写一些编译指令#pragma,声明一下变量让属性值在CG块中可见,定义输入结构,然后填充一下表面着色函数即可。注意:专门强调一句,SurfaceShader不能使用Pass,一使用就报错,我们直接在SubShader中实现和填充代码就可以了。
Standard Surface Shader模板详细注释的Shader代码如下:
//表面着色器 内部包含很多内置函数 计算 使用起来非常方便适合新手
Shader "Shader( 名字)/Volume8/Surface Shader模板"
{
//------------------------------------【属性值】------------------------------------
//添加需要shader需要属性
Properties
{
//主颜色
_Color("Color", Color) = (1,1,1,1)
//主纹理
_MainTex("Albedo (RGB)", 2D) = "white" {}
//光泽度
_Glossiness("Smoothness", Range(0,1)) = 0.5
//金属度
_Metallic("Metallic", Range(0,1)) = 0.0
}
//------------------------------------【子着色器】------------------------------------
SubShader
{
//【注意:Surface Shader不能使用Pass,直接在SubShader中实现即可】
//渲染类型设置:不透明 ()
Tags{"RenderType" = "Opaque" }
//细节层次设为:200
LOD200
//===========CG着色器语言编写模块===========
CGPROGRAM
//编译指令:告知编译器表明着色函数的名称为surf
//Standard表示光照模型为Unity标准版光照模型
//fullforwardshadows表示在正向渲染路径中支持所有阴影类型
#pragma surface surf Standard fullforwardshadows
//编译指令: 指定着色器编译目标为Shader Model 3.0
#pragma target 3.0
//变量的声明
sampler2D _MainTex;
//表面输入结构体
struct Input
{
float2 uv_MainTex;//纹理坐标
};
//变量的声明
half _Glossiness;
half _Metallic;
fixed4 _Color;
//--------------------------------【表面着色函数】-----------------------------
//输入:表面输入结构体
//输出:Unity内置的SurfaceOutputStandard结构体
//SurfaceOutputStandard原型如下:
/*
struct SurfaceOutputStandard
{
fixed3 Albedo; // 漫反射颜色
fixed3 Normal; // 切线空间法线
half3 Emission; //自发光
half Metallic; // 金属度;取0为非金属, 取1为金属
half Smoothness; // 光泽度;取0为非常粗糙, 取1为非常光滑
half Occlusion; // 遮挡(默认值为1)
fixed Alpha; // 透明度
};
*/
//-----
void surf(Input IN, inout SurfaceOutputStandard o)
{
//【1】漫反射颜色为主纹理对应的纹理坐标,并乘以主颜色
fixed4c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
//【2】将准备好的颜色的rgb分量作为漫反射颜色
o.Albedo= c.rgb;
//【3】金属度取自属性值
o.Metallic= _Metallic;
//【4】光泽度也取自属性值
o.Smoothness= _Glossiness;
//【5】将准备好的颜色的alpha分量作为Alpha分量值
o.Alpha= c.a;
}
//===========结束CG着色器语言编写模块===========
ENDCG
}
//备胎为漫反射
FallBack"Diffuse"
}
2.无灯光着色器(Unlit Shader)模板源码解析
Unlit Shader,简单来说,就是直接采用漫反射纹理,不考虑场景中的任何灯光效果。使用无灯光着色器的话,也就不能使用任何镜面或者法线效果了。Unlit系的Shader基本原理和其他Shader无异,但是计算量更小,更快速,更高效。
下面一起看一下Unity为我们提供的无灯光着色器模板的代码
Shader "无灯光着色器(Unlit Shader)模板"
{
//------------------------------------【属性值】------------------------------------
Properties
{
//主纹理
_MainTex("Texture", 2D) = "white" {}
}
//------------------------------------【子着色器】------------------------------------
SubShader
{
//渲染类型设置:不透明
Tags{ "RenderType"="Opaque" }
//细节层次设为:100
LOD 100
//--------------------------------唯一的通道-------------------------------
Pass
{
//Always: 总是渲染;没有光照模式。
//ForwardBase: 适用于前渲染、环境、主要方向灯、光/sh光和烘焙图。
//ForwardAdd: 适用于前渲染, 叠加每一盏灯,每一盏灯就多一个pass。
//Deferred: 延迟渲染,渲染g缓冲区 。
//ShadowCaster:将物体深度渲染到阴影贴图或者深度纹理上 。
//PrepassBase: 用于传统的延迟光照,渲染法线和高光效果。
//PrepassFinal:用于传统的延迟光照,通过结合文理、灯光、和法线来渲染最终的结果。
//Vertex:当对象不是光映射时,用于遗留顶点的渲染,所有顶点灯都被利用。
//VertexLMRGBM: 当对象被光映射时,在遗留的顶点上使用渲染,在LightMap是RGBM编码的平台上(pc和控制台)。
//VertexLM: 当对象被光映射时,在遗留的顶点上使用渲染,在LightMap是双idr编码的(移动平台)平台上。
//===========开启CG着色器语言编写模块===========
CGPROGRAM
//编译指令:告知编译器顶点和片段着色函数的名称
#pragma vertex vert
#pragma fragment frag
//着色器变体快捷编译指令:雾效。编译出几个不同的Shader变体来处理不同类型的雾效(关闭/线性/指数/二阶指数)
#pragma multi_compile_fog
//衰减与阴影的实现
#include "AutoLight.cginc"//
//fwdadd:ForwardBase的阴影显示,在下面的ForwardAdd里得用fwdadd; 必须结合fallback,两者缺一不可
//包含头文件
#include"UnityCG.cginc"
//顶点着色器输入结构
struct appdata
{
float4 vertex : POSITION;//顶点位置
float2 uv : TEXCOORD0;//纹理坐标
};
//顶点着色器输出结构
struct v2f
{
float2 uv : TEXCOORD0;//纹理坐标
UNITY_FOG_COORDS(1)//雾
float4 vertex : SV_POSITION;//像素位置
LIGHTING_COORDS(3,4)//#include "AutoLight.cginc"
};
//变量声明
sampler2D _MainTex;
float4 _MainTex_ST;
//--------------------------------【顶点着色函数】-----------------------------
//输入:顶点输入结构体
//输出:顶点输出结构体
//---------------------------------------------------------------------------------
v2f vert (appdata v)
{
//【1】实例化一个输入结构体
v2f o;
//【2】填充此输出结构
//输出的顶点位置(像素位置)为模型视图投影矩阵乘以顶点位置,也就是将三维空间中的坐标投影到了二维窗口
o.vertex= mul(UNITY_MATRIX_MVP, v.vertex);
//【3】用UnityCG.cginc头文件中内置定义的宏,根据uv坐标来计算真正的纹理上对应的位置(按比例进行二维变换)
o.uv= TRANSFORM_TEX(v.uv, _MainTex);
//点光源需要的衰减
TRANSFER_VERTEX_TO_FRAGMENT(o)//#include "AutoLight.cginc"
//用UnityCG.cginc头文件中内置定义的宏处理雾效,从顶点着色器中输出雾效数据
UNITY_TRANSFER_FOG(o,o.vertex);
//返回此输出结构对象
return o;
}
//--------------------------------【片段着色函数】-----------------------------
//输入:顶点输出结构体
//输出:float4型的像素颜色值
//---------------------------------------------------------------------------------
fixed4 frag (v2f i) : SV_Target
{
//【1】采样主纹理在对应坐标下的颜色值
fixed4 col = tex2D(_MainTex, i.uv);
//【2】用UnityCG.cginc头文件中内置定义的宏启用雾效
UNITY_APPLY_FOG(i.fogCoord,col);
//【3】返回最终的颜色值
return col;
}
ENDCG
}
}
//需要产生阴影 调用备用材质
FallBack "Diffuse"
}
页:
[1]