Unity 实现选中物体的简单描边效果
WIKI : Silhouette-Outlined Diffuse
完整源码:https://github.com/ZeroChiLi/ShaderTest
原理
在完场景渲染后,再对需要描边效果的物体进行渲染,实质上就是就是在原来mesh基础上把顶点延法线方向外扩一点,再上色即可。实现简单,效果也比较劣质。
对物体再渲染一层(背面),顶点外扩一定距离,模拟描边
DrawOutlineWithTarget类继承于PostEffectsBase类,介绍见这里。
实现
原场景包含:左边一个有镂空的立方体,中间有多个子mesh的坦克,和右边半透明的小球。
DrawOutlineWithTarget类
使用Graphics.DrawMesh()对选中物体再次渲染。
public class DrawOutlineWithTarget : PostEffectsBase
{
// 选择的物体列表
public GameObject[] targets;
[Range(0,1)]
public float width = 0.05f;
public Color color = Color.green;
// 所有选择物体的网格
private MeshFilter[] meshFilters;
// 也可以在OnPostRender()中更新
private void Update()
{
if (TargetMaterial != null && targets != null)
{
TargetMaterial.SetFloat("_Width", width);
TargetMaterial.SetColor("_Color", color);
for (int i = 0; i < targets.Length; i++)
{
if (targets[i] == null)
continue;
meshFilters = targets[i].GetComponentsInChildren<MeshFilter>();
for (int j = 0; j < meshFilters.Length; j++)
Graphics.DrawMesh(meshFilters[j].sharedMesh, meshFilters[j].transform.localToWorldMatrix, TargetMaterial, 0); // 对选中物体再次渲染。
}
}
}
}
DrawOutlineWithTarget.shader
设置好渲染队列(屏幕后处理),关闭深度写入(避免遮挡透明物体),剔除正面,开启透明度混合,再对顶点外扩,最后输出颜色即可。
Shader "Custom/DrawOutlineWithTarget" {
Properties {
_Color ("Outline Color", Color) = (0,0,0,1)
_Width ("Outline Width", Float) = 0.5
}
SubShader {
Tags { "Queue" = "Transparent" }
Pass {
ZWrite OFF // 关闭深度写入
Cull Front // 剔除正面
Blend SrcAlpha OneMinusSrcAlpha // 透明混合颜色
CGPROGRAM
fixed4 _Color;
float _Width;
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 pos : SV_POSITION;
};
v2f vert (appdata_base v)
{
v2f o;
v.vertex.xyz += v.normal.xyz * _Width; // 顶点延法线方向外扩
o.pos = UnityObjectToClipPos(v.vertex);
return o;
}
half4 frag(v2f i) :COLOR {
return _Color * _Color.a;
}
ENDCG
}
}
FallBack OFF
}