Unity 2D内描边Shader

一、前言

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

二、Shader内容

2.1 初版Shader

Shader "Custom/2DInline"
{
    Properties
    {
        _MainTex("MainTex",2D) = "white"{}
        _InlineColor("InlineColor",Color) = (0,0,0,1)
        _InlineWidth("InlineWidth",Range(0,10)) = 1
    }

    SubShader{
        Tags { "Queue" = "Transparent" "RenderType" = "Transparent"}
        Blend SrcAlpha OneMinusSrcAlpha

        Pass{
            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;
            float4 _MainTex_TexelSize;
            float4 _InlineColor;
            float _InlineWidth;
            
            v2f vert(appdata a){
                v2f v;
                v.pos = UnityObjectToClipPos(a.vertex);
                v.uv = TRANSFORM_TEX(a.uv,_MainTex);
                
### 实现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、付费专栏及课程。

余额充值