Unity 对选中物体实现描边效果(方法2:对物体网格顶点的外扩)

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
}

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值