Захват последовательности рендеринга камеры в единстве

В 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
  }
}

Я решил эту проблему, переместив операцию прозрачности за пределы камеры и используя сопрограммы и yieldWaitForEndFrame.

Archimedes Trajano 14.06.2019 08:56

Пожалуйста, опубликуйте свой ответ как «Ответ» и примите его, чтобы, если у кого-то еще возникла такая же проблема, он мог ее найти.

Mohammad Zamanian 14.06.2019 10:20
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
167
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это моя реализация. Я могу сделать 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;
        }

    }
}

Другие вопросы по теме