UI置灰

在UIDefault的基础上做的修改

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
Shader "My/UI/UIDefault-Gray"
{
    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

        _ClipRect("Clip Rect", Vector) = (0,0,0,0)
    }

    SubShader
    {
        Tags
        {
            "RenderType" = "Transparent"
            "Queue" = "Transparent"
            "IgnoreProjector" = "True"
            "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_CLIP_RECT
            #pragma multi_compile __ UNITY_UI_ALPHACLIP
            #pragma multi_compile_local __ GRAY

            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
            };

            sampler2D _MainTex;
            fixed4 _Color;
            fixed4 _TextureSampleAdd;
            float4 _ClipRect;
            float4 _MainTex_ST;
            fixed _IsGray;

            v2f vert(appdata_t v)
            {
                v2f OUT;
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
                OUT.worldPosition = v.vertex; // mul(unity_ObjectToWorld, v.vertex); //不用后面这句貌似也没问题
                OUT.vertex = UnityObjectToClipPos(v.vertex);

                OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);

                OUT.color = v.color * _Color;
                return OUT;
            }

            fixed4 frag(v2f IN) : SV_Target
            {
                half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;

                #ifdef UNITY_UI_CLIP_RECT
                color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
                #endif

                #ifdef UNITY_UI_ALPHACLIP
                clip(color.a - 0.001);
                #endif

                #ifdef GRAY
                half lum = Luminance(color.rgb);
                half isWhite = step(0.998, lum); //精度问题用1结果不对
                color.rgb = lerp(half3(lum, lum, lum), Luminance(half3(0, 1, 1)), isWhite); //非白色使用前面的, 白色使用后面的
                #endif

                return color;
            }
            ENDCG
        }
    }
}

 

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class MyImage : Image
{
    private bool m_isGray;
    public bool Gray
    {
        get { return m_isGray; }
        set
        {
            if (m_isGray != value)
            {
                m_isGray = value;
                if (value)
                {
                    if (null == m_grayMat)
                    {
                        var shader = Shader.Find("My/UI/UIDefault-Gray");
                        m_grayMat = new Material(shader);
                        m_grayMat.EnableKeyword("GRAY");
                        m_grayMat.hideFlags = HideFlags.DontSave;
                    }
                    material = m_grayMat;
                }
                else
                {
                    material = null;
                }
            }
        }
    }

    private Material m_grayMat;




    //******************** 测试用

    private PointerEventData m_uiPointerEventData;
    private List<RaycastResult> m_uiRaycastResultCache = new List<RaycastResult>();

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            var screenPos = Input.mousePosition;
            var go = GetFirstTouchUI(screenPos);
            if (this.gameObject == go)
            {
                this.Gray = !this.Gray;
            }
        }
    }

    public GameObject GetFirstTouchUI(Vector2 screenPos)
    {
        if (null == EventSystem.current)
            return null;

        if (m_uiPointerEventData == null)
            m_uiPointerEventData = new PointerEventData(EventSystem.current);
        m_uiPointerEventData.position = new Vector2(screenPos.x, screenPos.y);

        EventSystem.current.RaycastAll(m_uiPointerEventData, m_uiRaycastResultCache);
        if (m_uiRaycastResultCache.Count > 0)
            return m_uiRaycastResultCache[0].gameObject;
        return null;
    }

    //********************

}

效果图

 

 

需要注意

如果置灰部分不考虑白色的话

color.rgb =  Luminance(color.rgb);

可能会出现在Gamma颜色空间下,白色图片没法变灰

 

参考

unity 常见的置灰处理_天涯过客TYGK的博客-CSDN博客_unity置灰mash

Unity shader实现灰度效果 - 知乎 (zhihu.com)

Shader 学习笔记:图片置灰 - 知乎 (zhihu.com)

Shader_UGUI白色图片无法置灰问题 - 知乎 (zhihu.com)

posted @ 2023-02-16 00:42  yanghui01  阅读(26)  评论(0编辑  收藏  举报