123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981 |
- #if UNITY_5_6_0 || UNITY_5_6_1
- #define AVPRO_MOVIECAPTURE_UNITYBUG_RENDERTOCUBEMAP_56
- #endif
- #if UNITY_2018_1_OR_NEWER
- // Unity 2018.1 introduces stereo cubemap render methods, but with no camera rotation
- #define AVPRO_MOVIECAPTURE_UNITY_STEREOCUBEMAP_RENDER
- #if UNITY_2018_2_OR_NEWER || UNITY_2018_1_9
- // Unity 2018.2 adds camera rotation
- #define AVPRO_MOVIECAPTURE_UNITY_STEREOCUBEMAP_RENDER_WITHROTATION
- #endif
- #endif
- using UnityEngine;
- using UnityEngine.Rendering;
- using System.Collections;
- //-----------------------------------------------------------------------------
- // Copyright 2012-2022 RenderHeads Ltd. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace RenderHeads.Media.AVProMovieCapture
- {
- /// <summary>
- /// Capture a camera view in 360 equi-rectangular format.
- /// The camera is rendered into a cubemap, so the scene is rendered an extra 6 times.
- /// Finally the cubemap is converted to equi-rectangular format and encoded.
- /// </summary>
- //[RequireComponent(typeof(Camera))]
- [AddComponentMenu("AVPro Movie Capture/Capture From Camera 360 (VR)", 100)]
- public class CaptureFromCamera360 : CaptureBase
- {
- [SerializeField] CameraSelector _cameraSelector = null;
- public CameraSelector CameraSelector
- {
- get { return _cameraSelector; }
- set { _cameraSelector = value; }
- }
- [SerializeField] Camera _camera = null;
- [SerializeField] CubemapResolution _cubemapResolution = CubemapResolution.POW2_2048;
- [SerializeField] CubemapDepth _cubemapDepth = CubemapDepth.Depth_24;
- public CubemapResolution CubemapFaceResolution
- {
- get { return _cubemapResolution; }
- set { _cubemapResolution = value; }
- }
- public CubemapDepth CubemapDepthResolution
- {
- get { return _cubemapDepth; }
- set { _cubemapDepth = value; }
- }
- [SerializeField] bool _supportGUI = false;
- [SerializeField] bool _supportCameraRotation = false;
- [SerializeField] bool _onlyLeftRightRotation = false;
- public bool SupportGUI
- {
- get { return _supportGUI; }
- set { _supportGUI = value; }
- }
- public bool SupportCameraRotation
- {
- get { return _supportCameraRotation; }
- set { _supportCameraRotation = value; }
- }
- public bool OnlyLeftRightRotation
- {
- get { return _onlyLeftRightRotation; }
- set { _onlyLeftRightRotation = value; }
- }
-
- [Tooltip("Render 180 degree equirectangular instead of 360 degrees")]
- [SerializeField] bool _render180Degrees = false;
- [SerializeField] StereoPacking _stereoRendering = StereoPacking.None;
-
- public bool Render180Degrees
- {
- get { return _render180Degrees; }
- set { _render180Degrees = value; }
- }
-
- public StereoPacking StereoRendering
- {
- get { return _stereoRendering; }
- set { _stereoRendering = value; }
- }
- [Tooltip("Makes assumption that 1 Unity unit is 1m")]
- [SerializeField] float _ipd = 0.064f;
- public float IPD
- {
- get { return _ipd; }
- set { _ipd = value; }
- }
- [Tooltip("Percentage cube faces are overdrawn each edge then blended to alleviate screen space FX seams")]
- [SerializeField] float _blendOverlapPercent = 0.0f;
- // State
- private RenderTexture _faceTarget;
- // RJT TODO: Texture array?
- private RenderTexture[] _faceTargets = new RenderTexture[6];
- private Material _blitMaterial;
- private Material _cubemapToEquirectangularMaterial;
- private RenderTexture _cubeTarget;
- private RenderTexture _finalTarget;
- private System.IntPtr _targetNativePointer = System.IntPtr.Zero;
- private int _propFlipX;
- #if SUPPORT_SHADER_ROTATION
- private int _propRotation;
- #endif
- private enum CubemapRenderMethod
- {
- Manual, // Manually render the cubemaps - supports world space GUI, camera rotation, but is slow and doesn't give correct stereo
- Unity, // No stereo, no world space GUI, no camera rotation
- Unity2018, // Good fast stereo, no world space GUI, camera rotation only in 2018.2 and above
- }
- public CaptureFromCamera360()
- {
- // Override the default values to match more common use cases for this capture component
- _renderResolution = Resolution.POW2_2048x2048;
- }
- private CubemapRenderMethod GetCubemapRenderingMethod()
- {
- if (_supportGUI)
- {
- return CubemapRenderMethod.Manual;
- }
- if (_supportCameraRotation)
- {
- #if AVPRO_MOVIECAPTURE_UNITY_STEREOCUBEMAP_RENDER_WITHROTATION
- return CubemapRenderMethod.Unity2018;
- #else
- return CubemapRenderMethod.Manual;
- #endif
- }
- if (_stereoRendering == StereoPacking.None)
- {
- #if AVPRO_MOVIECAPTURE_UNITY_STEREOCUBEMAP_RENDER_WITHROTATION
- return CubemapRenderMethod.Unity2018;
- #else
- return CubemapRenderMethod.Unity;
- #endif
- }
- else
- {
- #if AVPRO_MOVIECAPTURE_UNITY_STEREOCUBEMAP_RENDER
- return CubemapRenderMethod.Unity2018;
- #else
- return CubemapRenderMethod.Manual;
- #endif
- }
- }
- public void SetCamera(Camera camera)
- {
- _camera = camera;
- }
- #if false
- private void OnRenderImage(RenderTexture source, RenderTexture dest)
- {
- #if false
- if (_capturing && !_paused)
- {
- while (_handle >= 0 && !NativePlugin.IsNewFrameDue(_handle))
- {
- System.Threading.Thread.Sleep(1);
- }
- if (_handle >= 0)
- {
- if (_audioCapture && _audioDeviceIndex < 0 && !_noAudio)
- {
- uint bufferLength = (uint)_audioCapture.BufferLength;
- if (bufferLength > 0)
- {
- NativePlugin.EncodeAudio(_handle, _audioCapture.BufferPtr, bufferLength);
- _audioCapture.FlushBuffer();
- }
- }
- // In Direct3D the RT can be flipped vertically
- /*if (source.texelSize.y < 0)
- {
- }*/
- Graphics.Blit(_cubeTarget, _target, _cubemapToEquirectangularMaterial);
- RenderThreadEvent(NativePlugin.PluginEvent.CaptureFrameBuffer);
- GL.InvalidateState();
-
- UpdateFPS();
- }
- }
- #endif
- // Pass-through
- if (_cubeTarget != null)
- {
- Graphics.Blit(_cubeTarget, dest, _cubemapToEquirectangularMaterial);
- }
- else
- {
- Graphics.Blit(source, dest);
- }
- }
- #endif
- public override void UpdateFrame()
- {
- if (_cameraSelector != null)
- {
- if (_camera != _cameraSelector.Camera)
- {
- SetCamera(_cameraSelector.Camera);
- }
- }
- if (_useWaitForEndOfFrame)
- {
- if (_capturing && !_paused)
- {
- StartCoroutine(FinalRenderCapture());
- }
- }
- else
- {
- Capture();
- }
- base.UpdateFrame();
- }
- private IEnumerator FinalRenderCapture()
- {
- yield return _waitForEndOfFrame;
- Capture();
- }
- private void Capture()
- {
- TickFrameTimer();
- AccumulateMotionBlur();
- if (_capturing && !_paused)
- {
- if (
- ((_cubeTarget != null) || (_faceTargets[0] != null)) &&
- (_camera != null)
- )
- {
- bool canGrab = true;
- if (IsUsingMotionBlur())
- {
- // TODO: fix motion blur
- //this._motionBlur.RenderImage()
- // If the motion blur is still accumulating, don't grab this frame
- canGrab = _motionBlur.IsFrameAccumulated;
- }
- if (canGrab && CanOutputFrame())
- {
- EncodeUnityAudio();
- RenderTexture finalTexture = _finalTarget;
- if (!IsUsingMotionBlur())
- {
- UpdateTexture();
- }
- else
- {
- finalTexture = _motionBlur.FinalTexture;
- }
- // Side-by-side transparency
- RenderTexture newSourceTexture = UpdateForSideBySideTransparency( finalTexture );
- if (newSourceTexture)
- {
- finalTexture = newSourceTexture;
- }
- if (_targetNativePointer == System.IntPtr.Zero || _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 = finalTexture.GetNativeTexturePtr();
- }
- NativePlugin.SetTexturePointer(_handle, _targetNativePointer);
- RenderThreadEvent(NativePlugin.PluginEvent.CaptureFrameBuffer);
- // ADG NOTE: Causes screen flickering under D3D12, even if we're not doing any rendering at native level
- // And also seems to cause GL.sRGBWrite to be set to false, which causes screen darkening in Linear mode
- if (SystemInfo.graphicsDeviceType != GraphicsDeviceType.Direct3D12)
- {
- GL.InvalidateState();
- }
- UpdateFPS();
- }
- }
- }
- RenormTimer();
- }
- private static void ClearCubemap(RenderTexture texture, Color color)
- {
- // TODO: Find a better way to do this?
- bool clearDepth = (texture.depth != 0);
- Graphics.SetRenderTarget(texture, 0, CubemapFace.PositiveX);
- GL.Clear(true, clearDepth, color);
- Graphics.SetRenderTarget(texture, 0, CubemapFace.PositiveY);
- GL.Clear(true, clearDepth, color);
- Graphics.SetRenderTarget(texture, 0, CubemapFace.PositiveZ);
- GL.Clear(true, clearDepth, color);
- Graphics.SetRenderTarget(texture, 0, CubemapFace.NegativeX);
- GL.Clear(true, clearDepth, color);
- Graphics.SetRenderTarget(texture, 0, CubemapFace.NegativeY);
- GL.Clear(true, clearDepth, color);
- Graphics.SetRenderTarget(texture, 0, CubemapFace.NegativeZ);
- GL.Clear(true, clearDepth, color);
- Graphics.SetRenderTarget(null);
- }
- private void RenderCubemapToEquiRect(RenderTexture cubemap, RenderTexture target, bool supportRotation, Quaternion rotation, bool isEyeLeft)
- {
- #if SUPPORT_SHADER_ROTATION
- if (supportRotation)
- {
- // Note: Because Unity's Camera.RenderCubemap() doesn't support rotated cameras, we apply the rotation matrix in the cubemap lookup
- _cubemapToEquirectangularMaterial.EnableKeyword("USE_ROTATION");
- Matrix4x4 rotationMatrix = Matrix4x4.TRS(Vector3.zero, rotation, Vector3.one);
- _cubemapToEquirectangularMaterial.SetMatrix(_propRotation, rotationMatrix);
- }
- else
- {
- _cubemapToEquirectangularMaterial.DisableKeyword("USE_ROTATION");
- }
- #endif
- if (_stereoRendering == StereoPacking.TopBottom)
- {
- if (isEyeLeft)
- {
- // Render to top
- _cubemapToEquirectangularMaterial.DisableKeyword("STEREOPACK_BOTTOM");
- _cubemapToEquirectangularMaterial.EnableKeyword("STEREOPACK_TOP");
- }
- else
- {
- // Render to bottom
- _cubemapToEquirectangularMaterial.DisableKeyword("STEREOPACK_TOP");
- _cubemapToEquirectangularMaterial.EnableKeyword("STEREOPACK_BOTTOM");
- }
- }
- else if (_stereoRendering == StereoPacking.LeftRight)
- {
- if (isEyeLeft)
- {
- // Render to left
- _cubemapToEquirectangularMaterial.DisableKeyword("STEREOPACK_RIGHT");
- _cubemapToEquirectangularMaterial.EnableKeyword("STEREOPACK_LEFT");
- }
- else
- {
- // Render to right
- _cubemapToEquirectangularMaterial.DisableKeyword("STEREOPACK_LEFT");
- _cubemapToEquirectangularMaterial.EnableKeyword("STEREOPACK_RIGHT");
- }
- }
- // Between Unity 2018.1.0 and 2018.3.0 Unity doesn't seem to set the correct sRGBWrite state and keeps it as false
- #if (UNITY_2018_1_OR_NEWER && !UNITY_2018_3_OR_NEWER)
- bool sRGBWritePrev = GL.sRGBWrite;
- GL.sRGBWrite = target.sRGB;
- #endif
- // Blending?
- if (_blendOverlapPercent > 0.0f)
- {
- _cubemapToEquirectangularMaterial.EnableKeyword("USE_BLENDING");
- _cubemapToEquirectangularMaterial.SetTexture("_Face_Left", _faceTargets[0]);
- _cubemapToEquirectangularMaterial.SetTexture("_Face_Right", _faceTargets[1]);
- _cubemapToEquirectangularMaterial.SetTexture("_Face_Up", _faceTargets[2]);
- _cubemapToEquirectangularMaterial.SetTexture("_Face_Down", _faceTargets[3]);
- _cubemapToEquirectangularMaterial.SetTexture("_Face_Front", _faceTargets[4]);
- _cubemapToEquirectangularMaterial.SetTexture("_Face_Back", _faceTargets[5]);
- _cubemapToEquirectangularMaterial.SetFloat("_inverseOverlap", (1.0f / (1.0f + (_blendOverlapPercent * 0.01f))));
- }
- else { _cubemapToEquirectangularMaterial.DisableKeyword("USE_BLENDING"); }
- // Render
- Graphics.Blit(cubemap, target, _cubemapToEquirectangularMaterial);
- #if (UNITY_2018_1_OR_NEWER && !UNITY_2018_3_OR_NEWER)
- GL.sRGBWrite = sRGBWritePrev;
- #endif
- }
- private void UpdateTexture()
- {
- // Between Unity 2018.1.0 and 2018.3.0 Unity doesn't seem to set the correct sRGBWrite state and keeps it as false
- #if (UNITY_2018_1_OR_NEWER && !UNITY_2018_3_OR_NEWER)
- bool sRGBWritePrev = GL.sRGBWrite;
- GL.sRGBWrite = _cubeTarget.sRGB;
- #endif
- // In Direct3D the RT can be flipped vertically
- /*if (source.texelSize.y < 0)
- {
- }*/
- //_cubeCamera.transform.position = _camera.transform.position;
- //_cubeCamera.transform.rotation = _camera.transform.rotation;
- Camera camera = _camera;
- Rect prevRect = camera.rect;
- camera.rect = new Rect(0f, 0f, 1f, 1f); // NOTE: the Scene View camera will change it's rect when being interacted with, so we need to make sure it's overridden
- CubemapRenderMethod cubemapRenderMethod = GetCubemapRenderingMethod();
-
- if (_stereoRendering == StereoPacking.None)
- {
- if (cubemapRenderMethod == CubemapRenderMethod.Unity)
- {
- #if AVPRO_MOVIECAPTURE_UNITYBUG_RENDERTOCUBEMAP_56
- RenderTexture prev = camera.targetTexture;
- #endif
-
- // Note: Camera.RenderToCubemap() doesn't support camera rotation
- camera.RenderToCubemap(_cubeTarget, 63);
- #if AVPRO_MOVIECAPTURE_UNITYBUG_RENDERTOCUBEMAP_56
- // NOTE: We need this to clean up the state in at least Unity 5.6.0 - 5.6.1p1
- camera.targetTexture = prev;
- #endif
- }
- #if AVPRO_MOVIECAPTURE_UNITY_STEREOCUBEMAP_RENDER
- else if (cubemapRenderMethod == CubemapRenderMethod.Unity2018)
- {
- // Note: If we use Mono instead of Left then rotation isn't supported
- if (this.transform.rotation == Quaternion.identity)
- {
- camera.RenderToCubemap(_cubeTarget, 63, Camera.MonoOrStereoscopicEye.Mono);
- }
- else
- {
- camera.stereoSeparation = 0f;
- camera.RenderToCubemap(_cubeTarget, 63, Camera.MonoOrStereoscopicEye.Left);
- }
- }
- #endif
- else if (cubemapRenderMethod == CubemapRenderMethod.Manual)
- {
- RenderCameraToCubemap(camera, _cubeTarget);
- }
- RenderCubemapToEquiRect(_cubeTarget, _finalTarget, false, Quaternion.identity, true);
- }
- else
- {
- #if AVPRO_MOVIECAPTURE_UNITY_STEREOCUBEMAP_RENDER
- if (cubemapRenderMethod == CubemapRenderMethod.Unity2018)
- {
- //Left eye
- camera.stereoSeparation = _ipd;
- camera.RenderToCubemap(_cubeTarget, 63, Camera.MonoOrStereoscopicEye.Left);
- RenderCubemapToEquiRect(_cubeTarget, _finalTarget, false, camera.transform.rotation, true);
- // Right eye
- _cubeTarget.DiscardContents();
- camera.RenderToCubemap(_cubeTarget, 63, Camera.MonoOrStereoscopicEye.Right);
- RenderCubemapToEquiRect(_cubeTarget, _finalTarget, false, camera.transform.rotation, false);
- } else
- #endif
- if (cubemapRenderMethod == CubemapRenderMethod.Manual)
- {
- // Save camera state
- Vector3 cameraPosition = camera.transform.localPosition;
- // Left eye
- camera.transform.Translate(new Vector3(-_ipd / 2f, 0f, 0f), Space.Self);
- RenderCameraToCubemap(camera, _cubeTarget);
- RenderCubemapToEquiRect(_cubeTarget, _finalTarget, false, Quaternion.identity, true);
- // Right eye
- camera.transform.localPosition = cameraPosition;
- camera.transform.Translate(new Vector3(_ipd / 2f, 0f, 0f), Space.Self);
- RenderCameraToCubemap(camera, _cubeTarget);
- RenderCubemapToEquiRect(_cubeTarget, _finalTarget, false, Quaternion.identity, false);
- // Restore camera state
- camera.transform.localPosition = cameraPosition;
- }
- }
- camera.rect = prevRect;
- #if (UNITY_2018_1_OR_NEWER && !UNITY_2018_3_OR_NEWER)
- GL.sRGBWrite = sRGBWritePrev;
- #endif
- }
- private void RenderCameraToCubemap(Camera camera, RenderTexture cubemapTarget)
- {
- RenderTexture prevRT = RenderTexture.active;
- // Cache old camera values
- float prevFieldOfView = camera.fieldOfView;
- RenderTexture prevtarget = camera.targetTexture;
- Quaternion prevRotation = camera.transform.rotation;
- // Ignore the camera rotation
- Quaternion xform = camera.transform.rotation;
- if (!_supportCameraRotation)
- {
- xform = Quaternion.identity;
- }
- else if (_onlyLeftRightRotation)
- {
- xform = Quaternion.Euler(0f, camera.transform.eulerAngles.y, 0f);
- }
- if (_blendOverlapPercent > 0.0f)
- {
- // Adjust FOV for overlap percentage (each each)
- camera.fieldOfView = (Mathf.Atan(1.0f + (_blendOverlapPercent * 0.01f)) * 2.0f * Mathf.Rad2Deg);
- // RJT TODO: LUT/loop
- // Left
- camera.transform.rotation = xform * Quaternion.LookRotation(Vector3.right, Vector3.down);
- camera.targetTexture = _faceTargets[0];
- camera.Render();
- // Right
- camera.transform.rotation = xform * Quaternion.LookRotation(Vector3.left, Vector3.down);
- camera.targetTexture = _faceTargets[1];
- camera.Render();
- // Up
- camera.transform.rotation = xform * Quaternion.LookRotation(Vector3.up, Vector3.forward);
- camera.targetTexture = _faceTargets[2];
- camera.Render();
- // Down
- camera.transform.rotation = xform * Quaternion.LookRotation(Vector3.down, Vector3.back);
- camera.targetTexture = _faceTargets[3];
- camera.Render();
- // Front
- camera.transform.rotation = xform * Quaternion.LookRotation(Vector3.forward, Vector3.down);
- camera.targetTexture = _faceTargets[4];
- camera.Render();
- // Back
- camera.transform.rotation = xform * Quaternion.LookRotation(Vector3.back, Vector3.down);
- camera.targetTexture = _faceTargets[5];
- camera.Render();
- }
- else
- {
- // NOTE: There is a bug in Unity 2017.1.0f3 to at least 2017.2beta7 which causes deferred rendering mode to always clear the cubemap target to white
- camera.fieldOfView = 90f;
- camera.targetTexture = _faceTarget;
-
- // Front
- camera.transform.rotation = xform * Quaternion.LookRotation(Vector3.forward, Vector3.down);
- _faceTarget.DiscardContents();
- camera.Render();
- Graphics.SetRenderTarget(cubemapTarget, 0, CubemapFace.PositiveZ);
- Graphics.Blit(_faceTarget, _blitMaterial);
- // Back
- camera.transform.rotation = xform * Quaternion.LookRotation(Vector3.back, Vector3.down);
- _faceTarget.DiscardContents();
- camera.Render();
- Graphics.SetRenderTarget(cubemapTarget, 0, CubemapFace.NegativeZ);
- Graphics.Blit(_faceTarget, _blitMaterial);
- // Right
- camera.transform.rotation = xform * Quaternion.LookRotation(Vector3.right, Vector3.down);
- _faceTarget.DiscardContents();
- camera.Render();
- Graphics.SetRenderTarget(cubemapTarget, 0, CubemapFace.NegativeX);
- Graphics.Blit(_faceTarget, _blitMaterial);
- // Left
- camera.transform.rotation = xform * Quaternion.LookRotation(Vector3.left, Vector3.down);
- _faceTarget.DiscardContents();
- camera.Render();
- Graphics.SetRenderTarget(cubemapTarget, 0, CubemapFace.PositiveX);
- Graphics.Blit(_faceTarget, _blitMaterial);
- // Up
- camera.transform.rotation = xform * Quaternion.LookRotation(Vector3.up, Vector3.forward);
- _faceTarget.DiscardContents();
- camera.Render();
- Graphics.SetRenderTarget(cubemapTarget, 0, CubemapFace.PositiveY);
- Graphics.Blit(_faceTarget, _blitMaterial);
- // Down
- camera.transform.rotation = xform * Quaternion.LookRotation(Vector3.down, Vector3.back);
- _faceTarget.DiscardContents();
- camera.Render();
- Graphics.SetRenderTarget(cubemapTarget, 0, CubemapFace.NegativeY);
- Graphics.Blit(_faceTarget, _blitMaterial);
- Graphics.SetRenderTarget(prevRT);
- }
- // Restore camera values
- camera.transform.rotation = prevRotation;
- camera.fieldOfView = prevFieldOfView;
- camera.targetTexture = prevtarget;
- }
- private void AccumulateMotionBlur()
- {
- if (_motionBlur != null)
- {
- if (_capturing && !_paused)
- {
- if (_camera != null && _handle >= 0)
- {
- UpdateTexture();
- _motionBlur.Accumulate(_finalTarget);
- }
- }
- }
- }
- public override bool PrepareCapture()
- {
- if (_capturing)
- {
- return false;
- }
- #if UNITY_EDITOR_WIN || (!UNITY_EDITOR && UNITY_STANDALONE_WIN)
- if (SystemInfo.graphicsDeviceVersion.StartsWith("Direct3D 9"))
- {
- Debug.LogError("[AVProMovieCapture] Direct3D9 not yet supported, please use Direct3D11 instead.");
- return false;
- }
- else if (SystemInfo.graphicsDeviceVersion.StartsWith("OpenGL") && !SystemInfo.graphicsDeviceVersion.Contains("emulated"))
- {
- Debug.LogError("[AVProMovieCapture] OpenGL not yet supported for CaptureFromCamera360 component, please use Direct3D11 instead. You may need to switch your build platform to Windows.");
- return false;
- }
- #endif
- // Check cubemap resolution support
- int cubemapResolution = (int)_cubemapResolution;
- if (_blendOverlapPercent > 0.0f)
- {
- // Adjust resolution for overlap percentage (each edge)
- cubemapResolution = (int)(((float)cubemapResolution * (1.0f + ((_blendOverlapPercent * 0.01f) * 2.0f))) + 0.5f);
- }
- if (cubemapResolution > SystemInfo.maxCubemapSize)
- {
- cubemapResolution = SystemInfo.maxCubemapSize;
- Debug.LogWarning("[AVProMovieCapture] Reducing cubemap size to system max: " + cubemapResolution);
- }
- // Setup material
- _pixelFormat = NativePlugin.PixelFormat.RGBA32;
- _isTopDown = true;
- if (_cameraSelector != null)
- {
- //if (_camera != _cameraSelector.Camera)
- {
- SetCamera(_cameraSelector.Camera);
- }
- }
- if (_camera == null)
- {
- SetCamera(this.GetComponent<Camera>());
- }
- if (_camera == null)
- {
- Debug.LogError("[AVProMovieCapture] No camera assigned to CaptureFromCamera360");
- return false;
- }
- // Resolution
- int finalWidth = Mathf.FloorToInt(_camera.pixelRect.width);
- int finalHeight = Mathf.FloorToInt(_camera.pixelRect.height);
- if (_renderResolution == Resolution.Custom)
- {
- finalWidth = (int)_renderSize.x;
- finalHeight = (int)_renderSize.y;
- }
- else if (_renderResolution != Resolution.Original)
- {
- GetResolution(_renderResolution, ref finalWidth, ref finalHeight);
- }
- // Setup rendering a different render target if we're overriding resolution or anti-aliasing
- //if (_renderResolution != Resolution.Original || _renderAntiAliasing != QualitySettings.antiAliasing)
- {
- int aaLevel = GetCameraAntiAliasingLevel(_camera);
- CubemapRenderMethod cubemapRenderMethod = GetCubemapRenderingMethod();
- Debug.Log("[AVProMovieCapture] Using cubemap render method: " + cubemapRenderMethod.ToString());
- // Create the final render target
- _targetNativePointer = System.IntPtr.Zero;
- if (_finalTarget != null)
- {
- _finalTarget.DiscardContents();
- if (_finalTarget.width != finalWidth || _finalTarget.height != finalHeight)
- {
- RenderTexture.ReleaseTemporary(_finalTarget);
- _finalTarget = null;
- }
- }
- if (_finalTarget == null)
- {
- _finalTarget = RenderTexture.GetTemporary(finalWidth, finalHeight, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Default, 1);
- _finalTarget.name = "[AVProMovieCapture] 360 Final Target";
- }
- // Create the per-face render target (only when need to support GUI rendering)
- if (_faceTarget != null)
- {
- _faceTarget.DiscardContents();
- if (_faceTarget.width != (int)cubemapResolution ||
- _faceTarget.height != (int)cubemapResolution ||
- _faceTarget.depth != (int)_cubemapDepth ||
- _faceTarget.antiAliasing != aaLevel)
- {
- RenderTexture.Destroy(_faceTarget);
- _faceTarget = null;
- }
- }
- if (_faceTargets[0] != null)
- {
- for (int i = 0; i < 6; ++i )
- {
- _faceTargets[i].DiscardContents();
- }
- if (_faceTargets[0].width != cubemapResolution ||
- _faceTargets[0].height != cubemapResolution ||
- _faceTargets[0].depth != (int)_cubemapDepth ||
- _faceTargets[0].antiAliasing != aaLevel)
- {
- for (int i = 0; i < 6; ++i )
- {
- RenderTexture.Destroy(_faceTargets[i]);
- _faceTargets[i] = null;
- }
- }
- }
- RenderTextureFormat renderTextureFormat = RenderTextureFormat.Default;
- #if USING_URP
- renderTextureFormat = RenderTextureFormat.ARGBHalf;//ARGBFloat;
- #endif
- if (cubemapRenderMethod == CubemapRenderMethod.Manual)
- {
- if ((_blendOverlapPercent > 0.0f) && (_faceTargets[0] == null))
- {
- for (int i = 0; i < 6; ++i )
- {
- _faceTargets[i] = new RenderTexture(cubemapResolution, cubemapResolution, (int)_cubemapDepth, renderTextureFormat, RenderTextureReadWrite.Default);
- _faceTargets[i].name = "[AVProMovieCapture] 360 Face Target";
- _faceTargets[i].isPowerOfTwo = Mathf.IsPowerOfTwo(cubemapResolution);
- _faceTargets[i].wrapMode = TextureWrapMode.Clamp;
- _faceTargets[i].filterMode = FilterMode.Bilinear;
- _faceTargets[i].autoGenerateMips = false;
- _faceTargets[i].antiAliasing = aaLevel;
- }
- }
- else if (_faceTarget == null)
- {
- _faceTarget = new RenderTexture((int)cubemapResolution, (int)cubemapResolution, (int)_cubemapDepth, RenderTextureFormat.Default, RenderTextureReadWrite.Default);
- _faceTarget.name = "[AVProMovieCapture] 360 Face Target";
- _faceTarget.isPowerOfTwo = true;
- _faceTarget.wrapMode = TextureWrapMode.Clamp;
- _faceTarget.filterMode = FilterMode.Bilinear;
- _faceTarget.autoGenerateMips = false;
- _faceTarget.antiAliasing = aaLevel;
- }
- _cubemapToEquirectangularMaterial.SetFloat(_propFlipX, 0.0f);
- }
- else
- {
- // Unity's RenderToCubemap result needs flipping
- _cubemapToEquirectangularMaterial.SetFloat(_propFlipX, 1.0f);
- }
- _cubemapToEquirectangularMaterial.DisableKeyword("USE_ROTATION");
- _cubemapToEquirectangularMaterial.DisableKeyword("STEREOPACK_TOP");
- _cubemapToEquirectangularMaterial.DisableKeyword("STEREOPACK_BOTTOM");
- _cubemapToEquirectangularMaterial.DisableKeyword("STEREOPACK_LEFT");
- _cubemapToEquirectangularMaterial.DisableKeyword("STEREOPACK_RIGHT");
- if (_render180Degrees)
- {
- _cubemapToEquirectangularMaterial.DisableKeyword("LAYOUT_EQUIRECT360");
- _cubemapToEquirectangularMaterial.EnableKeyword("LAYOUT_EQUIRECT180");
- }
- else
- {
- _cubemapToEquirectangularMaterial.DisableKeyword("LAYOUT_EQUIRECT180");
- _cubemapToEquirectangularMaterial.EnableKeyword("LAYOUT_EQUIRECT360");
- }
- if (_blendOverlapPercent == 0.0f)
- {
- // Create the cube render target
- int cubeDepth = 0;
- if (cubemapRenderMethod != CubemapRenderMethod.Manual)
- {
- cubeDepth = (int)_cubemapDepth;
- }
- int cubeAA = 1;
- if (cubemapRenderMethod != CubemapRenderMethod.Manual)
- {
- cubeAA = aaLevel;
- }
- if (_cubeTarget != null)
- {
- _cubeTarget.DiscardContents();
- if (_cubeTarget.width != cubemapResolution ||
- _cubeTarget.height != cubemapResolution ||
- _cubeTarget.depth != cubeDepth ||
- _cubeTarget.antiAliasing != cubeAA)
- {
- RenderTexture.Destroy(_cubeTarget);
- _cubeTarget = null;
- }
- }
- if (_cubeTarget == null)
- {
- _cubeTarget = new RenderTexture(cubemapResolution, cubemapResolution, cubeDepth, renderTextureFormat, RenderTextureReadWrite.Default);
- _cubeTarget.name = "[AVProMovieCapture] 360 Cube Target";
- _cubeTarget.isPowerOfTwo = true;
- _cubeTarget.dimension = UnityEngine.Rendering.TextureDimension.Cube;
- _cubeTarget.useMipMap = false;
- _cubeTarget.autoGenerateMips = false;
- _cubeTarget.antiAliasing = cubeAA;
- _cubeTarget.wrapMode = TextureWrapMode.Clamp;
- _cubeTarget.filterMode = FilterMode.Bilinear;
- }
- }
- if (_useMotionBlur)
- {
- _motionBlurCameras = new Camera[1];
- _motionBlurCameras[0] = _camera;
- }
- }
- _Transparency = Transparency.None;
- if ( !NativePlugin.IsBasicEdition() )
- {
- if( (_outputTarget == OutputTarget.VideoFile || _outputTarget == OutputTarget.NamedPipe) && GetEncoderHints().videoHints.transparency != Transparency.None )
- {
- _Transparency = GetEncoderHints().videoHints.transparency;
- }
- else if( _outputTarget == OutputTarget.ImageSequence && GetEncoderHints().imageHints.transparency != Transparency.None )
- {
- _Transparency = GetEncoderHints().imageHints.transparency;
- }
- //
- if( _Transparency == Transparency.TopBottom || _Transparency == Transparency.LeftRight )
- {
- InitialiseSideBySideTransparency( finalWidth, finalHeight );
- }
- switch ( _Transparency )
- {
- case Transparency.TopBottom: finalHeight *= 2; break;
- case Transparency.LeftRight: finalWidth *= 2; break;
- }
- }
- SelectRecordingResolution(finalWidth, finalHeight);
- GenerateFilename();
- if (base.PrepareCapture())
- {
- UpdateInjectionOptions(_stereoRendering, _render180Degrees?SphericalVideoLayout.Equirectangular180:SphericalVideoLayout.Equirectangular360);
- return true;
- }
- return false;
- }
- public override Texture GetPreviewTexture()
- {
- if (IsUsingMotionBlur())
- {
- return _motionBlur.FinalTexture;
- }
- return _finalTarget;
- }
- public override void Start()
- {
- Shader shader = Resources.Load<Shader>("CubemapToEquirectangular");
- if (shader != null)
- {
- _cubemapToEquirectangularMaterial = new Material(shader);
- }
- else
- {
- Debug.LogError("[AVProMovieCapture] Can't find CubemapToEquirectangular shader");
- }
- Shader blitShader = Shader.Find("Hidden/BlitCopy");
- if (blitShader != null)
- {
- _blitMaterial = new Material(blitShader);
- }
- else
- {
- Debug.LogError("[AVProMovieCapture] Can't find Hidden/BlitCopy shader");
- }
- _propFlipX = Shader.PropertyToID("_FlipX");
- #if SUPPORT_SHADER_ROTATION
- _propRotation = Shader.PropertyToID("_RotationMatrix");
- #endif
- base.Start();
- }
- public override void OnDestroy()
- {
- _targetNativePointer = System.IntPtr.Zero;
- if (_blitMaterial != null)
- {
- Material.Destroy(_blitMaterial);
- _blitMaterial = null;
- }
- if (_faceTarget != null)
- {
- RenderTexture.Destroy(_faceTarget);
- _faceTarget = null;
- }
- if (_faceTargets[0] != null)
- {
- for (int i = 0; i < 6; ++i)
- {
- RenderTexture.Destroy(_faceTargets[i]);
- _faceTargets[i] = null;
- }
- }
- if (_cubeTarget != null)
- {
- RenderTexture.Destroy(_cubeTarget);
- _cubeTarget = null;
- }
- if (_finalTarget != null)
- {
- RenderTexture.ReleaseTemporary(_finalTarget);
- _finalTarget = null;
- }
- base.OnDestroy();
- }
- }
- }
|