unity下貼圖混合(Texture Blending)


在unity制作自定義時,經常會遇到自定義妝容等問題,美術會提供大量的眉毛/胡子/腮紅等貼圖,來供用戶選擇。

美術給出的眉毛的小貼圖如下:

在用戶選用不同的胡子眉毛,可以將選定的小貼圖和皮膚base貼圖進行融合,得到完整的Character貼圖。

       

 

Method1:CPU端逐像素根據alpha通道進行疊加。

public void MergeTexture_(Texture2D tt1, Texture2D tt2, int offsetX, int offsetY)
        {

            Texture2D newTex = new Texture2D(tt1.width, tt1.height, TextureFormat.ARGB32, false);

            newTex.SetPixels(tt1.GetPixels());

            for (int x = 0; x < tt2.width; x++)
            {
                for (int y = 0; y < tt2.height; y++)
                {
                    var PixelColorFore = tt2.GetPixel(x, y) * tt2.GetPixel(x, y).a;
                    var newY = tt1.height - offsetY - tt2.height + y;
                    var PixelColorBack = tt1.GetPixel(x + offsetX, newY) * tt1.GetPixel(x + offsetX, newY).a;
                    newTex.SetPixel(x + offsetX, newY, PixelColorFore+ PixelColorBack);
                }
            }
            newTex.Apply();
             System.IO.File.WriteAllBytes(Application.dataPath + "/" + tt1.name + ".png", newTex.EncodeToPNG());
            GameObject.Find("obj001").GetComponent<Renderer>().material.mainTexture = newTex;
        }

這里注意下,由於需要對Texture進行讀取像素,因此需要將相應的Texture設置為Read/Write Enabled,否則會報錯。

逐像素操作可以用unity內置函數改為塊操作,經過測試,能大概少一半的耗時

 1 public void MergeTexture(Texture2D tt1, Texture2D tt2, int offsetX, int offsetY)
 2         {
 3             
 4             Texture2D newTex= new Texture2D(tt1.width, tt1.height, TextureFormat.ARGB32, false);
 5             
 6             newTex.SetPixels(tt1.GetPixels());
 7             Color32[] colors = tt2.GetPixels32();
 8             // tt1.
 9             newTex.SetPixels32(offsetX, tt1.height - offsetY - tt2.height,tt2.width,tt2.height, colors,0);
10             newTex.Apply();
11             GameObject.Find("obj001").GetComponent<Renderer>().material.mainTexture = newTex;
12         }

上述方案基本上是在CPU端進行的,實際上可以調用Unity的底層繪制接口在GPU上進行操作,主要是利用RenderTexture和Graphics.DrawTexture()進行操作

 public Texture2D texture;        //Starting image.
    public Texture2D stampTexture;   //Texture to Graphics.Drawtexture on my RenderTexture.
    public float posX = 256f;        //Position the DrawTexture command while testing.
    public float posY = 256f;        //Position the DrawTexture command while testing.
    RenderTexture rt;                //RenderTexture to use as buffer.

    void Start()
    {
        rt = new RenderTexture(1024, 1024, 32);           //Create RenderTexture 512x512 pixels in size.
        GameObject.Find("obj001").GetComponent<Renderer>().material.mainTexture = rt;   //Assign my RenderTexure to be the main texture of my object.
        RenderTexture.active = rt;
        Graphics.Blit(texture, rt);          //Blit my starting texture to my RenderTexture.
        RenderTexture.active = rt;                      //Set my RenderTexture active so DrawTexture will draw to it.
        GL.PushMatrix();                                //Saves both projection and modelview matrices to the matrix stack.
        GL.LoadPixelMatrix(0, 1024, 1024, 0);            //Setup a matrix for pixel-correct rendering.
                                                         //Draw my stampTexture on my RenderTexture positioned by posX and posY.
        Graphics.DrawTexture(new Rect(posX, posY, stampTexture.width, stampTexture.height), stampTexture);
        Texture2D png = new Texture2D(rt.width, rt.height, TextureFormat.ARGB32, false);
        png.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
        System.IO.File.WriteAllBytes(Application.dataPath + "/" + "nihao.png", png.EncodeToPNG());
        GL.PopMatrix();
        //Restores both projection and modelview matrices off the top of the matrix stack.
        RenderTexture.active = null;                    //De-activate my RenderTexture.   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM