Unity ShaderLab新手宝典简单Shader:描边效果 + 相关基础知识
<>原理
当Shader中有多个Pass时,Pass会按照顺序执行,后执行的Pass绘制的图像会覆盖掉前面的Pass绘制的图像。
这个案例就是通过两层Pass实现,第一层Pass将模型的顶点位置沿法线方向膨胀一段距离,然后为膨胀的模型指定一个颜色,不需要与任何灯光交互。
第二层模型正常显示,本案例使用Surface Shader,并使用Standard Specular光照模型。
正常情况第一层膨胀起来的模型会将第二层模型笼罩,因此第二层模型无法通过深度测试,最终只会显示第一层的模型。为解决这个问题,需要让第二层模型通过深度测试。具体解决办法有如下两种:
* 更改第二层的深度值比较方法,但这样做会导致其它物体在深度测试时出现错误,所以排除此法。
* 关闭第一层的深度写入,这样深度缓存中没有第一层模型深度值,第二层模型自然就可以通过深度测试了。
但使用第二种方法又会引发另一个问题,就是当物体关闭深度写入后,后面被遮挡的物体无法知道自己被遮挡,在绘制图像时会覆盖已经绘制好的第一层模型。为了避免这个问题,需要让该物体在所有不透明物体绘制完成后在进行绘制,所以更改Shader的渲染队列为Transparent,这样就不会被后面的物体覆盖了。
Shader"Samples/OutLine" { Properties { [Header(Texture Group)]
//[Header(name)]材质面板说明 [Space(10)]//间距 _Albedo("Albedo",2D) = "white"{} [
NoScaleOffset]_Specular("Specular(RGB-A)",2D) = "black"{}
//[NoScalleOffset]就是没有贴图缩放和位移设置 [NoScaleOffset]_Normal("Normal",2D) = "bump"{} [
NoScaleOffset]_AO("Ambient Occlusion",2D) = "white"{} [Header(OutLine Properties
)] [Space(10)] _OutLineColor("OutLine Color",Color) = (1,0,1,1) _OutLineWidth(
"OutLine Width",Range(0,0.1)) = 0.01 } SubShader { Tags { "RenderType"="Opaque"
"Queue" = "Transparent"} //----------OutLine Layer---------- Pass { ZWrite Off
//ZWrite On/Off 表示设置是否写入深度缓存,默认为On CGPROGRAM #pragma vertex vert #pragma
fragment frag #include "UnityCG.cginc" struct v2f { float4 vertex : SV_POSITION;
}; fixed4 _OutLineColor; fixed _OutLineWidth; v2f vert (appdata_base v) { v2f o;
v.vertex.xyz += v.normal * _OutLineWidth; o.vertex = UnityObjectToClipPos(v.
vertex); return o; } fixed4 frag (v2f i) : SV_Target { return _OutLineColor; }
ENDCG} //----------Regular Layer---------- CGPROGRAM #pragma surface surf
StandardSpecular fullforwardshadows
//定义表面着色器的名称,通常使用surf,定义光照模型为StandardSpecular,fullforwardshadows指令使物体支持所有灯光类型的投影
struct Input { float2 uv_Albedo; }; sampler2D _Albedo; sampler2D _Specular;
sampler2D _Normal; sampler2D _AO; void surf(Input IN, inout
SurfaceOutputStandardSpecular o) { fixed4 c = tex2D(_Albedo, IN.uv_Albedo); o.
Albedo= c.rgb; fixed4 specular = tex2D(_Specular, IN.uv_Albedo); o.Specular =
specular.rgb; o.Smoothness = specular.a; o.Normal = UnpackNormal(tex2D(_Normal,
IN.uv_Albedo)); o.Occlusion = tex2D(_AO, IN.uv_Albedo); } ENDCG } }
我使用这个Shader遇到了一些问题:
1、在URP模板中使用了这个Shader的材质球除描边外呈粉紫色,但是没有报错。
<>可以设置的渲染状态
渲染状态数值作用
CullCull Back/Front/Off设置多边形的剔除方式,有背面剔除、正面剔除、不剔除,默认为back
ZTestZTest (Less/Greater/LEqual/GEqual/Equal/NotEqual/Always)
设置深度测试的对比方式,默认为LEqual
ZWriteZWrite On/Off设置是否写入深度缓存,默认为On
BlendBlend sourecBlendMode destBlendMode设置渲染图像的混合方式
ColorMaskColorMask RGB/A/0/或者R、G、B、A的任意组合设置颜色通道的写入蒙版,默认蒙版为RGBA,当设置为0时,则无法写入任何颜色
上面表格中只列出了一些使用频次较高的渲染状态,除这些外Unity还提供了其他可设置的渲染状态,感兴趣的可以阅读Unity官方文档中关于Pass渲染状态的部分内容。