Problem with color in texture output

Hey guys, I stumbled upon this little plugin that can combine maps into new map formats,

It uses a custom shader to pack the channels together to a new textures and then saves is.

I want to convert a RMA map to Unity metalness map.

I have done it manual in Photoshop and now with the tool (I have created my own version of it that inverts the alpha channel (Rma uses roughness and Unity smoothness). I invert like this

            float4 SwapChannels(sampler2D tex, float2 uv, float4 e, float4 inv, float4x4 v)
            {
                float4 inColor = tex2D(tex, uv);
               
                float4 r = (inv[0] ? (1-inColor.rrrr) : inColor.rrrr) * v[0] * e.r;
                float4 g = (inv[1] ? (1-inColor.gggg) : inColor.gggg) * v[1] * e.g;
                float4 b = (inv[2] ? (1-inColor.bbbb) : inColor.bbbb) * v[2] * e.b;
                float4 a = (inv[3] ? (1-inColor.aaaa) : inColor.aaaa) * v[3] * e.a;

                return r + g + b + a;
            }

The output is however slightly off, I import both with sRBG disabled

The one made from the plugin seems a bit overexposed etc

I’m I inverting the Smothness map wrong or something?

Are you using this function to blit a texture to a new texture file?

If so, part of the issue is that you’re going to get bilinear texture filtering applied because you’re using the default sampler there.

Outside of the function, define SamplerState my_point_clamp_sampler;
And then to sample a pixel do float4 inColor = tex.Sample(my_point_clamp_sampler, uv);
(Though you might have to make the function take in a Texture2D instead of a sampler2D, and then the compiler might throw warnings at you which you can solve using some unity built-in methods for defining this stuff…)

Also are you making sure each float4 in your 4x4 “v” input has only one of its values set to 1 and none of them have the same value set to 1 there? Otherwise you will get channel merging.

1 Like

Thnaks im a complete noob when it comes to shaders and channels
The shader in whole (Minus my invert changes)

Shader "Hidden/TexturePacker"
{
    Properties
    {
        _Input00Tex ("Input00", 2D) = "black" {}
        _Input01Tex ("Input01", 2D) = "black" {}
        _Input02Tex ("Input02", 2D) = "black" {}
        _Input03Tex ("Input03", 2D) = "black" {}

        _Input00In ("Input00 In", Vector) = (0,0,0,0)
        _Input01In ("Input01 In", Vector) = (0,0,0,0)
        _Input02In ("Input02 In", Vector) = (0,0,0,0)
        _Input03In ("Input03 In", Vector) = (0,0,0,0)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 4.6
          
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            sampler2D _Input00Tex;
            sampler2D _Input01Tex;
            sampler2D _Input02Tex;
            sampler2D _Input03Tex;

            float4 _Input00In;
            float4 _Input01In;
            float4 _Input02In;
            float4 _Input03In;
          
            float4x4 _Input00Out;
            float4x4 _Input01Out;
            float4x4 _Input02Out;
            float4x4 _Input03Out;
          
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            float4 SwapChannels(sampler2D tex, float2 uv, float4 e, float4x4 v)
            {
                float4 inColor = tex2D(tex, uv);
              
                float4 r = inColor.rrrr * v[0] * e.r;
                float4 g = inColor.gggg * v[1] * e.g;
                float4 b = inColor.bbbb * v[2] * e.b;
                float4 a = inColor.aaaa * v[3] * e.a;

                return r + g + b + a;
            }
          
            fixed4 frag (v2f i) : SV_Target
            {
                float4 c00 = SwapChannels(_Input00Tex, i.uv, _Input00In, _Input00Out);
                float4 c01 = SwapChannels(_Input01Tex, i.uv, _Input01In, _Input01Out);
                float4 c02 = SwapChannels(_Input02Tex, i.uv, _Input02In, _Input02Out);
                float4 c03 = SwapChannels(_Input03Tex, i.uv, _Input03In, _Input03Out);
                return c00 + c01 + c02 + c03;
            }
            ENDCG
        }
    }
}

The code that sets the matrix

        private Matrix4x4 GetOutputs(TextureInput texInput)
        {
            Matrix4x4 m = Matrix4x4.zero;

            for (int i = 0; i < 4; ++i)
            {
                Vector4 inChannel = Vector4.zero;
                var output = texInput.GetChannelInput((TextureChannel)i).output;
                inChannel[(int)output] = 1f;
                m.SetRow(i, inChannel);
            }

            return m;
        }

Output to file

 Texture2D output = _texturePacker.Create();                
File.WriteAllBytes(savePath, output.EncodeToTGA());