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的材质球除描边外呈粉紫色,但是没有报错。
可以设置的渲染状态
渲染状态 | 数值 | 作用 |
Cull | Cull Back/Front/Off | 设置多边形的剔除方式,有背面剔除、正面剔除、不剔除,默认为back |
ZTest | ZTest (Less/Greater/LEqual/GEqual/Equal/NotEqual/Always) | 设置深度测试的对比方式,默认为LEqual |
ZWrite | ZWrite On/Off | 设置是否写入深度缓存,默认为On |
Blend | Blend sourecBlendMode destBlendMode | 设置渲染图像的混合方式 |
ColorMask | ColorMask RGB/A/0/或者R、G、B、A的任意组合 | 设置颜色通道的写入蒙版,默认蒙版为RGBA,当设置为0时,则无法写入任何颜色 |