123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- using UnityEngine;
- //-----------------------------------------------------------------------------
- // Copyright 2012-2017 RenderHeads Ltd. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace RenderHeads.Media.AVProMovieCapture
- {
- /// <summary>
- /// Accumulates frames to average for generating motion blur in renders
- /// </summary>
- [AddComponentMenu("AVPro Movie Capture/Motion Blur", 301)]
- public class MotionBlur : MonoBehaviour
- {
- [SerializeField]
- public RenderTextureFormat _format = RenderTextureFormat.ARGBFloat;
- [SerializeField]
- private int _numSamples = 16;
- // State
- private RenderTexture _accum;
- private RenderTexture _lastComp;
- private Material _addMaterial;
- private Material _divMaterial;
- private int _frameCount;
- private int _targetWidth;
- private int _targetHeight;
- private bool _isDirty;
- private static int _propNumSamples;
- private static int _propWeight;
- public bool IsFrameAccumulated
- {
- get;
- private set;
- }
- public int NumSamples
- {
- get { return _numSamples; }
- set { _numSamples = value; OnNumSamplesChanged(); }
- }
- public int FrameCount
- {
- get { return _frameCount; }
- }
- public RenderTexture FinalTexture
- {
- get { return _lastComp; }
- }
- private void Awake()
- {
- if (_propNumSamples == 0)
- {
- _propNumSamples = Shader.PropertyToID("_NumSamples");
- _propWeight = Shader.PropertyToID("_Weight");
- }
- }
- public void SetTargetSize(int width, int height)
- {
- if (_targetWidth != width || _targetHeight != height)
- {
- _targetWidth = width;
- _targetHeight = height;
- _isDirty = true;
- }
- }
- private void Start()
- {
- Setup();
- }
- private void OnEnable()
- {
- _frameCount = 0;
- IsFrameAccumulated = false;
- ClearAccumulation();
- }
- private void Setup()
- {
- if (_addMaterial == null)
- {
- Shader addShader = Resources.Load<Shader>("AVProMovieCapture_MotionBlur_Add");
- Shader divShader = Resources.Load<Shader>("AVProMovieCapture_MotionBlur_Div");
- _addMaterial = new Material(addShader);
- _divMaterial = new Material(divShader);
- }
- if (_targetWidth == 0 && _targetHeight == 0)
- {
- // TODO: change the size of these RenderTextures based on the output size of the capture
- _targetWidth = Screen.width;
- _targetHeight = Screen.height;
- }
- if (_accum != null)
- {
- _accum.Release();
- RenderTexture.Destroy(_accum);
- _accum = null;
- }
- if (_lastComp != null)
- {
- _lastComp.Release();
- RenderTexture.Destroy(_lastComp);
- _lastComp = null;
- }
- _accum = new RenderTexture(_targetWidth, _targetHeight, 0, _format, RenderTextureReadWrite.Default);
- _lastComp = new RenderTexture(_targetWidth, _targetHeight, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Default);
- _accum.filterMode = FilterMode.Point;
- _lastComp.filterMode = FilterMode.Bilinear;
- _accum.Create();
- _lastComp.Create();
- OnNumSamplesChanged();
- _isDirty = false;
- }
- private void ClearAccumulation()
- {
- RenderTexture prev = RenderTexture.active;
- RenderTexture.active = _accum;
- GL.Clear(false, true, Color.black);
- RenderTexture.active = prev;
- }
- private void OnDestroy()
- {
- if (_addMaterial != null)
- {
- Material.Destroy(_addMaterial);
- _addMaterial = null;
- }
- if (_divMaterial != null)
- {
- Material.Destroy(_divMaterial);
- _divMaterial = null;
- }
- if (_accum != null)
- {
- _accum.Release();
- RenderTexture.Destroy(_accum);
- _accum = null;
- }
- if (_lastComp != null)
- {
- _lastComp.Release();
- RenderTexture.Destroy(_lastComp);
- _lastComp = null;
- }
- }
- public void OnNumSamplesChanged()
- {
- if (_divMaterial != null)
- {
- _addMaterial.SetFloat(_propWeight, 1f);
- _divMaterial.SetFloat(_propNumSamples, _numSamples);
- }
- }
- private static float LerpUnclamped(float a, float b, float t)
- {
- return a + ((b - a) * t);
- }
- [SerializeField]
- public float _bias = 1f;
- private float _total = 0f;
- private void ApplyWeighting()
- {
- // Apply some frame weighting so the newer frames have the most contribution
- // Not sure this is better than non-weighted averaging.
- float weight = ((float)_frameCount / (float)_numSamples);
- weight = Mathf.Pow(weight, 2f);
- _total += weight;
- float numSamples = ((float)_numSamples / 2f) + 0.5f;
- numSamples = _total;
- weight = LerpUnclamped(weight, 1f, _bias);
- numSamples = LerpUnclamped(numSamples, _numSamples, _bias);
- _addMaterial.SetFloat(_propWeight, weight);
- _divMaterial.SetFloat(_propNumSamples, numSamples);
- }
- public void Accumulate(Texture src)
- {
- if (_isDirty)
- {
- Setup();
- }
- //ApplyWeighting();
- //_divMaterial.SetFloat(_propNumSamples, _numSamples);
- Graphics.Blit(src, _accum, _addMaterial);
- _frameCount++;
- if (_frameCount >= _numSamples)
- {
- // Divide the accumation texture
- Graphics.Blit(_accum, _lastComp, _divMaterial);
- // Clear the accumation texture so it is ready to start again
- ClearAccumulation();
- //Graphics.Blit(src, _accum, _addMaterial);
- //Graphics.Blit(_lastComp, _accum, _divMaterial);
- IsFrameAccumulated = true;
- _frameCount = 0;
- _total = 0f;
- }
- else
- {
- IsFrameAccumulated = false;
- }
- }
- private void OnRenderImage(RenderTexture src, RenderTexture dst)
- {
- // Take the result of the camera render and accumulate it
- // NOTE: Some capture components disable the this MotionBlur component so that OnRenderImage() isn't called as the component is used manually
- Accumulate(src);
- Graphics.Blit(_lastComp, dst);
- }
- /*void OnGUI()
- {
- GUILayout.Label("Real (slow) Motion Blur Demo");
- GUILayout.BeginHorizontal();
- GUILayout.Label("Samples");
- int numSamples = (int)GUILayout.HorizontalSlider(_numSamples, 1, 64, GUILayout.Width(128f));
- if (numSamples != _numSamples)
- {
- _numSamples = numSamples;
- OnNumSamplesChanged();
- }
- GUILayout.Label(_numSamples.ToString());
- GUILayout.EndHorizontal();
- }*/
- }
- }
|