Unity SDK Docs 1.5.0-beta.6
Loading...
Searching...
No Matches
SplitStereoTextures.cs
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
17using UnityEngine;
18#if TILT_FIVE_SRP
19using UnityEngine.Rendering;
20#endif
21using System;
22
23namespace 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(Glasses.DisplayInfo displayInfo)
72 {
73 LeftTexture_GLS = new RenderTexture(
74 displayInfo.monoWidth,
75 displayInfo.height,
76 displayInfo.depthBuffer,
77 displayInfo.nativeTextureFormat);
78 LeftTexture_GLS.name = "Left Eye Output RenderTexture";
79 RightTexture_GLS = new RenderTexture(
80 displayInfo.monoWidth,
81 displayInfo.height,
82 displayInfo.depthBuffer,
83 displayInfo.nativeTextureFormat);
84 RightTexture_GLS.name = "Right Eye Output RenderTexture";
85
86 MonoPreviewTex = new RenderTexture(
87 displayInfo.monoWidth,
88 displayInfo.height,
89 displayInfo.depthBuffer,
90 RenderTextureFormat.Default);
91 MonoPreviewTex.name = "Mono Preview RenderTexture";
92 StereoPreviewTex = new RenderTexture(
93 displayInfo.stereoWidth,
94 displayInfo.height,
95 displayInfo.depthBuffer,
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}
The Glasses API and runtime.
Definition Glasses.cs:35
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.
void Initialize(Glasses.DisplayInfo displayInfo)
Creates and configures the stereo rendertextures.
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.