【Unity】UGUI中图片置灰shader以及动态修改Image的材质,导致所有图片的材质都变了

今天项目中有个需求是,当奖牌没有获得的时候,变灰色,这个灰色不单单是改变原图片的颜色就行了,而是需要特定的shader进行颜色叠加才能实现。(很多游戏技能变灰应该也是这样做的)

当弄好shader做好材质之后,当需要变灰时执行下面方法

    void SetGray()
    {
    
    
        Icon.color = Color.gray;
        Icon.material = Material_Gray;  //假设Material_Gray为变灰的材质球
        
    }

这样设置之后,当代码一运行,所有ui界面全变灰了,并且就算重启运行项目,还是灰的,吓得我以为要把全部ui重新改一遍。
研究后发现相同材质的Image在创建后引用的是内存中同一份材质,所以改掉一个后,其实就是改掉了所有Image的默认材质,这个时候如果需要单独修改这个Image的材质,如使某些技能灰掉,那么就在创建实例时新建一份材质,之后修改这一份材质,导致的问题是这样内存中就会有多份材质存在,慎用。如下:

    void SetGray()
    {
    
    
        Icon.color = Color.gray;
        if (Material_Gray != null)
        {
    
    
            Material material = new Material(Material_Gray);
            Icon.material = material;
        }
    }

下面是是使图片置灰的shader,其中有不少无用参数,将所有参数设置为0就好了:

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)

Shader "UI/Default_Overlay"
{
    
    
	Properties
	{
    
    
		[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {
    
    }
		_Color ("Tint", Color) = (1,1,1,1)
		
		_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

		[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
	}

	SubShader
	{
    
    
		Tags
		{
    
     
			"Queue"="Transparent" 
			"IgnoreProjector"="True" 
			"RenderType"="Transparent" 
			"PreviewType"="Plane"
			"CanUseSpriteAtlas"="True"
		}
		
		Stencil
		{
    
    
			Ref [_Stencil]
			Comp [_StencilComp]
			Pass [_StencilOp] 
			ReadMask [_StencilReadMask]
			WriteMask [_StencilWriteMask]
		}

		Cull Off
		Lighting Off
		ZWrite Off
		ZTest [unity_GUIZTestMode]
		Blend SrcAlpha OneMinusSrcAlpha
		ColorMask [_ColorMask]

		Pass
		{
    
    
			Name "Default"
		CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma target 2.0

			#include "UnityCG.cginc"
			#include "UnityUI.cginc"

			#pragma multi_compile __ UNITY_UI_ALPHACLIP
			
			struct appdata_t
			{
    
    
				float4 vertex   : POSITION;
				float4 color    : COLOR;
				float2 texcoord : TEXCOORD0;
				UNITY_VERTEX_INPUT_INSTANCE_ID
			};

			struct v2f
			{
    
    
				float4 vertex   : SV_POSITION;
				fixed4 color    : COLOR;
				float2 texcoord  : TEXCOORD0;
				float4 worldPosition : TEXCOORD1;
				UNITY_VERTEX_OUTPUT_STEREO
			};
			
			fixed4 _Color;
			fixed4 _TextureSampleAdd;
			float4 _ClipRect;

			v2f vert(appdata_t IN)
			{
    
    
				v2f OUT;
				UNITY_SETUP_INSTANCE_ID(IN);
				UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
				OUT.worldPosition = IN.vertex;
				OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);

				OUT.texcoord = IN.texcoord;
				
				OUT.color = IN.color * _Color;
				return OUT;
			}

			sampler2D _MainTex;

			fixed4 frag(v2f IN) : SV_Target
			{
    
    
				 fixed4 tex = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;//tex2D(_MainTex, IN.uv);
				 float gray = dot(tex.rgb, float3(0.299, 0.587, 0.114));
                 // 输出灰色
                 return fixed4(gray, gray, gray, tex.a);
			}
		ENDCG
		}
	}
}

============ ================= ===== ===== 手动分割================== ======== ======= ===========

下面是另外一种置灰的shade,可以进行灰色彩色切换 :(参考文章传送门

Shader "Custom/GrayScaleShader"
{
    
    
    Properties
    {
    
    
        _MainTex ("Texture", 2D) = "white" {
    
    }
        _IsGrayScale ("Is GrayScale", Range(0, 1)) = 0
    }
    
    SubShader
    {
    
    
        Tags {
    
    "Queue"="Transparent" "RenderType"="Transparent"}
        LOD 100
        
        Pass
        {
    
    
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"
            
            struct appdata
            {
    
    
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f
            {
    
    
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
            };
            
            sampler2D _MainTex;
            bool _IsGrayScale;
            
            v2f vert (appdata v)
            {
    
    
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
    
    
                fixed4 tex = tex2D(_MainTex, i.uv);
                // 判断是否是灰度效果
                if (_IsGrayScale)
                {
    
    
                    // 转换为灰度
                    float gray = dot(tex.rgb, float3(0.299, 0.587, 0.114));
                    // 输出灰色
                    return fixed4(gray, gray, gray, tex.a);
                }
                else
                {
    
    
                    // 输出彩色
                    return tex;
                }
            }
            
            ENDCG
        }
    }
}

该shader的置灰使用方法:

 grayScaleMaterial.SetInt("_IsGrayScale", isGrayScale ? 1 : 0);

over~

猜你喜欢

转载自blog.csdn.net/qq_41789645/article/details/142558387