美术工具:截半透明UI

2024/06 05 18:06

一般摄像机都会带清除颜色,截图出来的图是混合之后的。

美术希望,某些UI去掉底图后,截图可以保持透明;


原理就是先用全白的颜色做底,渲染后抓一屏

再用全黑的颜色做底,渲染后抓一屏

再通过2张图插值获得Alpha值


以下为代码

#if UNITY_EDITOR

using UnityEngine;
using UnityEditor;
using System.Collections;
using System;
using System.IO;

public class CaptureTransparentUI: MonoBehaviour
{
    [MenuItem("Tools/CaptureTransparentUI")]
    public static void Capture()
    {
        var baseCameraObj = GameObject.Find("【主摄像机的路径】");
        if (baseCameraObj != null)
        {
            baseCameraObj.AddComponent<CaptureTransparentUI>();
        }
    }

    void Start()
    {
        var time = DateTime.Now.ToString("yyyy-MM-dd HH.mm.ss");
        StartCoroutine(CaptureTask($"Assets/{time}.png"));
    }

    IEnumerator CaptureTask(string outputFilename)
    {
        var camera = GetComponent<Camera>();
        if (camera == null)
        {
            yield break;
        }

        const string whiteFilename = "white.png";
        const string blackFilename = "black.png";

        yield return new WaitForEndOfFrame();
        camera.backgroundColor = Color.white;
        yield return new WaitForEndOfFrame();
        yield return new WaitForEndOfFrame();
        ScreenCapture.CaptureScreenshot(whiteFilename);
        yield return new WaitForEndOfFrame();
        yield return new WaitForEndOfFrame();
        camera.backgroundColor = Color.clear;
        yield return new WaitForEndOfFrame();
        yield return new WaitForEndOfFrame();
        ScreenCapture.CaptureScreenshot(blackFilename);
        yield return new WaitForEndOfFrame();
        yield return new WaitForEndOfFrame();

        var textureBlack = new Texture2D(2, 2);
        textureBlack.LoadImage(System.IO.File.ReadAllBytes(blackFilename));

        var textureWhite = new Texture2D(2, 2);
        textureWhite.LoadImage(System.IO.File.ReadAllBytes(whiteFilename));

        var textureTransparentBackground = new Texture2D(textureBlack.width, textureBlack.height, TextureFormat.ARGB32, false);


        for (int y = 0; y < textureBlack.height; ++y)
        {
            for (int x = 0; x < textureBlack.width; ++x)
            {
                var blackPixel = textureBlack.GetPixel(x, y);
                var whitePixel = textureWhite.GetPixel(x, y);
                textureTransparentBackground.SetPixel(x, y, LerpColor(whitePixel, blackPixel));
            }
        }

        var pngShot = textureTransparentBackground.EncodeToPNG();
        System.IO.File.WriteAllBytes(outputFilename, pngShot);
        System.IO.File.Delete(whiteFilename);
        System.IO.File.Delete(blackFilename);
    }

    static Color LerpColor(Color whitePixel, Color blackPixel)
    {
        float alpha = 1 - (whitePixel.r - blackPixel.r);
        if (alpha == 0)
        {
            return new Color(0,0,0,alpha);
        }
        else
        {
            var color = blackPixel / alpha;
            color.a = alpha;
            return color;
        }
    }
}

#endif