Захват последовательности изображений камеры в единстве - PullRequest
0 голосов
/ 14 июня 2019

В Unity у меня есть следующий метод, который берет камеру и создает прозрачное изображение (которое уже хорошо работает).RenderTexture rt создается и создается вне этого метода.

Texture2D reallyTakeShot() {
camera.backgroundColor = Color.white;
Texture2D texWhite = new Texture2D(width, height, TextureFormat.RGB24, mipmap: false);
DoCameraRender(camera, shader);
RenderTexture.active = rt;
texWhite.ReadPixels(new Rect(0f, 0f, width, height), 0, 0);
texWhite.Apply();
camera.backgroundColor = Color.black;
DoCameraRender(camera, shader);
Texture2D texBlack = new Texture2D(width, height, TextureFormat.RGB24, mipmap: false);
texBlack.ReadPixels(new Rect(0f, 0f, width, height), 0, 0);
texBlack.Apply();
Texture2D transparentTexture = new Texture2D(width, height, TextureFormat.ARGB32, mipmap: false);
for (int y = 0; y < transparentTexture.height; ++y)
{
  for (int x = 0; x < transparentTexture.width; ++x)
  {
    float alpha = 1.0f - (texWhite.GetPixel(x, y).r - texBlack.GetPixel(x, y).r);
    Color color;
    if ((int)(alpha * 100) == 0)
    {
      color = Color.clear;
    }
    else
    {
      color = texBlack.GetPixel(x, y) / alpha;
      color.a = alpha;
    }
    transparentTexture.SetPixel(x, y, color);
  }
}
return transparentTexture;

Я пытаюсь сделать серию снимков, которые на самом деле не должны быть на 100% гладкими, но я не получаю многоудачи.Из 30 захватов, большинство из них выглядят одинаково.

Самым последним, что я сделал, был цикл, который вызывает

, который имеет следующий метод (который выводит 0 мс, чтобы сделать захват так,Я предполагаю, что это быстро)

private IEnumerator TakeShotNoWrite()
{
  shooting = CaptureStates.Capturing;
  Stopwatch sw = new Stopwatch();
  bool useJpeg = ModPrefs.GetBool("HomeShot", "use_jpeg");
  int outputWidth = ModPrefs.GetInt("HomeShot", "output_width");
  Texture2D tex = TakeShotToTexture2(!useJpeg);
  caps.Add(tex);
  shooting = CaptureStates.NormalCapture;
  Console.WriteLine("capture took " + sw.Elapsed.TotalMilliseconds + "ms");
  yield return new WaitForFixedUpdate();
  // tried these too
  // yield return 0;
  // yield return WaitForNextFrame();
}

Я запускаю камеру на FixedUpdate() (это единственный раз, когда я могу заставить объекты выглядеть правильно LateUpdate() не работает)

private void FixedUpdate()
{
  if (shooting == CaptureStates.Capturing)
  {
    return;
  }
  if (shooting != CaptureStates.NotCapturing)
  {
    // Extra StopWatch logic so I can increase the minimum time 
    // before next screen shot I set it to 30ms.
    StartCoroutine(TakeShotNoWrite()); // the render to texture code is above.

    // when stopwatch reaches 15 seconds start writing the files
  }
}

1 Ответ

0 голосов
/ 17 июня 2019

Это моя реализация.Я могу получить 200 снимков за 10 секунд (около 20 кадров в секунду), сохраненных в 1080p.Но это уменьшает до 60 кадров в течение 10 секунд при 4K.Я думаю, что это двойной рендер, но это удовлетворяет то, что мне нужно на данный момент.

public class BurstShooter : MonoBehaviour
{
    private Camera camera;
    private Texture2D[] blacks;
    private Texture2D[] whites;

    /**
     * Number of captures
     */
    private int caps;

    private int width;
    private int height;

    private int burstSeconds;
    private int burstInterval;
    private Stopwatch burstWatch = new Stopwatch();
    private Color backgroundColor;
    private RenderTexture rt;
    private double lastBurstMillis;

    private void Start()
    {
    }

    public void Shoot()
    {
        if (!burstWatch.IsRunning)
        {
            StartCoroutine(TakeBurstShotCoroutine());
        }
    }
    private IEnumerator<YieldInstruction> TakeBurstShotCoroutine()
    {
        StartTakeBurstShot();
        while (burstWatch.Elapsed.TotalSeconds < burstSeconds && caps < blacks.Length)
        {
            yield return new WaitForEndOfFrame();
            if (burstWatch.Elapsed.TotalMilliseconds - lastBurstMillis > burstInterval)
            {
                lastBurstMillis = burstWatch.Elapsed.TotalMilliseconds;
                TakeBurstShot();
            }
        }
        burstWatch.Stop();
        RenderTexture.ReleaseTemporary(rt);
        yield return new WaitForEndOfFrame();

        // Flush Caps takes the Texture2Ds and 
        // converts them to PNG.  Not going to 
        // bother with this as it is outside 
        //the scope of the question.
        FlushCaps();
    }

    private void StartTakeBurstShot()
    {

        // these can be larger than the screen
        width = 1920;
        height = 1080;
        rt = getRenderTexture();
        SelectCamera();
        backgroundColor = camera.backgroundColor;

        burstInterval = 15;
        burstSeconds = 15;

        // assume 60 frames per second max
        blacks = new Texture2D[60 * burstSeconds];
        whites = new Texture2D[60 * burstSeconds];
        caps = 0;

        burstWatch.Reset();
        burstWatch.Start();
        lastBurstMillis = -burstInterval;
    }

    private void TakeBurstShot()
    {
        Stopwatch sw = new Stopwatch();
        sw.Reset();
        sw.Start();
        try
        {
            camera.targetTexture = rt;
            RenderTexture.active = rt;

            Texture2D texWhite = new Texture2D(width, height, TextureFormat.RGB24, mipmap: false);
            texWhite.filterMode = FilterMode.Point;
            texWhite.wrapMode = TextureWrapMode.Clamp;

            Texture2D texBlack = new Texture2D(width, height, TextureFormat.RGB24, mipmap: false);
            texBlack.filterMode = FilterMode.Point;
            texBlack.wrapMode = TextureWrapMode.Clamp;

            camera.backgroundColor = Color.white;
            camera.Render();
            texWhite.ReadPixels(new Rect(0f, 0f, width, height), 0, 0);
            texWhite.Apply();

            camera.backgroundColor = Color.black;
            camera.Render();
            texBlack.ReadPixels(new Rect(0f, 0f, width, height), 0, 0);
            texBlack.Apply();

            blacks[caps] = texBlack;
            whites[caps] = texWhite;
            ++caps;
        }
        finally
        {
            camera.backgroundColor = backgroundColor;
            RenderTexture.active = null;
            camera.targetTexture = null;
        }

    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...