在Texture2D / Sprite中查找和替换颜色

Owo*_*wow 0 c# colors renderer sprite unity-game-engine

在此处输入图片说明

我想直接在代码中将裤子的颜色从蓝色(#0088f0)更改为红色(#f00000)(这是2D精灵)。

我进行了很多搜索,但未找到无需重新着色特定像素(setPixel()).. ect。的精灵对象。

我们不能以某种方式仅将颜色替换为精灵上的另一种颜色吗?例如,对于此精灵,默认情况下BLUE的RGB渲染等于RED?

小智 5

您可以使用着色器实现所需的功能。您需要创建新的材质,为其指定着色器,然后将该材质分配给场景中的图像组件。这是着色器代码:

Shader "PiotrMitrega/ColorSwap"
{
    Properties
    {
        _MainTex("Sprite", 2D) = "white" {}
        _ColorToChange("Color You Want To Change", Color) = (0,0,1,1)
        _DesiredColor("Desired Color ", Color) = (1,0,0,1)
    }
    SubShader
    {
        Tags
        {
            "RenderType" = "Opaque"
            "Queue" = "Transparent+1"
        }

        Pass
        {
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #pragma multi_compile DUMMY PIXELSNAP_ON

        sampler2D _MainTex;
        float4 _ColorToChange;
        float4 _DesiredColor;

        struct Vertex
        {
            float4 vertex : POSITION;
            float2 uv_MainTex : TEXCOORD0;
            float2 uv2 : TEXCOORD1;
        };

        struct Fragment
        {
            float4 vertex : POSITION;
            float2 uv_MainTex : TEXCOORD0;
            float2 uv2 : TEXCOORD1;
        };

        Fragment vert(Vertex v)
        {
            Fragment o;

            o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
            o.uv_MainTex = v.uv_MainTex;
            o.uv2 = v.uv2;

            return o;
        }

        float4 frag(Fragment IN) : COLOR
        {
            half4 c = tex2D(_MainTex, IN.uv_MainTex);

                if (c.r >= _ColorToChange.r - 0.005 && c.r <= _ColorToChange.r + 0.005
                && c.g >= _ColorToChange.g - 0.005 && c.g <= _ColorToChange.g + 0.005
                    && c.b >= _ColorToChange.b - 0.005 && c.b <= _ColorToChange.b + 0.005)
            {
                return _DesiredColor;
            }

            return c;
        }
            ENDCG
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我不太擅长编写着色器,因此绝对可以编写更好的着色器。但是无论如何,它确实可以做到。

这就是您应该在现场设置的方式

使用着色器的结果

但是,您可以看到它在边缘上不起作用。那是因为您的纹理是这样制作的。身体,腿和头不是纯色。因此它只交换一种特定的颜色。

请记住,如果您不会在纹理导入设置中设置“点”滤镜模式,则边缘将更加模糊(即使您的纹理到处都是纯色)

因此,如果纹理上到处都有纯色,则着色器将完全正常地工作。但是,例如给定的纹理(边缘模糊),我们可以使用另一种方法。我们可以分别为r,g,b分量手动定义最小值/最大值,并为所需范围内的所有内容交换颜色。这是着色器代码:

Shader "PiotrMitrega/ColorSwap-Range"
{
    Properties
    {
        _MainTex("Sprite", 2D) = "white" {}
        _MinG("Minimum Green Value", Float) = 0.5
        _MaxG("Maximum Green Value", Float) = 1
        _MinB("Minimum Blue Value", Float) = 0.5
        _MaxB("Maximum Blue Value", Float) = 1
        _MinR("Minimum Red Value", Float) = 0.5
        _MaxR("Maximum Red Value", Float) = 1
        _DesiredColor("Desired Color ", Color) = (1,0,0,1)
    }
    SubShader
    {
        Tags
        {
            "RenderType" = "Opaque"
            "Queue" = "Transparent+1"
        }

        Pass
        {
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #pragma multi_compile DUMMY PIXELSNAP_ON

        sampler2D _MainTex;
        float4 _DesiredColor;
        float _MinG;
        float _MaxG;
        float _MinB;
        float _MaxB;
        float _MinR;
        float _MaxR;

        struct Vertex
        {
            float4 vertex : POSITION;
            float2 uv_MainTex : TEXCOORD0;
            float2 uv2 : TEXCOORD1;
        };

        struct Fragment
        {
            float4 vertex : POSITION;
            float2 uv_MainTex : TEXCOORD0;
            float2 uv2 : TEXCOORD1;
        };

        Fragment vert(Vertex v)
        {
            Fragment o;

            o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
            o.uv_MainTex = v.uv_MainTex;
            o.uv2 = v.uv2;

            return o;
        }

        float4 frag(Fragment IN) : COLOR
        {
            half4 c = tex2D(_MainTex, IN.uv_MainTex);
            if (c.g >= _MinG && c.g <= _MaxG
                && c.r >= _MinR && c.r <= _MaxR
                && c.b >= _MinB && c.b <= _MaxB)
            {
                return _DesiredColor;
            }

            return c;
        }
            ENDCG
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

通过以最小/最大值播放一点,您绝对可以得到想要的效果。

如果要具有几个预定义的效果,例如“红色衬衫”,“棕色裤子”等,则应创建一些材料,更改其参数以符合您的要求,然后根据当前需要进行交换。

希望能帮助到你!