Neodroid  0.2.0
Machine Learning Environment Prototyping Tool
MultiPassCamera.cs
Go to the documentation of this file.
1 using System;
2 using System.Linq;
4 using UnityEditor;
5 using UnityEngine;
6 using UnityEngine.Rendering;
7 using Object = UnityEngine.Object;
8 
9 namespace droid.Runtime.Utilities.GameObjects.NeodroidCamera.Experimental {
13  [ExecuteInEditMode]
14  public class MultiPassCamera : MonoBehaviour {
17  Renderer[] _all_renders = null;
18 
21  MaterialPropertyBlock _block = null;
22 
23  [SerializeField] RenderTexture depthRenderTexture = null;
24  [SerializeField] RenderTexture objectIdRenderTexture = null;
25  [SerializeField] RenderTexture tagIdRenderTexture = null;
26  [SerializeField] RenderTexture flowRenderTexture = null;
27 
30  void Start() { this.Setup(); }
31 
32  void Awake() {
33  //this._asf= new TextureFlipper();
34  }
35 
36  void CheckBlock() {
37  if (this._block == null) {
38  this._block = new MaterialPropertyBlock();
39  }
40  }
41 
42  [SerializeField] CapturePassMaterial[] _capture_passes;
43 
44  [SerializeField] Camera _camera;
45  [SerializeField] Boolean debug = true;
46  [SerializeField] Boolean always_re = true;
47  [SerializeField] Mesh m_quad;
48  [SerializeField] GUISkin gui_style = null;
49 
54  public static Mesh CreateFullscreenQuad() {
55  var r = new Mesh {
56  vertices = new[] {
57  new Vector3(1.0f, 1.0f, 0.0f),
58  new Vector3(-1.0f, 1.0f, 0.0f),
59  new Vector3(-1.0f, -1.0f, 0.0f),
60  new Vector3(1.0f, -1.0f, 0.0f)
61  },
62  triangles = new[] {0, 1, 2, 2, 3, 0}
63  };
64  r.UploadMeshData(true);
65  return r;
66  }
67 
70  void Setup() {
71  if (!this.gui_style) {
72  this.gui_style = Resources.FindObjectsOfTypeAll<GUISkin>().First(a => a.name == "BoundingBox");
73  }
74 
75  this._all_renders = FindObjectsOfType<Renderer>();
76  if (this._capture_passes == null || this._capture_passes.Length == 0 || this.always_re) {
77  this._capture_passes = new[] {
78  new CapturePassMaterial(CameraEvent.AfterDepthTexture,
79  BuiltinRenderTextureType.Depth) {
80  _SupportsAntialiasing
81  = false,
82  _RenderTexture
83  = this
84  .depthRenderTexture
85  },
86  new CapturePassMaterial(CameraEvent.AfterForwardAlpha,
87  BuiltinRenderTextureType.MotionVectors) {
88  _SupportsAntialiasing
89  = false,
90  _RenderTexture
91  = this
92  .flowRenderTexture
93  },
94  new CapturePassMaterial(CameraEvent.AfterForwardAlpha,
95  BuiltinRenderTextureType.None) {
96  _SupportsAntialiasing
97  = false,
98  _RenderTexture
99  = this
100  .objectIdRenderTexture,
101  _TextureId
102  = Shader
103  .PropertyToID("_TmpFrameBuffer")
104  },
105  new CapturePassMaterial(CameraEvent.AfterDepthTexture,
106  BuiltinRenderTextureType.None) {
107  _SupportsAntialiasing
108  = false,
109  _RenderTexture
110  = this
111  .tagIdRenderTexture,
112  _TextureId
113  = Shader
114  .PropertyToID("_CameraDepthTexture")
115  }
116  };
117  }
118 
119  if (this.m_quad == null) {
120  this.m_quad = CreateFullscreenQuad();
121  }
122 
123  this._camera = this.GetComponent<Camera>();
124  //this._camera.SetReplacementShader(this.uberMaterial.shader,"");
125 
126  this._camera.RemoveAllCommandBuffers(); // cleanup capturing camera
127 
128  this._camera.depthTextureMode = DepthTextureMode.Depth | DepthTextureMode.MotionVectors;
129 
130  foreach (var capture_pass in this._capture_passes) {
131  var cb = new CommandBuffer {name = capture_pass.Source.ToString()};
132 
133  cb.Clear();
134 
135  if (capture_pass._Material) {
136  cb.GetTemporaryRT(capture_pass._TextureId, -1, -1, 0, FilterMode.Point);
137  //cb.Blit(capture_pass.Source, capture_pass._RenderTexture, capture_pass._Material);
138  cb.Blit(capture_pass.Source, capture_pass._TextureId);
139  cb.SetRenderTarget(new RenderTargetIdentifier[] {capture_pass._RenderTexture},
140  capture_pass._RenderTexture);
141  cb.DrawMesh(this.m_quad, Matrix4x4.identity, capture_pass._Material, 0, 0);
142  cb.ReleaseTemporaryRT(capture_pass._TextureId);
143  } else {
144  cb.Blit(capture_pass.Source, capture_pass._RenderTexture);
145  }
146 
147  this._camera.AddCommandBuffer(capture_pass.When, cb);
148  }
149 
150  this.CheckBlock();
151  foreach (var r in this._all_renders) {
152  r.GetPropertyBlock(this._block);
153  var sm = r.sharedMaterial;
154  if (sm) {
155  var id = sm.GetInstanceID();
156  var color = ColorEncoding.EncodeIdAsColor(id);
157 
158  this._block.SetColor(SynthesisUtilities._Shader_MaterialId_Color_Name, color);
159  r.SetPropertyBlock(this._block);
160  }
161  }
162  }
163 
164  const int _size = 100;
165  const int _margin = 20;
166 
167  void OnGUI() {
168  if (this.debug) {
169  var index = 0;
170 
171  foreach (var pass in this._capture_passes) {
172  var xi = (_size + _margin) * index++;
173  var x = xi % (Screen.width - _size);
174  var y = (_size + _margin) * (xi / (Screen.width - _size));
175  var r = new Rect(_margin + x, _margin + y, _size, _size);
176  //this._asf?.Flip(pass._RenderTexture);
177 
178  GUI.DrawTexture(r, pass._RenderTexture, ScaleMode.ScaleToFit);
179  GUI.TextField(r, pass.Source.ToString(), this.gui_style.box);
180  }
181  }
182  }
183 
184  TextureFlipper _asf;
185  }
186 
190  [Serializable]
191  public struct CapturePassMaterial {
193  public bool _NeedsRescale;
194  public Material _Material;
195  public RenderTexture _RenderTexture;
196  public CameraEvent When;
197  public BuiltinRenderTextureType Source;
198  public int _TextureId;
199 
200  public CapturePassMaterial(CameraEvent when = CameraEvent.AfterEverything,
201  BuiltinRenderTextureType source = BuiltinRenderTextureType.CurrentActive) {
202  this.When = when;
203  this.Source = source;
204  this._Material = null;
205  this._RenderTexture = null;
206  this._SupportsAntialiasing = false;
207  this._NeedsRescale = false;
208  this._TextureId = 0;
209  }
210  }
211 
212  public class TextureFlipper : IDisposable {
213  Shader _m_sh_v_flip;
214  Material _m_vf_lip_material;
215  RenderTexture _m_work_texture;
216 
217  public TextureFlipper() {
218  this._m_sh_v_flip = Shader.Find("Neodroid/Experimental/VerticalFlipper");
219  if (this._m_sh_v_flip) {
220  this._m_vf_lip_material = new Material(this._m_sh_v_flip);
221  }
222  }
223 
224  public void Flip(RenderTexture target) {
225  if (this._m_work_texture == null
226  || this._m_work_texture.width != target.width
227  || this._m_work_texture.height != target.height) {
228  UnityHelpers.Destroy(this._m_work_texture);
229  this._m_work_texture = new RenderTexture(target.width,
230  target.height,
231  target.depth,
232  target.format,
233  RenderTextureReadWrite.Linear);
234  }
235 
236  if (this._m_vf_lip_material) {
237  Graphics.Blit(target, this._m_work_texture, this._m_vf_lip_material);
238  Graphics.Blit(this._m_work_texture, target);
239  }
240  }
241 
242  public void Dispose() {
243  UnityHelpers.Destroy(this._m_work_texture);
244  this._m_work_texture = null;
245  if (this._m_vf_lip_material) {
246  UnityHelpers.Destroy(this._m_vf_lip_material);
247  this._m_vf_lip_material = null;
248  }
249  }
250  }
251 
257  public static class UnityHelpers {
258  public static void Destroy(Object obj, bool allow_destroying_assets = false) {
259  if (obj == null) {
260  return;
261  }
262  #if UNITY_EDITOR
263  if (EditorApplication.isPlaying) {
264  Object.Destroy(obj);
265  } else {
266  Object.DestroyImmediate(obj, allow_destroying_assets);
267  }
268  #else
269  Object.Destroy(obj);
270  #endif
271  obj = null;
272  }
273 
274  public static bool IsPlaying() {
275  #if UNITY_EDITOR
276  return EditorApplication.isPlaying;
277  #else
278  return true;
279  #endif
280  }
281  }
282 }
CapturePassMaterial(CameraEvent when=CameraEvent.AfterEverything, BuiltinRenderTextureType source=BuiltinRenderTextureType.CurrentActive)