模型描边效果

1、模型描边效果是什么

在Unity中,模型描边效果也可以称为边缘描边、轮廓描边、轮廓线效果。
它实现出来的效果类似边缘检测,主要是为了让单个3D模型产生描边效果,使模型的轮廓更加突出。这种效果一般用在卡通渲染、手绘风格、漫画风格的游戏中,还可以用来制作对象选中效果。

2、基本原理

一句话描述模型描边效果的基本原理:
两个Pass渲染对象,一个Pass用于渲染沿法线方向放大的模型,一个Pass用于正常渲染正常模型。相当于先用纯色渲染一次放大后的模型,再用模型本来的颜色覆盖重合部分
关键点:

  • 如何放大模型

在第一个Pass中我们可以在顶点着色器函数中将顶点沿着法线方向进行偏移,偏移的距离可以是一个自定义参数,它可以用来控制边缘线的粗细。在片元着色器函数中直接返回一个自定义颜色即可,它决定了边缘线的颜色。

注意:对于棱角分明的几何体,最简单的方法是采用外壳模型的方案

  • 如何覆盖重合部分

在第二个Pass中,我们只需要正常按需求(是否受光照影响等)渲染模型即可。
但是正常情况下,放大的部分会直接挡住正常大小的模型内容,这是因为第二个Pass的渲染的重合部分无法通过深度写入,直接被抛弃了
要解决这个问题很简单,直接让第一个Pass关闭深度写入即可,这样重合部分,就会显示为第二个Pass绘制的结果

两个Pass渲染对象,一个Pass用于渲染沿法线方向放大的模型,一个Pass用于正常渲染正常模型。相当于先用纯色渲染一次放大后的模型,再用模型本来的颜色覆盖重合部分。为了让重合部分能够正常显示为第二个Pass的渲染内容,需要关闭第一个Pass的深度写入!

3、解决关闭深度写入带来的问题

虽然关闭第一个Pass的深度写入可以帮助我们实现出想要的效果,但是它会带来一个问题,就是物体后方的内容会覆盖掉边缘线!

解决这个问题的方案是:设置该 模型描边效果Shader 的渲染队列为Transparent,让它晚于几何体进行渲染

4、实现

Shader "ShaderProj/15/Outline"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _OutLineColor ("OutLineColor", Color) = (1,1,1,1)
        _OutLineWidth ("OutLineWidth", Float) = 0.1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "Queue"="Transparent"}
        Pass
        {
            ZWrite Off

            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct v2f
            {
                // 不需要 uv 纹理坐标,因为 outline 颜色是确定的
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _OutLineColor;
            float _OutLineWidth;

            v2f vert (appdata_base v)
            {
                v2f o;
                // 顶点朝法线方向偏移后再转换到裁剪空间
                float3 newVertex = v.vertex + normalize(v.normal) * _OutLineWidth;
                o.vertex = UnityObjectToClipPos(newVertex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return _OutLineColor;
            }
            ENDCG
        }

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            v2f vert (appdata_base v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return tex2D(_MainTex, i.uv);
            }
            ENDCG
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值