FairyGUI-Unity 自定义UIShader

FairyGUI中给组件更换Shader,最简单的方式就是找到组件中的Shader字段进行赋值。需要注意的是,对于自定的shader效果需要将目标图片进行单独发布,也就是一个目标图片占用一张图集。(应该会有更好的解决办法,但目前还是就先这样子)

本篇文章中的Shader源码来自于对官方的“FairyGUI/Image”修改,修改部分的源码来自于网络。

示例:加载Shader

代码中加载自定义Shader:

local logoImg = this.GetChild("n2").asImage
logoImg.shader = "FairyGUI/Image-Light"

一:扫光Shader

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "FairyGUI/Image-Light"
{
    Properties
    {
        _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}
        _StencilComp ("Stencil Comparison", Float) = 8
        _Stencil ("Stencil ID", Float) = 0
        _StencilOp ("Stencil Operation", Float) = 0
        _StencilWriteMask ("Stencil Write Mask", Float) = 255
        _StencilReadMask ("Stencil Read Mask", Float) = 255
        _ColorMask ("Color Mask", Float) = 15
        _BlendSrcFactor ("Blend SrcFactor", Float) = 5
        _BlendDstFactor ("Blend DstFactor", Float) = 10
        [Header(Light)]
        //扫光时间
        _LightTime("Light Time", Float) = 1
        //扫光厚度
        _LightThick("Light Thick", Float) = 0.2
        //循环时间
        _LightInterval("Light Interval", Float) = 2
        //扫光角度
        _LightAngle("Light Angle", int) = 60
        //亮度
        _Brightness("Light Brightness",float) = 1
        //扫光颜色
        _LightColor ("Light Color", Color) = (1,1,1,1)
    }
    SubShader
    {
        LOD 100
        Tags
        {
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderType" = "Transparent"
        }
        Stencil
        {
            Ref [_Stencil]
            Comp [_StencilComp]
            Pass [_StencilOp]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
        }
        Cull Off
        Lighting Off
        ZWrite Off
        Fog
        {
            Mode Off
        }
        Blend [_BlendSrcFactor] [_BlendDstFactor], One One
        ColorMask [_ColorMask]
        Pass
        {
            CGPROGRAM
            #pragma multi_compile NOT_COMBINED COMBINED
            #pragma multi_compile NOT_GRAYED GRAYED COLOR_FILTER
            #pragma multi_compile NOT_CLIPPED CLIPPED SOFT_CLIPPED ALPHA_MASK
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            struct appdata_t
            {
                float4 vertex : POSITION;
                fixed4 color : COLOR;
                float4 texcoord : TEXCOORD0;
            };
            struct v2f
            {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
                float4 texcoord : TEXCOORD0;
                #ifdef CLIPPED
                    float2 clipPos : TEXCOORD1;
                #endif
                #ifdef SOFT_CLIPPED
                    float2 clipPos : TEXCOORD1;
                #endif
            };
            sampler2D _MainTex;
            half _LightTime;
            float _LightThick;
            float _LightInterval;
            int _LightAngle;
            float _Brightness;
            float4 _LightColor;
            #ifdef COMBINED
                sampler2D _AlphaTex;
            #endif
            CBUFFER_START(UnityPerMaterial)
            #ifdef CLIPPED
                float4 _ClipBox = float4(-2, -2, 0, 0);
            #endif
            #ifdef SOFT_CLIPPED
                float4 _ClipBox = float4(-2, -2, 0, 0);
                float4 _ClipSoftness = float4(0, 0, 0, 0);
            #endif
            CBUFFER_END
            #ifdef COLOR_FILTER
                float4x4 _ColorMatrix;
                float4 _ColorOffset;
                float _ColorOption = 0;
            #endif
            v2f vert(appdata_t v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.texcoord = v.texcoord;
                #if !defined(UNITY_COLORSPACE_GAMMA) && (UNITY_VERSION >= 550)
                    o.color.rgb = GammaToLinearSpace(v.color.rgb);
                    o.color.a = v.color.a;
                #else
                o.color = v.color;
                #endif
                #ifdef CLIPPED
                    o.clipPos = mul(unity_ObjectToWorld, v.vertex).xy * _ClipBox.zw + _ClipBox.xy;
                #endif
                #ifdef SOFT_CLIPPED
                    o.clipPos = mul(unity_ObjectToWorld, v.vertex).xy * _ClipBox.zw + _ClipBox.xy;
                #endif
                return o;
            }
            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.texcoord.xy / i.texcoord.w) * i.color;
                //扫光代码来源 https://blog.csdn.net/u014621871/article/details/122685044
                //光照的流逝时间
                fixed currentTimePassed = fmod(_Time.y, _LightTime + _LightInterval);
                fixed x = currentTimePassed / _LightTime;
                
                //倾斜角 1°≈0.0174444
                float angleInRad = 0.0174444 * _LightAngle;
                
                fixed tanX = tan(angleInRad);
                x += (x - 1) / tanX;
                
                fixed x1 = i.texcoord.y / tanX + x;
                fixed x2 = x1 + _LightThick;
                if (i.texcoord.x > x1 && i.texcoord.x < x2)
                {
                    //差值计算,根据与中心的距离的比例来计算亮度
                    float xMid = 0.5 * (x1 + x2);
                    fixed dis = 1 - abs(i.texcoord.x - xMid) * 2 / _LightThick;
                    half colorA = col.a;
                    //扫光的颜色*强度+默认颜色输出
                    col += col + _LightColor * (_Brightness * dis);
                    col.a = colorA;
                }
                
                #ifdef COMBINED
                    col.a *= tex2D(_AlphaTex, i.texcoord.xy / i.texcoord.w).g;
                #endif
                #ifdef GRAYED
                    fixed grey = dot(col.rgb, fixed3(0.299, 0.587, 0.114));
                    col.rgb = fixed3(grey, grey, grey);
                #endif
                #ifdef SOFT_CLIPPED
                    float2 factor = float2(0,0);
                    if(i.clipPos.x<0)
                        factor.x = (1.0-abs(i.clipPos.x)) * _ClipSoftness.x;
                    else
                        factor.x = (1.0-i.clipPos.x) * _ClipSoftness.z;
                    if(i.clipPos.y<0)
                        factor.y = (1.0-abs(i.clipPos.y)) * _ClipSoftness.w;
                    else
                        factor.y = (1.0-i.clipPos.y) * _ClipSoftness.y;
                    col.a *= clamp(min(factor.x, factor.y), 0.0, 1.0);
                #endif
                #ifdef CLIPPED
                    float2 factor = abs(i.clipPos);
                    col.a *= step(max(factor.x, factor.y), 1);
                #endif
                #ifdef COLOR_FILTER
                    if (_ColorOption == 0)
                    {
                        fixed4 col2 = col;
                        col2.r = dot(col, _ColorMatrix[0]) + _ColorOffset.x;
                        col2.g = dot(col, _ColorMatrix[1]) + _ColorOffset.y;
                        col2.b = dot(col, _ColorMatrix[2]) + _ColorOffset.z;
                        col2.a = dot(col, _ColorMatrix[3]) + _ColorOffset.w;
                        col = col2;
                    }
                    else //premultiply alpha
                        col.rgb *= col.a;
                #endif
                #ifdef ALPHA_MASK
                    clip(col.a - 0.001);
                #endif
                return col;
            }
            ENDCG
        }
    }
}

