Unity 2D外描边Shader

一、前言

今天,我们来实现一个2D外描边的效果。外描边:即在边缘透明像素周围加上一层描边,不占用原来的像素。
思路:我们可以在片元着色器实现此效果,当一个像素本身不是透明的(alpha>0),那么让它返回自身的颜色;当一个像素本身是透明的,并且它上下左右4个像素的alpha值总和不等于0,那么我们可以判定该像素处于边缘,让它变成描边颜色就可以。

二、Shader内容

2.1 初版shader

好,我们根据思路来写代码

Shader "Custom/2DOutline"{
    
    Properties{
        _MainTex("Texture",2D) = "white" {}
        _OutlineWidth("OutlineWidth",Range(0,10)) = 0
        _OutlineColor("OutlineColor",Color) = (0,0,0,1)     
    }

    SubShader{
        Tags { "Queue" = "Transparent" "RenderType" = "Transparent"}



        Pass{
            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            Cull Off
            CGPROGRAM

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

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

            
            sampler2D _MainTex;
            float4 _MainTex_ST; //获取_MainTex纹理的Tiling和Offset,带入xyzw
            float4 _MainTex_TexelSize;//获取_MainTex纹理的宽高,4个分量如下:Vector4(1 / width, 1 / height, width, height)
            
            float _OutlineWidth;
            float4 _OutlineColor;

            
            //顶点着色器不做额外操作
            v2f vert (appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                return o;
            }

            
            //片元着色器
            half4 frag(v2f v) : SV_Target{
                fixed4 col = tex2D(_
### 实现Unity半透明描边效果 在Unity中创建具有半透明特性的描边效果,主要依赖于对Shader的深入理解和灵活运用。为了达到这一目标,通常会采用Surface Shader或自定义Vertex and Fragment (Vert/Frag) Shaders来实现特定需求的效果。 对于半透明描边而言,在Shader内部设置合适的混合模式至关重要。具体来说,`Blend SrcAlpha OneMinusSrcAlpha`指令被广泛应用于此类场景下[^2]。这使得渲染对象能够以基于源颜色alpha通道的方式与背景图像相融合,从而呈现出自然过渡的半透明视觉效果。 下面是一个简单的示例代码片段展示如何构建这样的Shader: ```csharp Shader "Custom/TranslucentOutline" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _Color ("Main Color", Color) = (1,1,1,0.5) _OutlineColor ("Outline Color", Color) = (0,0,0,1) _OutlineWidth ("Outline Width", Range(0.0, 0.1)) = .05 } SubShader { Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"} Pass { Name "OUTLINE" Cull Front Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata_t { float4 vertex : POSITION; float3 normal : NORMAL; }; struct v2f { float4 pos : SV_POSITION; float4 color : COLOR; }; uniform float _OutlineWidth; uniform float4 _OutlineColor; v2f vert(appdata_t v) { v2f o; // 计算顶点位置偏移量 float3 norm = normalize(mul((float3x3)unity_ObjectToWorld, v.normal)); float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, v.vertex).xyz); float d = dot(norm, viewDir); o.pos = UnityObjectToClipPos(v.vertex + v.normal * (_OutlineWidth / abs(d))); o.color = _OutlineColor; return o; } half4 frag(v2f i) :COLOR { return i.color; } ENDCG } GrabPass{ "_BackgroundTexture"} Pass { Name "BASE" ZWrite Off Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag sampler2D _MainTex; fixed4 _Color; struct data { float4 vertex : POSITION; float2 uv_MainTex : TEXCOORD0; }; data vert(data v){ v.vertex = UnityObjectToClipPos(v.vertex); return v; } half4 frag(data IN) : COLOR { half4 col = tex2D(_MainTex, IN.uv_MainTex) *_Color; clip(col.a - 0.1); // 剔除完全透明像素 return col; } ENDCG } } } ``` 这段代码实现了两个重要功能:首先是通过调整顶点法线方向并乘以一定宽度参数 `_OutlineWidth` 来生成向扩展的轮廓;其次是利用 `GrabPass` 技术捕捉当前屏幕内容作为背景纹理,并在此基础上绘制主体模型,确保两者之间存在适当层次关系的同时也支持了半透明属性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值