Unity PostProcess Shader - 14 - InnerGlow - 基于后效的内轮廓效果,类似 PhotoShop 图层的内发光


之前写的一个类似Photoshop中的图层的 发光 效果


管线:built-in 管线
unity 版本:2019.4.30f1


思路

  • 得到内轮廓边缘:只要某个像素的 kernal size 范围内的,如 5x5 的 kernal size,只要某个 pixel(x,y) 像素不是全黑,并且 kernal size 核内的 sum 值小于 kernal size 平方,都算是边缘
  • 将内轮廓边缘模糊
  • 将模糊的边缘与 _SrcTex 做像素交集才显示

Shader

// jave.lin 2021/02/25
Shader "PP/InnerGlowPP"
{
   
   
    CGINCLUDE
        #include "UnityCG.cginc"

        // pure col
        float4 vert_pure_col(float4 vertex : POSITION) : SV_POSITION
        {
   
   
            return UnityObjectToClipPos(vertex);
        }
        fixed4 frag_pure_col() : SV_Target
        {
   
   
            return 1;
        }

        // inner glow
        Sampler2D _InnerGlowOrginTex;
        float4 _InnerGlowOrginTex_TexelSize;
        F _InnerGlowKernelSize;
        F _InnerGlowSize;
        struct a2v_inner_glow
        {
   
   
            float4 vertex : POSITION;
            float2 uv : TEXCOORD0;
        };
        struct v2f_inner_glow
        {
   
   
            float4 vertex : SV_POSITION;
            float2 uv : TEXCOORD0;
        };
        v2f_inner_glow vert_inner_glow (a2v_inner_glow v) {
   
   
            v2f_inner_glow o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.uv = v.uv;
            return o;
        }
        fixed4 frag_inner_glow(v2f_inner_glow i) : SV_Target
        {
   
   
            fixed originV = 0;
            F sum = 0;
            int start = -_InnerGlowKernelSize;
            int count = _InnerGlowKernelSize + 1;
            int delta = count - start;
            int threhold = delta * delta;

            for (int x = start; x < count; x++)
            {
   
   
                for (int y = start; y < count; y++)
                {
   
   
                    float2 temp_uv = i.uv + float2(x, y) * _InnerGlowOrginTex_TexelSize.xy * _InnerGlowSize;
                    fixed v = tex2D(_InnerGlowOrginTex, temp_uv);
                    if (x == 0 && y == 0) originV = v;
                    sum += v;
                }
            }
            
            return originV > 0 && sum < threhold ? 1 : 0;
        }

        /////////////// blur /////////////////
        struct a2v_blur
        {
   
   
            float4 vertex : POSITION;
            float2 uv : TEXCOORD0;
        };
        struct v2f_blur
        {
   
   
            float4 vertex : SV_POSITION;
            float2 uv : TEXCOORD0;
            float4 uv01 : TEXCOORD1;
            float4 uv23 : TEXCOORD2;
        };
        Sampler2D _BlurOrginTex;
        float4 _BlurOrginTex_TexelSize;
        F _BlurSize;
        v2f_blur vert_blur_h (a2v_blur v) {
   
   
            v2f_blur o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.uv = v.uv;
            float2 ts = _BlurOrginTex_TexelSize.xy;
            float2 offset1 = float2(1, 0);
            float2 offset2 = float2(2, 0);
            o.uv01.xy = v.uv + offset1 *  ts * _BlurSize; // 左1
            o.uv01.zw = v.uv + offset1 * -ts * _BlurSize; // 右1
            o.uv23.xy = v.uv + offset2 *  ts * _BlurSize; // 左2
            o.uv23.zw = v.uv + offset2 * -ts * _BlurSize; // 右2
            return o;
        }
        v2f_blur vert_blur_v (a2v_blur v) {
   
   
            v2f_blur o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.uv = v.uv;
            float2 ts = _BlurOrginTex_TexelSize.xy;
            float2 offset1 = float2(0, 1);
            float2 offset2 = float2(0, 2);
            o.uv01.xy = v.uv + offset1 *  ts * _BlurSize; // 上1
            o.uv01.zw = v.uv + offset1 * -ts * _BlurSize; // 下1
            o.uv23.xy = v.uv + offset2 *  ts * _BlurSize; // 上2
            o.uv23.zw = v.uv + offset2 * -ts * _BlurSize; // 下2
            return o;
        }
        fixed4 frag_blur (v2f_blur i) : SV_Target {
   
   
            fixed4 sum = tex2D(_BlurOrginTex, i.uv) * 0.4026;
            sum += tex2D(_BlurOrginTex, i.uv01.xy) * 0.2442; // 左1 | 上1
            sum += tex2D(_BlurOrginTex, i.uv01.zw) * 0.2442; // 右1 | 下1
            sum += tex2D(_BlurOrginTex, i.uv23.xy) * 0.0545; // 左2 | 上2
            sum += tex2D(_BlurOrginTex, i.uv23.zw) * 0.0545; // 右2 | 下2
            return sum;
        }

        /////////////// final /////////////////
        Sampler2D _MaskTex;
        Sampler2D _BlurTex;
        Sampler2D _SrcTex;
        fixed4 _InnerGlowColor;
        struct a2v_final
        {
   
   
            float4 vertex : POSITION;
            float2 uv : TEXCOORD0;
        };
        struct v2f_final
        {
   
   
            float4 vertex : SV_POSITION;
            float2 uv : TEXCOORD0;
        };
        v2f_final vert_final (a2v_final v) {
   
   
            v2f_final o;
            o.vertex = UnityObjectToClipPos(v.vertex);
            o.uv = v.uv;
            return o;
        }
        fixed4 frag_final (v2f_final i) : SV_Target {
   
   
            fixed blur_col = tex2D(_BlurTex, i.uv).r;
            fixed mask_col = tex2D(_MaskTex, i.uv).r;
            blur_col *= (mask_col > 0 ? 1 : 0);
            fixed4 combinedCol = saturate(tex2D(_SrcTex, i.uv));
            combinedCol.rgb += (blur_col * _InnerGlowColor.a) * _InnerGlowColor.rgb;
            return combinedCol;
        }
    ENDCG
    SubShader
    {
   
   
        // No culling or depth
        Cull Off ZWrite Off ZTest Always
        Pass // pure col 0
        {
   
   
            
            ColorMask R
            CGPROGRAM
            #pragma vertex vert_pure_col
      
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值