Raikish
Raikish

Reputation: 744

Blend 2 Textures Unity C#

How can I blend two textures into a new one?

I have a texture from the android gallery and some logo png texture. I need to add this logo into the texture from the gallery and store this as variable to save into the gallery as a new image.

Upvotes: 0

Views: 6585

Answers (4)

Intraterrestrial
Intraterrestrial

Reputation: 46

I made this solution, It works with two texture2d in Unity.

public Texture2D ImageBlend(Texture2D Bottom, Texture2D Top)
{
    var bData = Bottom.GetPixels();
    var tData = Top.GetPixels();
    int count = bData.Length;
    var final = new Color[count];
    int i = 0;
    int iT = 0;
    int startPos = (Bottom.width / 2) - (Top.width / 2) -1;
    int endPos = Bottom.width - startPos -1;

    for (int y = 0; y < Bottom.height; y++)
    {
        for (int x = 0; x < Bottom.width; x++)
        {
            if (y > startPos && y < endPos && x > startPos && x < endPos)
            {
                Color B = bData[i];
                Color T = tData[iT];
                Color R;

                R = new Color((T.a * T.r) + ((1-T.a) * B.r),
                    (T.a * T.g) + ((1 - T.a) * B.g),
                    (T.a * T.b) + ((1 - T.a) * B.b), 1.0f);
                final[i] = R;
                i++;
                iT++;
            }
            else
            {
                final[i] = bData[i];
                i++;
            }
        }
    }
    var res = new Texture2D(Bottom.width, Bottom.height);
    res.SetPixels(final);
    res.Apply();
    return res;
}

Upvotes: 0

serge
serge

Reputation: 1609

It's an old question but I have another solution:

public static Texture2D merge(params Texture2D[] textures) {
        if (textures == null || textures.Length == 0)
            return null;
        int oldQuality = QualitySettings.GetQualityLevel();
        QualitySettings.SetQualityLevel(5);
        RenderTexture renderTex = RenderTexture.GetTemporary(
        textures[0].width,
        textures[0].height,
        0,
        RenderTextureFormat.Default,
        RenderTextureReadWrite.Linear);

        Graphics.Blit(textures[0], renderTex);
        RenderTexture previous = RenderTexture.active;
        RenderTexture.active = renderTex;
        GL.PushMatrix();
        GL.LoadPixelMatrix(0, textures[0].width, textures[0].height, 0);
        for (int i = 1; i < textures.Length; i++)
            Graphics.DrawTexture(new Rect(0, 0, textures[0].width, textures[0].height), textures[i]);
        GL.PopMatrix();
        Texture2D readableText = new Texture2D(textures[0].width, textures[0].height);
        readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
        readableText.Apply();
        RenderTexture.active = previous;
        RenderTexture.ReleaseTemporary(renderTex);
        QualitySettings.SetQualityLevel(oldQuality);
        return readableText;
    }

And here is the use:

Texture2D coloredTex = ImageUtils.merge(tex,
            sprites[0].texture,
            sprites[1].texture,
            sprites[2].texture,
            sprites[3].texture);

Hope it helps

Upvotes: 0

JShepp
JShepp

Reputation: 1

I had a similar task with a paint tool I was making. So here's my approach: First, import or instantiate logo and picture textures as Texture2D in order to use Texture2D.GetPixel() and Texture2D.SetPixel() methods. Assuming that logo size is smaller than picture itself, store logo pixels into the Color[] array:

Color[] logoPixels = logo.GetPixels();

We need to apply logo above the picture, considering alpha level in logo image itself:

//Method GetPixels stores pixel colors in 1D array
int i = 0; //Logo pixel index
for (int y = 0; y < picture.height; y++) {
  for (int x = 0; x < picture.width; x++) {
    //Get color of original pixel
    Color c = picture.GetPixel (logoPositionX + x, logoPositionY + y);
    //Lerp pixel color by alpha value 
    picture.SetPixel (logoPositionX + x, logoPositionY + y, Color.Lerp (c, logoPixels[i], logoPixels[i].a));
    i++;
  }
}
//Apply changes
picture.Apply();

So, if pixel's alpha = 0 we leave it without changes. Get bytes of resulting image with picture.GetRawTextureData() and save it as png in a regular way. And to use SetPixel() and SetPixels() methods, make sure both, logo and picture it being applied to, are set Read/Write enabled in the import settings!

Upvotes: 0

Joey Phillips
Joey Phillips

Reputation: 1625

These shaders blend between two textures based on a 0-1 value that you control. The first version is extra-fast because it does not use lighting, and the second uses the same basic ambient + diffuse calculation that I used in my Simply Lit shader.

http://wiki.unity3d.com/index.php/Blend_2_Textures

Drag a different texture onto each of the material's variable slots, and use the Blend control to mix them to taste.

Take note that the lit version requires two passes on the GPU used in the oldest iOS devices.

ShaderLab - Blend 2 Textures.shader

Shader "Blend 2 Textures" { 

Properties {
    _Blend ("Blend", Range (0, 1) ) = 0.5 
    _MainTex ("Texture 1", 2D) = "" 
    _Texture2 ("Texture 2", 2D) = ""
}

SubShader { 
    Pass {
        SetTexture[_MainTex]
        SetTexture[_Texture2] { 
            ConstantColor (0,0,0, [_Blend]) 
            Combine texture Lerp(constant) previous
        }       
    }
} 

}

ShaderLab - Blend 2 Textures, Simply Lit.shader

Shader "Blend 2 Textures, Simply Lit" { 

Properties {
    _Color ("Color", Color) = (1,1,1)
    _Blend ("Blend", Range (0,1)) = 0.5 
    _MainTex ("Texture 1", 2D) = "" 
    _Texture2 ("Texture 2", 2D) = ""
}

Category {
    Material {
        Ambient[_Color]
        Diffuse[_Color]
    }

    // iPhone 3GS and later
    SubShader {Pass {
        Lighting On
        SetTexture[_MainTex]
        SetTexture[_Texture2] { 
            ConstantColor (0,0,0, [_Blend]) 
            Combine texture Lerp(constant) previous
        }
        SetTexture[_] {Combine previous * primary Double}
    }}

    // pre-3GS devices, including the September 2009 8GB iPod touch
    SubShader {
        Pass {
            SetTexture[_MainTex]
            SetTexture[_Texture2] {
                ConstantColor (0,0,0, [_Blend])
                Combine texture Lerp(constant) previous
            }
        }
        Pass {
            Lighting On
            Blend DstColor SrcColor
        }
    }
}

}

Upvotes: 1

Related Questions