본문 바로가기

개발/Unity, C#

Unity 배경을 투명하게 캡처하는 방법

(URP프로젝트에서는 안 됨)

 

광고를 위해 배경을 투명하게 캡처해야 할 일이 생겨서 R&D함

 

그냥 렌더 텍스쳐를 png로 뽑으면 될 줄 알았는데..

 

잘 안 되서 여기저기 검색해서 정리해봄

 

 

using System.Collections;
using UnityEngine;

public class TransparencyCapture : MonoBehaviour
{
    public Camera _camera;

    private void Update()
    {
        if (Input.GetKey(KeyCode.Space))
        {
            Capture();
        }
    }

    private void Capture()
    {
        string path = Application.dataPath + "/capture.png";
        StartCoroutine(CoCapture(path));
    }

    private IEnumerator CoCapture(string path)
    {
        if (path == null)
        {
            yield break;
        }

        // ReadPixels을 하기 위해서 쉬어줌
        yield return new WaitForEndOfFrame();

        Rect rect = new Rect(0f, 0f, Screen.width, Screen.height);
        Texture2D texture = Capture(Camera.main, rect);

        byte[] bytes = texture.EncodeToPNG();
        System.IO.File.WriteAllBytes(path, bytes);
    }

    private Texture2D Capture(Camera camera, Rect pRect)
    {
        Texture2D capture;
        CameraClearFlags preClearFlags = camera.clearFlags;
        Color preBackgroundColor = camera.backgroundColor;
        {
            camera.clearFlags = CameraClearFlags.SolidColor;

            camera.backgroundColor = Color.black;
            camera.Render();
            Texture2D blackBackgroundCapture = CaptureView(pRect);

            camera.backgroundColor = Color.white;
            camera.Render();
            Texture2D whiteBackgroundCapture = CaptureView(pRect);

            for (int x = 0; x < whiteBackgroundCapture.width; ++x)
            {
                for (int y = 0; y < whiteBackgroundCapture.height; ++y)
                {
                    Color black = blackBackgroundCapture.GetPixel(x, y);
                    Color white = whiteBackgroundCapture.GetPixel(x, y);
                    if (black != Color.clear)
                    {
                        whiteBackgroundCapture.SetPixel(x, y, GetColor(black, white));
                    }
                }
            }

            whiteBackgroundCapture.Apply();
            capture = whiteBackgroundCapture;
            Object.DestroyImmediate(blackBackgroundCapture);
        }
        camera.backgroundColor = preBackgroundColor;
        camera.clearFlags = preClearFlags;
        return capture;
    }

    private Color GetColor(Color black, Color white)
    {
        float alpha = GetAlpha(black.r, white.r);
        return new Color(
            black.r / alpha,
            black.g / alpha,
            black.b / alpha,
            alpha);
    }

    private float GetAlpha(float black, float white)
    {
        return 1 + black - white;
    }

    private Texture2D CaptureView(Rect rect)
    {
        Texture2D captureView = new Texture2D((int)rect.width, (int)rect.height, TextureFormat.ARGB32, false);
        captureView.ReadPixels(rect, 0, 0, false);
        return captureView;
    }
}

 

 

잘나온 거 같은데 완벽하진 않은 것 같음

'개발 > Unity, C#' 카테고리의 다른 글

Unity 2Pass Outline Toon Shader  (0) 2020.12.26
Unity 하드웨어 스펙으로 자동 옵션 세팅하기  (0) 2020.10.18
C# Closure 클로저  (0) 2020.04.18
Unity 2019.3 URP Camera Stacking  (0) 2020.04.04
Unity Safe Area, Device Simulator  (0) 2019.12.29