美文网首页工作生活
关于unity shader描边的一二事(顶点挤出式描边的探讨)

关于unity shader描边的一二事(顶点挤出式描边的探讨)

作者: 小蜻蜓队长 | 来源:发表于2019-07-03 16:57 被阅读0次

    shader描边的方式很多,我们这里重点考虑其中一种。
    一个pass沿着顶点法线挤出,剔除正面
    一个pass正常渲染,剔除背面

    第一种

    下面贴出只是单纯的沿着将顶点沿着法线挤出的代码和效果(只贴出顶点挤出pass)

    
            Tags { "RenderType" = "Opaque" }
            LOD 100
            
            pass
            {
                Tags { "LightMode" = "Always" }
                Cull Front
                ZWrite On
                CGPROGRAM
                
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                float _Outline;
                float _Factor;
                struct v2f
                {
                    float4 pos: SV_POSITION;
                };
                v2f vert(appdata_full v)
                {
                    v2f o;
                    float4 pos = v.vertex; //转换到视图空间
                    float3 normal = v.normal;//将法线转换到视图空间
                    pos = pos + float4(normalize(normal), 0) * _Outline;//将顶点沿着法线方向延伸或者收缩
                    o.pos = UnityObjectToClipPos(pos);
                    
                    return o;
                }
                float4 frag(v2f i): COLOR
                {
                    return float4(1, 0, 0, 0);
                }
                ENDCG
                
            }
    

    就像下图看到的那样,cube的描边会有很严重的割裂现象,这是因为只是单纯的沿着法线挤出,效果就好像将他的面往顶点的Z方向拉出去,这种效果显然不是很不好。


    效果图1

    第二种

    既然会出现这种事情,那么我们就会想到想发现往回缩一点是不是就能让他们铆合起来呢。

    pass
           {
               Tags { "LightMode" = "Always" }
               Cull Front
               ZWrite On
               CGPROGRAM
               
               #pragma vertex vert
               #pragma fragment frag
               #include "UnityCG.cginc"
               float _Outline;
               float _SubNormal;
               struct v2f
               {
                   float4 pos: SV_POSITION;
               };
               v2f vert(appdata_full v)
               {
                   v2f o;
                   float4 pos = mul(UNITY_MATRIX_MV, v.vertex); //转换到视图空间
                   float3 normal = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);//将法线转换到视图空间
                   normal.z = -_SubNormal;//将Z轴进行收缩
                   pos = pos + float4(normalize(normal), 0) * _Outline;//将顶点沿着法线方向延伸或者收缩
                   o.pos = mul(UNITY_MATRIX_P, pos);
                   
                   return o;
               }
               float4 frag(v2f i): COLOR
               {
                   return float4(1, 0, 0, 0);
               }
               ENDCG
               
           }
    

    效果也不是很好,描边部分隔裂感依旧很重。


    效果

    第三种

    既然我们一开始描边是顺着法线方向挤出,那如果朝着顶点的方向会不会好一点,于是就想到了让挤出方向顺着顶点的方向和法线的方向做过度。

            pass
            {
                Tags { "LightMode" = "Always" }
                Cull Front
                ZWrite On
                CGPROGRAM
                
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                float _Outline;
                float _Factor;
                struct v2f
                {
                    float4 pos: SV_POSITION;
                };
                v2f vert(appdata_full v)
                {
                    v2f o;
                    float3 dir = normalize(v.vertex.xyz);
                    float3 dir2 = v.normal;
                    float D = dot(dir, dir2);
                    dir = dir * sign(D);
                    dir = dir * _Factor + dir2 * (1 - _Factor);
                    v.vertex.xyz += dir * _Outline;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    return o;
                }
                float4 frag(v2f i): COLOR
                {
                    return float4(1, 0, 0, 0);
                }
                ENDCG
                
            }
            
    

    效果来看差不多满足我们的需求了。


    最终效果

    相关文章

      网友评论

        本文标题:关于unity shader描边的一二事(顶点挤出式描边的探讨)

        本文链接:https://www.haomeiwen.com/subject/nxlncctx.html