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

时间:2017-03-15 09:41:10

标签: c# unity3d colors sprite renderer

enter image description here

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

我搜索了很多,但没有找到使用精灵的东西,而没有重新定义细节像素(setPixel())..等..

我们不能以某种方式在精灵上用另一个颜色替换颜色吗?就像这个精灵的RGB BLUE渲染默认等于RED一样?

2 个答案:

答案 0 :(得分:2)

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

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

我在写作着色器方面不太合格,所以它绝对可以写得比这更好。但无论如何,它确实起到了作用。

That's how you should setup this on the scene

Result of using shader

但是,你可以看到它没有处理边缘。这是因为你的纹理是这样的。身体,腿部和头部都不是纯色。所以它只交换一种特定的颜色。

请记住,如果你没有设置&#34; Point&#34;在纹理导入设置中的滤镜模式,您的边缘将更加模糊(即使您的纹理到处都是纯色)

所以,如果你的纹理上到处都是纯色,那么着色器就可以正常工作了。但是,例如给出的纹理(边缘模糊)我们可以使用另一种方法。我们可以手动为单独的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
        }
    }
}

通过使用最小值/最大值进行一点点游戏,您肯定能够获得理想的效果。

如果你想要有几个预定义效果,比如&#34;红色衬衫&#34;,&#34;棕色裤子&#39;等等,您应该创建几种材料,根据您​​的要求更改其参数,然后根据您当前的需要进行交换。

希望它有所帮助!

答案 1 :(得分:1)

我认为你可以使用其他材料而不是默认材料。你可以改变颜色或切断它看起来可能的精灵。

https://docs.unity3d.com/Manual/Materials.html