123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- #if UNITY_5_4_OR_NEWER || UNITY_5
- #define AVPRO_MOVIECAPTURE_DEFERREDSHADING
- #endif
- using UnityEngine;
- //-----------------------------------------------------------------------------
- // Copyright 2012-2017 RenderHeads Ltd. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace RenderHeads.Media.AVProMovieCapture
- {
- /// <summary>
- /// Capture from a specific Unity camera. This component re-renders the camera manually, so it does add extra draw calls.
- /// </summary>
- //[RequireComponent(typeof(Camera))]
- [AddComponentMenu("AVPro Movie Capture/Capture From Camera", 1)]
- public class CaptureFromCamera : CaptureBase
- {
- [SerializeField]
- private Camera _lastCamera;
- [SerializeField]
- private Camera[] _contribCameras;
- [SerializeField]
- private bool _useContributingCameras = true;
- private RenderTexture _target;
- private System.IntPtr _targetNativePointer = System.IntPtr.Zero;
- public bool UseContributingCameras
- {
- get { return _useContributingCameras; }
- set { _useContributingCameras = value; }
- }
- public void SetCamera(Camera mainCamera, bool useContributingCameras = true)
- {
- _lastCamera = mainCamera;
- _contribCameras = null;
- _useContributingCameras = useContributingCameras;
- if (_useContributingCameras && _lastCamera != null)
- {
- if (Utils.HasContributingCameras(_lastCamera))
- {
- _contribCameras = Utils.FindContributingCameras(mainCamera);
- }
- }
- }
- public void SetCamera(Camera mainCamera, Camera[] contributingCameras)
- {
- _lastCamera = mainCamera;
- _contribCameras = contributingCameras;
- }
- private bool HasCamera()
- {
- return (_lastCamera != null);
- }
- private bool HasContributingCameras()
- {
- return (_useContributingCameras && _contribCameras != null && _contribCameras.Length > 0);
- }
- // If we're forcing a resolution or AA change then we have to render the camera again to the new target
- // If we try to just set the targetTexture of the camera and grab it in OnRenderImage we can't render it to the screen as before :(
- public override void UpdateFrame()
- {
- TickFrameTimer();
- if (_capturing && !_paused && HasCamera())
- {
- bool canGrab = true;
- if (IsUsingMotionBlur())
- {
- // If the motion blur is still accumulating, don't grab this frame
- canGrab = _motionBlur.IsFrameAccumulated;
- }
- if (canGrab)
- {
- /*while (_handle >= 0 && !AVProMovieCapturePlugin.IsNewFrameDue(_handle))
- {
- System.Threading.Thread.Sleep(1);
- }*/
- if (_handle >= 0 && CanOutputFrame())
- {
- // Render the camera(s)
- if (!IsUsingMotionBlur())
- {
- // Render a single camera
- if (!HasContributingCameras())
- {
- RenderTexture prev = _lastCamera.targetTexture;
- // Reset the viewport rect as we're rendering to a texture captures the full viewport
- Rect prevRect = _lastCamera.rect;
- CameraClearFlags prevClear = _lastCamera.clearFlags;
- Color prevColor = _lastCamera.backgroundColor;
- bool clearChanged = false;
- if (_lastCamera.clearFlags == CameraClearFlags.Nothing || _lastCamera.clearFlags == CameraClearFlags.Depth)
- {
- clearChanged = true;
- _lastCamera.clearFlags = CameraClearFlags.SolidColor;
- if (!_supportAlpha)
- {
- _lastCamera.backgroundColor = Color.black;
- }
- else
- {
- _lastCamera.backgroundColor = new Color(0f, 0f, 0f, 0f);
- }
- }
- // Render
- _lastCamera.rect = new Rect(0f, 0f, 1f, 1f);
- _lastCamera.targetTexture = _target;
- _lastCamera.Render();
- // Restore camera
- {
- _lastCamera.rect = prevRect;
- if (clearChanged)
- {
- _lastCamera.clearFlags = prevClear;
- _lastCamera.backgroundColor = prevColor;
- }
- _lastCamera.targetTexture = prev;
- }
- }
- // Render the camera chain
- else
- {
- // First render contributing cameras
- for (int cameraIndex = 0; cameraIndex < _contribCameras.Length; cameraIndex++)
- {
- Camera camera = _contribCameras[cameraIndex];
- if (camera != null)
- {
- RenderTexture prev = camera.targetTexture;
- camera.targetTexture = _target;
- camera.Render();
- camera.targetTexture = prev;
- }
- }
- // Finally render the last camera
- if (_lastCamera != null)
- {
- RenderTexture prev = _lastCamera.targetTexture;
- _lastCamera.targetTexture = _target;
- _lastCamera.Render();
- _lastCamera.targetTexture = prev;
- }
- }
- }
- else
- {
- // Just grab the last result of the motion blur
- Graphics.Blit(_motionBlur.FinalTexture, _target);
- }
- if (_supportTextureRecreate)
- {
- // NOTE: If support for captures to survive through alt-tab events, or window resizes where the GPU resources are recreated
- // is required, then this line is needed. It is very expensive though as it does a sync with the rendering thread.
- _targetNativePointer = _target.GetNativeTexturePtr();
- }
- NativePlugin.SetTexturePointer(_handle, _targetNativePointer);
- RenderThreadEvent(NativePlugin.PluginEvent.CaptureFrameBuffer);
- if (IsRecordingUnityAudio())
- {
- int audioDataLength = 0;
- System.IntPtr audioDataPtr = _audioCapture.ReadData(out audioDataLength);
- if (audioDataLength > 0)
- {
- NativePlugin.EncodeAudio(_handle, audioDataPtr, (uint)audioDataLength);
- }
- }
- UpdateFPS();
- }
- }
- }
- base.UpdateFrame();
- RenormTimer();
- }
- #if false
- // NOTE: This is old code based on OnRenderImage...may be revived at some point
- private void OnRenderImage(RenderTexture source, RenderTexture dest)
- {
- if (_capturing && !_paused)
- {
- #if true
- while (_handle >= 0 && !NativePlugin.IsNewFrameDue(_handle))
- {
- System.Threading.Thread.Sleep(1);
- }
- if (_handle >= 0)
- {
- if (_audioCapture && _audioDeviceIndex < 0 && !_noAudio && _isRealTime)
- {
- int audioDataLength = 0;
- System.IntPtr audioDataPtr = _audioCapture.ReadData(out audioDataLength);
- if (audioDataLength > 0)
- {
- NativePlugin.EncodeAudio(_handle, audioDataPtr, (uint)audioDataLength);
- }
- }
- // In Direct3D the RT can be flipped vertically
- /*if (source.texelSize.y < 0)
- {
- }*/
- Graphics.Blit(source, dest);
- _lastSource = source;
- _lastDest = dest;
- if (dest != _originalTarget)
- {
- Graphics.Blit(dest, _originalTarget);
- }
- #if AVPRO_MOVIECAPTURE_GLISSUEEVENT_52
- GL.IssuePluginEvent(NativePlugin.GetRenderEventFunc(), NativePlugin.PluginID | (int)NativePlugin.PluginEvent.CaptureFrameBuffer | _handle);
- #else
- GL.IssuePluginEvent(NativePlugin.PluginID | (int)NativePlugin.PluginEvent.CaptureFrameBuffer | _handle);
- #endif
- GL.InvalidateState();
-
- UpdateFPS();
- return;
- }
- #endif
- }
- // Pass-through
- Graphics.Blit(source, dest);
- _lastSource = source;
- _lastDest = dest;
- }
- #endif
- public override void UnprepareCapture()
- {
- NativePlugin.SetTexturePointer(_handle, System.IntPtr.Zero);
- if (_target != null)
- {
- _target.DiscardContents();
- }
- base.UnprepareCapture();
- }
- public override Texture GetPreviewTexture()
- {
- return _target;
- }
- public override bool PrepareCapture()
- {
- if (_capturing)
- {
- return false;
- }
- if (SystemInfo.graphicsDeviceVersion.StartsWith("OpenGL") && !SystemInfo.graphicsDeviceVersion.Contains("emulated"))
- {
- Debug.LogError("[AVProMovieCapture] OpenGL not yet supported for CaptureFromCamera component, please use Direct3D11 instead. You may need to switch your build platform to Windows.");
- return false;
- }
- // Setup material
- _pixelFormat = NativePlugin.PixelFormat.RGBA32;
- _isTopDown = true;
- if (!HasCamera())
- {
- _lastCamera = this.GetComponent<Camera>();
- if (!HasCamera())
- {
- _lastCamera = Camera.main;
- }
- if (!HasCamera())
- {
- Debug.LogError("[AVProMovieCapture] No camera assigned to CaptureFromCamera");
- return false;
- }
- }
- if (!HasContributingCameras() && (_lastCamera.clearFlags == CameraClearFlags.Depth || _lastCamera.clearFlags == CameraClearFlags.Nothing))
- {
- Debug.LogWarning("[AVProMovieCapture] This camera doesn't clear, consider setting contributing cameras");
- }
- int width = Mathf.FloorToInt(_lastCamera.pixelRect.width);
- int height = Mathf.FloorToInt(_lastCamera.pixelRect.height);
- // Setup rendering a different render target if we're overriding resolution or anti-aliasing
- //if (_renderResolution != Resolution.Original || (_renderAntiAliasing > 0 && _renderAntiAliasing != QualitySettings.antiAliasing))
- {
- if (_renderResolution == Resolution.Custom)
- {
- width = (int)_renderSize.x;
- height = (int)_renderSize.y;
- }
- else if (_renderResolution != Resolution.Original)
- {
- GetResolution(_renderResolution, ref width, ref height);
- }
- int aaLevel = GetCameraAntiAliasingLevel(_lastCamera);
- // Create the render target
- if (_target != null)
- {
- _target.DiscardContents();
- if (_target.width != width || _target.height != height || _target.antiAliasing != aaLevel)
- {
- _targetNativePointer = System.IntPtr.Zero;
- RenderTexture.ReleaseTemporary(_target);
- _target = null;
- }
- }
- if (_target == null)
- {
- _target = RenderTexture.GetTemporary(width, height, 24, RenderTextureFormat.Default, RenderTextureReadWrite.Default, aaLevel);
- _target.name = "[AVProMovieCapture] Camera Target";
- _target.Create();
- _targetNativePointer = _target.GetNativeTexturePtr();
- }
- //camera.targetTexture = _target;
- // Adjust size for camera rectangle
- /*if (camera.rect.width < 1f || camera.rect.height < 1f)
- {
- float rectWidth = Mathf.Clamp01(camera.rect.width + camera.rect.x) - Mathf.Clamp01(camera.rect.x);
- float rectHeight = Mathf.Clamp01(camera.rect.height + camera.rect.y) - Mathf.Clamp01(camera.rect.y);
- width = Mathf.FloorToInt(width * rectWidth);
- height = Mathf.FloorToInt(height * rectHeight);
- }*/
- if (_useMotionBlur)
- {
- _motionBlurCameras = new Camera[1];
- _motionBlurCameras[0] = _lastCamera;
- }
- }
- SelectRecordingResolution(width, height);
- GenerateFilename();
- return base.PrepareCapture();
- }
- public override void OnDestroy()
- {
- if (_target != null)
- {
- _targetNativePointer = System.IntPtr.Zero;
- RenderTexture.ReleaseTemporary(_target);
- _target = null;
- }
- base.OnDestroy();
- }
- }
- }
|