Tilt Five™ Unity API  1.4.1
SplitStereoTextures.cs
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2020-2023 Tilt Five, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 using UnityEngine;
18 #if TILT_FIVE_SRP
19 using UnityEngine.Rendering;
20 #endif
21 using System;
22 
23 namespace TiltFive
24 {
26  {
27  #region Public Fields
28 
33  public RenderTexture LeftTexture_GLS;
38  public RenderTexture RightTexture_GLS;
39 
40 
45  private IntPtr LeftTexHandle { get; set; }
50  private IntPtr RightTexHandle { get; set; }
51 
52 
56  public RenderTexture MonoPreviewTex;
60  public RenderTexture StereoPreviewTex;
61 
62  #endregion Public Fields
63 
64 
65  #region Public Functions
66 
71  public void Initialize()
72  {
73  LeftTexture_GLS = new RenderTexture(
78  LeftTexture_GLS.name = "Left Eye Output RenderTexture";
79  RightTexture_GLS = new RenderTexture(
84  RightTexture_GLS.name = "Right Eye Output RenderTexture";
85 
86  MonoPreviewTex = new RenderTexture(
90  RenderTextureFormat.Default);
91  MonoPreviewTex.name = "Mono Preview RenderTexture";
92  StereoPreviewTex = new RenderTexture(
96  RenderTextureFormat.Default);
97  StereoPreviewTex.name = "Stereo Preview RenderTexture";
98  }
99 
105  {
106  /* Render textures have a state (created or not created), and that state can be invalidated.
107  There are a few ways this can happen, including the game switching to/from fullscreen,
108  or the system screensaver being displayed. When this happens, the native texture pointers we
109  pass to the native plugin are also invalidated, and garbage data gets displayed by the glasses.
110 
111  To fix this, we can check whether the state has been invalidated and reacquire a valid native texture pointer.
112  RenderTexture's IsCreated() function reports false if the render texture has been invalidated.
113  We must detect this change in OnPreRender(), because IsCreated() reports true within Update().
114  If we detect that the render textures have been invalidated, we null out the cached pointers and reacquire.
115  */
116 
117  // Check whether the render textures' states have been invalidated,
118  // and reset the cached texture handles if so.
119  if (!LeftTexture_GLS.IsCreated() || !RightTexture_GLS.IsCreated())
120  {
121  LeftTexHandle = System.IntPtr.Zero;
122  RightTexHandle = System.IntPtr.Zero;
123  }
124  }
125 
130  public void GetNativeTexturePointers(out IntPtr leftTexHandle, out IntPtr rightTexHandle)
131  {
132  // If the native texture handles were reset by ValidateNativeTexturePointers(), reacquire them
133  if(LeftTexHandle == IntPtr.Zero || RightTexHandle == IntPtr.Zero)
134  {
135  LeftTexHandle = LeftTexture_GLS.GetNativeTexturePtr();
136  RightTexHandle = RightTexture_GLS.GetNativeTexturePtr();
137  }
138 
139  leftTexHandle = LeftTexHandle;
140  rightTexHandle = RightTexHandle;
141  }
142 
147  public void SubmitPreviewTextures(GlassesMirrorMode glassesMirrorMode)
148  {
149  var previewTex = glassesMirrorMode == GlassesMirrorMode.Stereoscopic ? StereoPreviewTex : MonoPreviewTex;
150 
151  switch (glassesMirrorMode)
152  {
153  case GlassesMirrorMode.LeftEye:
154  CopyTexture(LeftTexture_GLS, previewTex);
155  break;
156  case GlassesMirrorMode.RightEye:
157  CopyTexture(RightTexture_GLS, previewTex);
158  break;
159  case GlassesMirrorMode.Stereoscopic:
160  // Copy the two eyes' target textures to a double-wide texture, then display it onscreen.
161  CopyTexture(LeftTexture_GLS, previewTex);
162  CopyTexture(RightTexture_GLS, previewTex, LeftTexture_GLS.width);
163  break;
164  }
165  }
166 #if TILT_FIVE_SRP
167  public void SubmitPreviewTexturesSRP(
168  GlassesMirrorMode glassesMirrorMode,
169  Camera headPoseCamera,
170  CommandBuffer commandBuffer,
171  Vector2 frameScale)
172  {
173  var previewTex = glassesMirrorMode == GlassesMirrorMode.Stereoscopic ? StereoPreviewTex : MonoPreviewTex;
174 
175  switch (glassesMirrorMode)
176  {
177  case GlassesMirrorMode.LeftEye:
178  CopyTextureToPreviewTextureSRP(commandBuffer, LeftTexture_GLS, previewTex);
179  break;
180  case GlassesMirrorMode.RightEye:
181  CopyTextureToPreviewTextureSRP(commandBuffer, RightTexture_GLS, previewTex);
182  break;
183  case GlassesMirrorMode.Stereoscopic:
184  // Copy the two eyes' target textures to a double-wide texture, then display it onscreen.
185  CopyTextureToPreviewTextureSRP(commandBuffer, LeftTexture_GLS, previewTex);
186  CopyTextureToPreviewTextureSRP(commandBuffer, RightTexture_GLS, previewTex, LeftTexture_GLS.width);
187  break;
188  }
189 
190  // We're going to composite the left/right eye cameras into a temporary render texture.
191  var tempRTIdentifier = Shader.PropertyToID("TiltFiveCanvas");
192  int tempRTWidth = (int)(previewTex.width * frameScale.x);
193  int tempRTHeight = (int)(previewTex.height * frameScale.y);
194 
195  RenderTargetIdentifier currentRenderTarget = BuiltinRenderTextureType.CurrentActive;
196 
197  // As of Unity 2020.3.24f1, it appears that this will result in an error if MSAA is
198  // enabled with D3D11, which will look something like:
199  //
200  // D3D11: Failed to create RenderTexture (1432 x 768 fmt 27 aa 2), error 0x80070057
201  //
202  // This does not appear to prevent the onscreen preview from working, so it's unclear
203  // whether this is really a problem. Disabling MSAA will get the error to go away, but
204  // is not recommended. This code is only executed if using one of the eye camera mirror
205  // modes, and we recommend setting the glasses mirror mode to None in release builds.
206  //
207  // See: https://answers.unity.com/questions/1592194/getting-d3d11-failed-to-create-render-texture-erro.html
208  commandBuffer.GetTemporaryRT(tempRTIdentifier,
209  tempRTWidth,
210  tempRTHeight,
211  previewTex.descriptor.depthBufferBits,
212  previewTex.filterMode,
213  previewTex.format,
214  RenderTextureReadWrite.Default,
215  previewTex.antiAliasing,
216  true // needs random access for the CopyTexture below to work with nonzero offset
217  );
218  commandBuffer.SetRenderTarget(tempRTIdentifier);
219  commandBuffer.ClearRenderTarget(true, true, Color.black);
220  commandBuffer.CopyTexture(previewTex, 0, 0, 0, 0,
221  previewTex.width, previewTex.height,
222  tempRTIdentifier, 0, 0,
223  (tempRTWidth - previewTex.width) / 2, (tempRTHeight - previewTex.height) / 2);
224  commandBuffer.Blit(tempRTIdentifier, headPoseCamera.targetTexture, Vector2.one, Vector2.zero);
225  commandBuffer.ReleaseTemporaryRT(tempRTIdentifier);
226  commandBuffer.SetRenderTarget(currentRenderTarget);
227  }
228 #endif // TILT_FIVE_SRP
229 
230  #endregion Public Functions
231 
232 
233  #region Private Functions
234 
235  void CopyTexture(RenderTexture sourceTex, RenderTexture destinationTex, int xOffset = 0)
236  {
237  Graphics.CopyTexture(
238  sourceTex,
239  0, // srcElement
240  0, // srcMip
241  0, 0, // src offset
242  sourceTex.width, sourceTex.height, // src size
243  destinationTex,
244  0, // dstElement
245  0, // dstMip
246  xOffset, 0); // dst offset
247  }
248 #if TILT_FIVE_SRP
249  void CopyTextureToPreviewTextureSRP(CommandBuffer cmd, RenderTexture sourceTex, RenderTexture destinationTex, int xOffset = 0)
250  {
251  cmd.CopyTexture(
252  sourceTex,
253  0,
254  0,
255  0, 0,
256  sourceTex.width, sourceTex.height,
257  destinationTex,
258  0, 0, xOffset, 0);
259  }
260 #endif
261 
262  #endregion Private Functions
263  }
264 }
Display settings constants.
const RenderTextureFormat nativeTextureFormat
static int monoWidth
The display width for a single eye.
static int height
The display height.
const int depthBuffer
The depth buffer's precision.
static int stereoWidth
The display width for two eyes.
RenderTexture MonoPreviewTex
The rendertexture used to display onscreen previews for the left or right eye camera.
void ValidateNativeTexturePointers()
Determines whether the left/right texture handles are still valid, and resets them if needed
void GetNativeTexturePointers(out IntPtr leftTexHandle, out IntPtr rightTexHandle)
Acquires the native output textures upon startup or invalidaiton.
IntPtr RightTexHandle
The native pointer to the right eye rendertexture
void CopyTexture(RenderTexture sourceTex, RenderTexture destinationTex, int xOffset=0)
IntPtr LeftTexHandle
The native pointer to the left eye rendertexture
void SubmitPreviewTextures(GlassesMirrorMode glassesMirrorMode)
Copies frame data from the HDR input textures to the onscreen preview textures.
RenderTexture LeftTexture_GLS
The left eye rendertexture
RenderTexture RightTexture_GLS
The right eye rendertexture
RenderTexture StereoPreviewTex
The rendertexture used to display onscreen previews for the left and right eye cameras in stereo.
void Initialize()
Creates and configures the stereo rendertextures
Definition: Log.cs:21