二:循环背景图

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "FairyGUI/Image-Loop"
{
    Properties
    {
        _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}
        _StencilComp ("Stencil Comparison", Float) = 8
        _Stencil ("Stencil ID", Float) = 0
        _StencilOp ("Stencil Operation", Float) = 0
        _StencilWriteMask ("Stencil Write Mask", Float) = 255
        _StencilReadMask ("Stencil Read Mask", Float) = 255
        _ColorMask ("Color Mask", Float) = 15
        _BlendSrcFactor ("Blend SrcFactor", Float) = 5
        _BlendDstFactor ("Blend DstFactor", Float) = 10
        _Speed("Speed", Range(0,3)) = 0.1
        _Rotation("Rotation", Range(0,360)) = 225 //为了方便直观,角度的值使用了0~360范围
    }
    SubShader
    {
        LOD 100
        Tags
        {
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "RenderType" = "Transparent"
        }
        Stencil
        {
            Ref [_Stencil]
            Comp [_StencilComp]
            Pass [_StencilOp]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
        }
        Cull Off
        Lighting Off
        ZWrite Off
        Fog
        {
            Mode Off
        }
        Blend [_BlendSrcFactor] [_BlendDstFactor], One One
        ColorMask [_ColorMask]
        Pass
        {
            Blend SrcAlpha OneMinusSrcAlpha
            CGPROGRAM
            #pragma multi_compile NOT_COMBINED COMBINED
            #pragma multi_compile NOT_GRAYED GRAYED COLOR_FILTER
            #pragma multi_compile NOT_CLIPPED CLIPPED SOFT_CLIPPED ALPHA_MASK
            #pragma vertex vert
            #pragma fragment frag
            #pragma shader_feature _FlipY
            #include "UnityCG.cginc"
            struct appdata_t
            {
                float4 vertex : POSITION;
                fixed4 color : COLOR;
                float4 texcoord : TEXCOORD0;
            };
            struct v2f
            {
                float4 vertex : SV_POSITION;
                fixed4 color : COLOR;
                half2 uvTA: TEXCOORD0;
                #ifdef CLIPPED
                    float2 clipPos : TEXCOORD1;
                #endif
                #ifdef SOFT_CLIPPED
                    float2 clipPos : TEXCOORD1;
                #endif
            };
            sampler2D _MainTex;
            float _Speed;
            float _Rotation;
            uniform half4 _MainTex_ST;
            #ifdef COMBINED
                sampler2D _AlphaTex;
            #endif
            CBUFFER_START(UnityPerMaterial)
            #ifdef CLIPPED
                float4 _ClipBox = float4(-2, -2, 0, 0);
            #endif
            #ifdef SOFT_CLIPPED
                float4 _ClipBox = float4(-2, -2, 0, 0);
                float4 _ClipSoftness = float4(0, 0, 0, 0);
            #endif
            CBUFFER_END
            #ifdef COLOR_FILTER
                float4x4 _ColorMatrix;
                float4 _ColorOffset;
                float _ColorOption = 0;
            #endif
            v2f vert(appdata_t v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                #if !defined(UNITY_COLORSPACE_GAMMA) && (UNITY_VERSION >= 550)
                    o.color.rgb = GammaToLinearSpace(v.color.rgb);
                    o.color.a = v.color.a;
                #else
                o.color = v.color;
                #endif
                #ifdef CLIPPED
                    o.clipPos = mul(unity_ObjectToWorld, v.vertex).xy * _ClipBox.zw + _ClipBox.xy;
                #endif
                #ifdef SOFT_CLIPPED
                    o.clipPos = mul(unity_ObjectToWorld, v.vertex).xy * _ClipBox.zw + _ClipBox.xy;
                #endif
                float Rot = _Rotation * (3.1415926f / 180.0f);
                float s = sin(Rot);
                float c = cos(Rot);
                o.uvTA = (v.texcoord) * _MainTex_ST.xy + fixed2(s, c) * (_Time.y * _Speed) - _MainTex_ST.zw;
                return o;
            }
            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uvTA).rgba * i.color;
                #ifdef COMBINED
                    col.a *= tex2D(_AlphaTex, i.texcoord.xy / i.texcoord.w).g;
                #endif
                #ifdef GRAYED
                    fixed grey = dot(col.rgb, fixed3(0.299, 0.587, 0.114));
                    col.rgb = fixed3(grey, grey, grey);
                #endif
                #ifdef SOFT_CLIPPED
                    float2 factor = float2(0,0);
                    if(i.clipPos.x<0)
                        factor.x = (1.0-abs(i.clipPos.x)) * _ClipSoftness.x;
                    else
                        factor.x = (1.0-i.clipPos.x) * _ClipSoftness.z;
                    if(i.clipPos.y<0)
                        factor.y = (1.0-abs(i.clipPos.y)) * _ClipSoftness.w;
                    else
                        factor.y = (1.0-i.clipPos.y) * _ClipSoftness.y;
                    col.a *= clamp(min(factor.x, factor.y), 0.0, 1.0);
                #endif
                #ifdef CLIPPED
                    float2 factor = abs(i.clipPos);
                    col.a *= step(max(factor.x, factor.y), 1);
                #endif
                #ifdef COLOR_FILTER
                    if (_ColorOption == 0)
                    {
                        fixed4 col2 = col;
                        col2.r = dot(col, _ColorMatrix[0]) + _ColorOffset.x;
                        col2.g = dot(col, _ColorMatrix[1]) + _ColorOffset.y;
                        col2.b = dot(col, _ColorMatrix[2]) + _ColorOffset.z;
                        col2.a = dot(col, _ColorMatrix[3]) + _ColorOffset.w;
                        col = col2;
                    }
                    else //premultiply alpha
                        col.rgb *= col.a;
                #endif
                #ifdef ALPHA_MASK
                    clip(col.a - 0.001);
                #endif
                return col;
            }
            ENDCG
        }
    }
}

参考:

1、UGUI扫光shader

2、无限循环背景的制作

如果有问题可以留言指出!感谢!

你可能感兴趣的:(Unity,FairyGUI,unity,FairyGUI,Shader)