rev |
line source |
nuclear@0
|
1 /************************************************************************************
|
nuclear@0
|
2
|
nuclear@0
|
3 Filename : Util_Render_Stereo.h
|
nuclear@0
|
4 Content : Sample stereo rendering configuration classes.
|
nuclear@0
|
5 Created : October 22, 2012
|
nuclear@0
|
6 Authors : Michael Antonov, Tom Forsyth
|
nuclear@0
|
7
|
nuclear@0
|
8 Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved.
|
nuclear@0
|
9
|
nuclear@0
|
10 Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License");
|
nuclear@0
|
11 you may not use the Oculus VR Rift SDK except in compliance with the License,
|
nuclear@0
|
12 which is provided at the time of installation or download, or which
|
nuclear@0
|
13 otherwise accompanies this software in either electronic or hard copy form.
|
nuclear@0
|
14
|
nuclear@0
|
15 You may obtain a copy of the License at
|
nuclear@0
|
16
|
nuclear@0
|
17 http://www.oculusvr.com/licenses/LICENSE-3.2
|
nuclear@0
|
18
|
nuclear@0
|
19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
|
nuclear@0
|
20 distributed under the License is distributed on an "AS IS" BASIS,
|
nuclear@0
|
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
nuclear@0
|
22 See the License for the specific language governing permissions and
|
nuclear@0
|
23 limitations under the License.
|
nuclear@0
|
24
|
nuclear@0
|
25 *************************************************************************************/
|
nuclear@0
|
26
|
nuclear@0
|
27 #ifndef OVR_Util_Render_Stereo_h
|
nuclear@0
|
28 #define OVR_Util_Render_Stereo_h
|
nuclear@0
|
29
|
nuclear@0
|
30 #include "../OVR_Stereo.h"
|
nuclear@0
|
31 #include "../Tracking/Tracking_SensorStateReader.h"
|
nuclear@0
|
32
|
nuclear@0
|
33 namespace OVR { namespace Util { namespace Render {
|
nuclear@0
|
34
|
nuclear@0
|
35
|
nuclear@0
|
36
|
nuclear@0
|
37 //-----------------------------------------------------------------------------------
|
nuclear@0
|
38 // **** Useful debug functions.
|
nuclear@0
|
39 //
|
nuclear@0
|
40 // Purely for debugging - the results are not very end-user-friendly.
|
nuclear@0
|
41 char const* GetDebugNameEyeCupType ( EyeCupType eyeCupType );
|
nuclear@0
|
42 char const* GetDebugNameHmdType ( HmdTypeEnum hmdType );
|
nuclear@0
|
43
|
nuclear@0
|
44
|
nuclear@0
|
45
|
nuclear@0
|
46 //-----------------------------------------------------------------------------------
|
nuclear@0
|
47 // **** Higher-level utility functions.
|
nuclear@0
|
48
|
nuclear@0
|
49 Sizei CalculateRecommendedTextureSize ( HmdRenderInfo const &hmd,
|
nuclear@0
|
50 bool bRendertargetSharedByBothEyes,
|
nuclear@0
|
51 float pixelDensityInCenter = 1.0f );
|
nuclear@0
|
52
|
nuclear@0
|
53 FovPort CalculateRecommendedFov ( HmdRenderInfo const &hmd,
|
nuclear@0
|
54 StereoEye eyeType,
|
nuclear@0
|
55 bool bMakeFovSymmetrical = false);
|
nuclear@0
|
56
|
nuclear@0
|
57 StereoEyeParams CalculateStereoEyeParams ( HmdRenderInfo const &hmd,
|
nuclear@0
|
58 StereoEye eyeType,
|
nuclear@0
|
59 Sizei const &actualRendertargetSurfaceSize,
|
nuclear@0
|
60 bool bRendertargetSharedByBothEyes,
|
nuclear@0
|
61 bool bRightHanded = true,
|
nuclear@0
|
62 float zNear = 0.01f, float zFar = 10000.0f,
|
nuclear@0
|
63 Sizei const *pOverrideRenderedPixelSize = NULL,
|
nuclear@0
|
64 FovPort const *pOverrideFovport = NULL,
|
nuclear@0
|
65 float zoomFactor = 1.0f );
|
nuclear@0
|
66
|
nuclear@0
|
67 Vector3f CalculateEyeVirtualCameraOffset(HmdRenderInfo const &hmd,
|
nuclear@0
|
68 StereoEye eyeType, bool bMonoRenderingMode );
|
nuclear@0
|
69
|
nuclear@0
|
70
|
nuclear@0
|
71 // These are two components from StereoEyeParams that can be changed
|
nuclear@0
|
72 // very easily without full recomputation of everything.
|
nuclear@0
|
73 struct ViewportScaleAndOffset
|
nuclear@0
|
74 {
|
nuclear@0
|
75 Recti RenderedViewport;
|
nuclear@0
|
76 ScaleAndOffset2D EyeToSourceUV;
|
nuclear@0
|
77 };
|
nuclear@0
|
78
|
nuclear@0
|
79 // Three ways to override the size of the render view dynamically.
|
nuclear@0
|
80 // None of these require changing the distortion parameters or the regenerating the distortion mesh,
|
nuclear@0
|
81 // and can be called every frame if desired.
|
nuclear@0
|
82 ViewportScaleAndOffset ModifyRenderViewport ( StereoEyeParams const ¶ms,
|
nuclear@0
|
83 Sizei const &actualRendertargetSurfaceSize,
|
nuclear@0
|
84 Recti const &renderViewport );
|
nuclear@0
|
85
|
nuclear@0
|
86 ViewportScaleAndOffset ModifyRenderSize ( StereoEyeParams const ¶ms,
|
nuclear@0
|
87 Sizei const &actualRendertargetSurfaceSize,
|
nuclear@0
|
88 Sizei const &requestedRenderSize,
|
nuclear@0
|
89 bool bRendertargetSharedByBothEyes = false );
|
nuclear@0
|
90
|
nuclear@0
|
91 ViewportScaleAndOffset ModifyRenderDensity ( StereoEyeParams const ¶ms,
|
nuclear@0
|
92 Sizei const &actualRendertargetSurfaceSize,
|
nuclear@0
|
93 float pixelDensity = 1.0f,
|
nuclear@0
|
94 bool bRendertargetSharedByBothEyes = false );
|
nuclear@0
|
95
|
nuclear@0
|
96
|
nuclear@0
|
97 //-----------------------------------------------------------------------------------
|
nuclear@0
|
98 // ***** StereoConfig
|
nuclear@0
|
99
|
nuclear@0
|
100 // StereoConfig maintains a scene stereo state and allow switching between different
|
nuclear@0
|
101 // stereo rendering modes. To support rendering, StereoConfig keeps track of HMD
|
nuclear@0
|
102 // variables such as screen size, eye-to-screen distance and distortion, and computes
|
nuclear@0
|
103 // extra data such as FOV and distortion center offsets based on it. Rendering
|
nuclear@0
|
104 // parameters are returned though StereoEyeParams for each eye.
|
nuclear@0
|
105 //
|
nuclear@0
|
106 // Beyond regular 3D projection, this class supports rendering a 2D orthographic
|
nuclear@0
|
107 // surface for UI and text. The 2D surface will be defined by CreateOrthoSubProjection().
|
nuclear@0
|
108 // The (0,0) coordinate corresponds to eye center location.
|
nuclear@0
|
109 //
|
nuclear@0
|
110 // Applications are not required to use this class, but they should be doing very
|
nuclear@0
|
111 // similar sequences of operations, and it may be useful to start with this class
|
nuclear@0
|
112 // and modify it.
|
nuclear@0
|
113
|
nuclear@0
|
114 struct StereoEyeParamsWithOrtho
|
nuclear@0
|
115 {
|
nuclear@0
|
116 StereoEyeParams StereoEye;
|
nuclear@0
|
117 Matrix4f OrthoProjection;
|
nuclear@0
|
118 };
|
nuclear@0
|
119
|
nuclear@0
|
120 struct ViewportScaleAndOffsetBothEyes
|
nuclear@0
|
121 {
|
nuclear@0
|
122 ViewportScaleAndOffset Left;
|
nuclear@0
|
123 ViewportScaleAndOffset Right;
|
nuclear@0
|
124 };
|
nuclear@0
|
125
|
nuclear@0
|
126 class StereoConfig
|
nuclear@0
|
127 {
|
nuclear@0
|
128 public:
|
nuclear@0
|
129
|
nuclear@0
|
130 // StereoMode describes rendering modes that can be used by StereoConfig.
|
nuclear@0
|
131 // These modes control whether stereo rendering is used or not (Stereo_None),
|
nuclear@0
|
132 // and how it is implemented.
|
nuclear@0
|
133 enum StereoMode
|
nuclear@0
|
134 {
|
nuclear@0
|
135 Stereo_None = 0, // Single eye
|
nuclear@0
|
136 Stereo_LeftRight_Multipass = 1, // One frustum per eye
|
nuclear@0
|
137 };
|
nuclear@0
|
138
|
nuclear@0
|
139
|
nuclear@0
|
140 StereoConfig(StereoMode mode = Stereo_LeftRight_Multipass);
|
nuclear@0
|
141
|
nuclear@0
|
142 //---------------------------------------------------------------------------------------------
|
nuclear@0
|
143 // *** Core functions - every app MUST call these functions at least once.
|
nuclear@0
|
144
|
nuclear@0
|
145 // Sets HMD parameters; also initializes distortion coefficients.
|
nuclear@0
|
146 void SetHmdRenderInfo(const HmdRenderInfo& hmd);
|
nuclear@0
|
147
|
nuclear@0
|
148 // Set the physical size of the rendertarget surface the app created,
|
nuclear@0
|
149 // and whether one RT is shared by both eyes, or each eye has its own RT:
|
nuclear@0
|
150 // true: both eyes are rendered to the same RT. Left eye starts at top-left, right eye starts at top-middle.
|
nuclear@0
|
151 // false: each eye is rendered to its own RT. Some GPU architectures prefer this arrangement.
|
nuclear@0
|
152 // Typically, the app would call CalculateRecommendedTextureSize() to suggest the choice of RT size.
|
nuclear@0
|
153 // This setting must be exactly the size of the actual RT created, or the UVs produced will be incorrect.
|
nuclear@0
|
154 // If the app wants to render to a subsection of the RT, it should use SetRenderSize()
|
nuclear@0
|
155 void SetRendertargetSize (Size<int> const rendertargetSize,
|
nuclear@0
|
156 bool rendertargetIsSharedByBothEyes );
|
nuclear@0
|
157
|
nuclear@0
|
158 // Returns full set of Stereo rendering parameters for the specified eye.
|
nuclear@0
|
159 const StereoEyeParamsWithOrtho& GetEyeRenderParams(StereoEye eye);
|
nuclear@0
|
160
|
nuclear@0
|
161
|
nuclear@0
|
162
|
nuclear@0
|
163 //---------------------------------------------------------------------------------------------
|
nuclear@0
|
164 // *** Optional functions - an app may call these to override default behaviours.
|
nuclear@0
|
165
|
nuclear@0
|
166 const HmdRenderInfo& GetHmdRenderInfo() const { return Hmd; }
|
nuclear@0
|
167
|
nuclear@0
|
168 // Returns the recommended size of rendertargets.
|
nuclear@0
|
169 // If rendertargetIsSharedByBothEyes is true, this is the size of the combined buffer.
|
nuclear@0
|
170 // If rendertargetIsSharedByBothEyes is false, this is the size of each individual buffer.
|
nuclear@0
|
171 // pixelDensityInCenter may be set to any number - by default it will match the HMD resolution in the center of the image.
|
nuclear@0
|
172 // After creating the rendertargets, the application MUST call SetRendertargetSize() with the actual size created
|
nuclear@0
|
173 // (which can be larger or smaller as the app wishes, but StereoConfig needs to know either way)
|
nuclear@0
|
174 Sizei CalculateRecommendedTextureSize ( bool rendertargetSharedByBothEyes,
|
nuclear@0
|
175 float pixelDensityInCenter = 1.0f );
|
nuclear@0
|
176
|
nuclear@0
|
177 // Sets a stereo rendering mode and updates internal cached
|
nuclear@0
|
178 // state (matrices, per-eye view) based on it.
|
nuclear@0
|
179 void SetStereoMode(StereoMode mode) { Mode = mode; DirtyFlag = true; }
|
nuclear@0
|
180 StereoMode GetStereoMode() const { return Mode; }
|
nuclear@0
|
181
|
nuclear@0
|
182 // Sets the fieldOfView that the 2D coordinate area stretches to.
|
nuclear@0
|
183 void Set2DAreaFov(float fovRadians);
|
nuclear@0
|
184
|
nuclear@0
|
185 // Really only for science experiments - no normal app should ever need to override
|
nuclear@0
|
186 // the HMD's lens descriptors. Passing NULL removes the override.
|
nuclear@0
|
187 // Supply both = set left and right.
|
nuclear@0
|
188 // Supply just left = set both to the same.
|
nuclear@0
|
189 // Supply neither = remove override.
|
nuclear@0
|
190 void SetLensOverride ( LensConfig const *pLensOverrideLeft = NULL,
|
nuclear@0
|
191 LensConfig const *pLensOverrideRight = NULL );
|
nuclear@0
|
192
|
nuclear@0
|
193 // Override the rendered FOV in various ways. All angles in tangent units.
|
nuclear@0
|
194 // This is not clamped to the physical FOV of the display - you'll need to do that yourself!
|
nuclear@0
|
195 // Supply both = set left and right.
|
nuclear@0
|
196 // Supply just left = set both to the same.
|
nuclear@0
|
197 // Supply neither = remove override.
|
nuclear@0
|
198 void SetFov ( FovPort const *pfovLeft = NULL,
|
nuclear@0
|
199 FovPort const *pfovRight = NULL );
|
nuclear@0
|
200
|
nuclear@0
|
201 void SetFovPortRadians ( float horizontal, float vertical )
|
nuclear@0
|
202 {
|
nuclear@0
|
203 FovPort fov = FovPort::CreateFromRadians(horizontal, vertical);
|
nuclear@0
|
204 SetFov( &fov, &fov );
|
nuclear@0
|
205 }
|
nuclear@0
|
206
|
nuclear@0
|
207
|
nuclear@0
|
208 // This forces a "zero IPD" mode where there is just a single render with an FOV that
|
nuclear@0
|
209 // is the union of the two calculated FOVs.
|
nuclear@0
|
210 // The calculated render is for the left eye. Any size & FOV overrides for the right
|
nuclear@0
|
211 // eye will be ignored.
|
nuclear@0
|
212 // If you query the right eye's size, you will get the same render
|
nuclear@0
|
213 // size & position as the left eye - you should not actually do the render of course!
|
nuclear@0
|
214 // The distortion values will be different, because it goes to a different place on the framebuffer.
|
nuclear@0
|
215 // Note that if you do this, the rendertarget does not need to be twice the width of
|
nuclear@0
|
216 // the render size any more.
|
nuclear@0
|
217 void SetZeroVirtualIpdOverride ( bool enableOverride );
|
nuclear@0
|
218
|
nuclear@0
|
219 // Allows the app to specify near and far clip planes and the right/left-handedness of the projection matrix.
|
nuclear@0
|
220 void SetZClipPlanesAndHandedness ( float zNear = 0.01f, float zFar = 10000.0f,
|
nuclear@0
|
221 bool rightHandedProjection = true );
|
nuclear@0
|
222
|
nuclear@0
|
223 // Allows the app to specify how much extra eye rotation to allow when determining the visible FOV.
|
nuclear@0
|
224 void SetExtraEyeRotation ( float extraEyeRotationInRadians = 0.0f );
|
nuclear@0
|
225
|
nuclear@0
|
226 // The dirty flag is set by any of the above calls. Just handy for the app to know
|
nuclear@0
|
227 // if e.g. the distortion mesh needs regeneration.
|
nuclear@0
|
228 void SetDirty() { DirtyFlag = true; }
|
nuclear@0
|
229 bool IsDirty() { return DirtyFlag; }
|
nuclear@0
|
230
|
nuclear@0
|
231 // An app never needs to call this - GetEyeRenderParams will call it internally if
|
nuclear@0
|
232 // the state is dirty. However apps can call this explicitly to control when and where
|
nuclear@0
|
233 // computation is performed (e.g. not inside critical loops)
|
nuclear@0
|
234 void UpdateComputedState();
|
nuclear@0
|
235
|
nuclear@0
|
236 // This returns the projection matrix with a "zoom". Does not modify any internal state.
|
nuclear@0
|
237 Matrix4f GetProjectionWithZoom ( StereoEye eye, float fovZoom ) const;
|
nuclear@0
|
238
|
nuclear@0
|
239
|
nuclear@0
|
240 //---------------------------------------------------------------------------------------------
|
nuclear@0
|
241 // The SetRender* functions are special.
|
nuclear@0
|
242 //
|
nuclear@0
|
243 // They do not require a full recalculation of state, and they do not change anything but the
|
nuclear@0
|
244 // ViewportScaleAndOffset data for the eyes (which they return), and do not set the dirty flag!
|
nuclear@0
|
245 // This means they can be called without regenerating the distortion mesh, and thus
|
nuclear@0
|
246 // can happily be called every frame without causing performance problems. Dynamic rescaling
|
nuclear@0
|
247 // of the rendertarget can help keep framerate up in demanding VR applications.
|
nuclear@0
|
248 // See the documentation for more details on their use.
|
nuclear@0
|
249
|
nuclear@0
|
250 // Specify a pixel density - how many rendered pixels per pixel in the physical display.
|
nuclear@0
|
251 ViewportScaleAndOffsetBothEyes SetRenderDensity ( float pixelsPerDisplayPixel );
|
nuclear@0
|
252
|
nuclear@0
|
253 // Supply the size directly. Will be clamped to the physical rendertarget size.
|
nuclear@0
|
254 ViewportScaleAndOffsetBothEyes SetRenderSize ( Sizei const &renderSizeLeft, Sizei const &renderSizeRight );
|
nuclear@0
|
255
|
nuclear@0
|
256 // Supply the viewport directly. This is not clamped to the physical rendertarget - careful now!
|
nuclear@0
|
257 ViewportScaleAndOffsetBothEyes SetRenderViewport ( Recti const &renderViewportLeft, Recti const &renderViewportRight );
|
nuclear@0
|
258
|
nuclear@0
|
259 private:
|
nuclear@0
|
260
|
nuclear@0
|
261 // *** Modifiable State
|
nuclear@0
|
262
|
nuclear@0
|
263 StereoMode Mode;
|
nuclear@0
|
264 HmdRenderInfo Hmd;
|
nuclear@0
|
265
|
nuclear@0
|
266 float Area2DFov; // FOV range mapping to the 2D area.
|
nuclear@0
|
267
|
nuclear@0
|
268 // Only one of these three overrides can be true!
|
nuclear@0
|
269 enum SetViewportModeEnum
|
nuclear@0
|
270 {
|
nuclear@0
|
271 SVPM_Density,
|
nuclear@0
|
272 SVPM_Size,
|
nuclear@0
|
273 SVPM_Viewport,
|
nuclear@0
|
274 } SetViewportMode;
|
nuclear@0
|
275 // ...and depending which it is, one of the following are used.
|
nuclear@0
|
276 float SetViewportPixelsPerDisplayPixel;
|
nuclear@0
|
277 Sizei SetViewportSize[2];
|
nuclear@0
|
278 Recti SetViewport[2];
|
nuclear@0
|
279
|
nuclear@0
|
280 // Other overrides.
|
nuclear@0
|
281 bool OverrideLens;
|
nuclear@0
|
282 LensConfig LensOverrideLeft;
|
nuclear@0
|
283 LensConfig LensOverrideRight;
|
nuclear@0
|
284 Sizei RendertargetSize;
|
nuclear@0
|
285 bool OverrideTanHalfFov;
|
nuclear@0
|
286 FovPort FovOverrideLeft;
|
nuclear@0
|
287 FovPort FovOverrideRight;
|
nuclear@0
|
288 bool OverrideZeroIpd;
|
nuclear@0
|
289 float ZNear;
|
nuclear@0
|
290 float ZFar;
|
nuclear@0
|
291 float ExtraEyeRotationInRadians;
|
nuclear@0
|
292 bool IsRendertargetSharedByBothEyes;
|
nuclear@0
|
293 bool RightHandedProjection;
|
nuclear@0
|
294
|
nuclear@0
|
295 bool DirtyFlag; // Set when any if the modifiable state changed. Does NOT get set by SetRender*()
|
nuclear@0
|
296
|
nuclear@0
|
297 // Utility function.
|
nuclear@0
|
298 ViewportScaleAndOffsetBothEyes setupViewportScaleAndOffsets();
|
nuclear@0
|
299
|
nuclear@0
|
300 // *** Computed State
|
nuclear@0
|
301
|
nuclear@0
|
302 public: // Small hack for the config tool. Normal code should never read EyeRenderParams directly - use GetEyeRenderParams() instead.
|
nuclear@0
|
303 // 0/1 = left/right main views.
|
nuclear@0
|
304 StereoEyeParamsWithOrtho EyeRenderParams[2];
|
nuclear@0
|
305 };
|
nuclear@0
|
306
|
nuclear@0
|
307
|
nuclear@0
|
308 //-----------------------------------------------------------------------------------
|
nuclear@0
|
309 // ***** Distortion Mesh Rendering
|
nuclear@0
|
310 //
|
nuclear@0
|
311
|
nuclear@0
|
312 // Stores both texture UV coords, or tan(angle) values.
|
nuclear@0
|
313 // Use whichever set of data the specific distortion algorithm requires.
|
nuclear@0
|
314 // This struct *must* be binary compatible with CAPI ovrDistortionVertex.
|
nuclear@0
|
315 struct DistortionMeshVertexData
|
nuclear@0
|
316 {
|
nuclear@0
|
317 // [-1,+1],[-1,+1] over the entire framebuffer.
|
nuclear@0
|
318 Vector2f ScreenPosNDC;
|
nuclear@0
|
319 // [0.0-1.0] interpolation value for timewarping - see documentation for details.
|
nuclear@0
|
320 float TimewarpLerp;
|
nuclear@0
|
321 // [0.0-1.0] fade-to-black at the edges to reduce peripheral vision noise.
|
nuclear@0
|
322 float Shade;
|
nuclear@0
|
323 // The red, green, and blue vectors in tan(angle) space.
|
nuclear@0
|
324 // Scale and offset by the values in StereoEyeParams.EyeToSourceUV.Scale
|
nuclear@0
|
325 // and StereoParams.EyeToSourceUV.Offset to get to real texture UV coords.
|
nuclear@0
|
326 Vector2f TanEyeAnglesR;
|
nuclear@0
|
327 Vector2f TanEyeAnglesG;
|
nuclear@0
|
328 Vector2f TanEyeAnglesB;
|
nuclear@0
|
329 };
|
nuclear@0
|
330
|
nuclear@0
|
331 // If you just want a single point on the screen transformed.
|
nuclear@0
|
332 DistortionMeshVertexData DistortionMeshMakeVertex ( Vector2f screenNDC,
|
nuclear@0
|
333 bool rightEye,
|
nuclear@0
|
334 const HmdRenderInfo &hmdRenderInfo,
|
nuclear@0
|
335 const DistortionRenderDesc &distortion, const ScaleAndOffset2D &eyeToSourceNDC );
|
nuclear@0
|
336
|
nuclear@0
|
337 void DistortionMeshCreate ( DistortionMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
|
nuclear@0
|
338 int *pNumVertices, int *pNumTriangles,
|
nuclear@0
|
339 const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo );
|
nuclear@0
|
340
|
nuclear@0
|
341 // Generate distortion mesh for a eye.
|
nuclear@0
|
342 // This version requires less data then stereoParms, supporting dynamic change in render target viewport.
|
nuclear@0
|
343 void DistortionMeshCreate( DistortionMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
|
nuclear@0
|
344 int *pNumVertices, int *pNumTriangles,
|
nuclear@0
|
345 bool rightEye,
|
nuclear@0
|
346 const HmdRenderInfo &hmdRenderInfo,
|
nuclear@0
|
347 const DistortionRenderDesc &distortion, const ScaleAndOffset2D &eyeToSourceNDC );
|
nuclear@0
|
348
|
nuclear@0
|
349 void DistortionMeshDestroy ( DistortionMeshVertexData *pVertices, uint16_t *pTriangleMeshIndices );
|
nuclear@0
|
350
|
nuclear@0
|
351
|
nuclear@0
|
352 //-----------------------------------------------------------------------------------
|
nuclear@0
|
353 // ***** Heightmap Mesh Rendering
|
nuclear@0
|
354 //
|
nuclear@0
|
355
|
nuclear@0
|
356 // Stores both texture UV coords, or tan(angle) values.
|
nuclear@0
|
357 // This struct *must* be binary compatible with CAPI ovrHeightmapVertex.
|
nuclear@0
|
358 struct HeightmapMeshVertexData
|
nuclear@0
|
359 {
|
nuclear@0
|
360 // [-1,+1],[-1,+1] over the entire framebuffer.
|
nuclear@0
|
361 Vector2f ScreenPosNDC;
|
nuclear@0
|
362 // [0.0-1.0] interpolation value for timewarping - see documentation for details.
|
nuclear@0
|
363 float TimewarpLerp;
|
nuclear@0
|
364 // The vectors in tan(angle) space.
|
nuclear@0
|
365 // Scale and offset by the values in StereoEyeParams.EyeToSourceUV.Scale
|
nuclear@0
|
366 // and StereoParams.EyeToSourceUV.Offset to get to real texture UV coords.
|
nuclear@0
|
367 Vector2f TanEyeAngles;
|
nuclear@0
|
368 };
|
nuclear@0
|
369
|
nuclear@0
|
370
|
nuclear@0
|
371 void HeightmapMeshCreate ( HeightmapMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
|
nuclear@0
|
372 int *pNumVertices, int *pNumTriangles,
|
nuclear@0
|
373 const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo );
|
nuclear@0
|
374
|
nuclear@0
|
375 // Generate heightmap mesh for a eye. This version requires less data then stereoParms, supporting
|
nuclear@0
|
376 // dynamic change in render target viewport.
|
nuclear@0
|
377 void HeightmapMeshCreate( HeightmapMeshVertexData **ppVertices, uint16_t **ppTriangleListIndices,
|
nuclear@0
|
378 int *pNumVertices, int *pNumTriangles, bool rightEye,
|
nuclear@0
|
379 const HmdRenderInfo &hmdRenderInfo, const ScaleAndOffset2D &eyeToSourceNDC );
|
nuclear@0
|
380
|
nuclear@0
|
381 void HeightmapMeshDestroy ( HeightmapMeshVertexData *pVertices, uint16_t *pTriangleMeshIndices );
|
nuclear@0
|
382
|
nuclear@0
|
383
|
nuclear@0
|
384
|
nuclear@0
|
385 //-----------------------------------------------------------------------------------
|
nuclear@0
|
386 // ***** Prediction and timewarp.
|
nuclear@0
|
387 //
|
nuclear@0
|
388
|
nuclear@0
|
389 struct PredictionValues
|
nuclear@0
|
390 {
|
nuclear@0
|
391 // All values in seconds.
|
nuclear@0
|
392 // These are the times in seconds from a present+flush to the relevant display element.
|
nuclear@0
|
393 // The time is measured to the middle of that element's visibility window,
|
nuclear@0
|
394 // e.g. if the device is a full-persistence display, the element will be visible for
|
nuclear@0
|
395 // an entire frame, so the time measures to the middle of that period, i.e. half the frame time.
|
nuclear@0
|
396 float PresentFlushToRenderedScene; // To the overall rendered 3D scene being visible.
|
nuclear@0
|
397 float PresentFlushToTimewarpStart; // To when the first timewarped scanline will be visible.
|
nuclear@0
|
398 float PresentFlushToTimewarpEnd; // To when the last timewarped scanline will be visible.
|
nuclear@0
|
399 float PresentFlushToPresentFlush; // To the next present+flush, i.e. the ideal framerate.
|
nuclear@0
|
400
|
nuclear@0
|
401 bool WithTimewarp;
|
nuclear@0
|
402 bool WithVsync;
|
nuclear@0
|
403 };
|
nuclear@0
|
404
|
nuclear@0
|
405 // Calculates the values from the HMD info.
|
nuclear@0
|
406 PredictionValues PredictionGetDeviceValues ( const HmdRenderInfo &hmdRenderInfo,
|
nuclear@0
|
407 bool withTimewarp = true,
|
nuclear@0
|
408 bool withVsync = true );
|
nuclear@0
|
409
|
nuclear@0
|
410 // Pass in an orientation used to render the scene, and then the predicted orientation
|
nuclear@0
|
411 // (which may have been computed later on, and thus is more accurate), and this
|
nuclear@0
|
412 // will return the matrix to pass to the timewarp distortion shader.
|
nuclear@0
|
413 // TODO: deal with different handedness?
|
nuclear@0
|
414 Matrix4f TimewarpComputePoseDelta ( Matrix4f const &renderedViewFromWorld, Matrix4f const &predictedViewFromWorld, Matrix4f const&hmdToEyeViewOffset );
|
nuclear@0
|
415 Matrix4f TimewarpComputePoseDeltaPosition ( Matrix4f const &renderedViewFromWorld, Matrix4f const &predictedViewFromWorld, Matrix4f const&hmdToEyeViewOffset );
|
nuclear@0
|
416
|
nuclear@0
|
417
|
nuclear@0
|
418
|
nuclear@0
|
419 // TimewarpMachine helps keep track of rendered frame timing and
|
nuclear@0
|
420 // handles predictions for time-warp rendering.
|
nuclear@0
|
421 class TimewarpMachine
|
nuclear@0
|
422 {
|
nuclear@0
|
423 public:
|
nuclear@0
|
424 TimewarpMachine();
|
nuclear@0
|
425
|
nuclear@0
|
426 // Call this on and every time something about the setup changes.
|
nuclear@0
|
427 void Reset ( HmdRenderInfo& renderInfo, bool vsyncEnabled, double timeNow );
|
nuclear@0
|
428
|
nuclear@0
|
429 // The only reliable time in most engines is directly after the frame-present and GPU flush-and-wait.
|
nuclear@0
|
430 // This call should be done right after that to give this system the timing info it needs.
|
nuclear@0
|
431 void AfterPresentAndFlush(double timeNow);
|
nuclear@0
|
432 // But some engines queue up the frame-present and only later find out when it actually happened.
|
nuclear@0
|
433 // They should call these two at those times.
|
nuclear@0
|
434 void AfterPresentWithoutFlush();
|
nuclear@0
|
435 void AfterPresentFinishes(double timeNow);
|
nuclear@0
|
436
|
nuclear@0
|
437 // The "average" time the rendered frame will show up,
|
nuclear@0
|
438 // and the predicted pose of the HMD at that time.
|
nuclear@0
|
439 // You usually only need to call one of these functions.
|
nuclear@0
|
440 double GetViewRenderPredictionTime();
|
nuclear@0
|
441 bool GetViewRenderPredictionPose(Tracking::SensorStateReader* reader, Posef& transform);
|
nuclear@0
|
442
|
nuclear@0
|
443
|
nuclear@0
|
444 // Timewarp prediction functions. You usually only need to call one of these three sets of functions.
|
nuclear@0
|
445
|
nuclear@0
|
446 // The predicted times that the first and last pixel will be visible on-screen.
|
nuclear@0
|
447 double GetVisiblePixelTimeStart();
|
nuclear@0
|
448 double GetVisiblePixelTimeEnd();
|
nuclear@0
|
449 // Predicted poses of the HMD at those first and last pixels.
|
nuclear@0
|
450 bool GetPredictedVisiblePixelPoseStart(Tracking::SensorStateReader* reader, Posef& transform);
|
nuclear@0
|
451 bool GetPredictedVisiblePixelPoseEnd(Tracking::SensorStateReader* reader, Posef& transform);
|
nuclear@0
|
452 // The delta matrices to feed to the timewarp distortion code,
|
nuclear@0
|
453 // given the pose that was used for rendering.
|
nuclear@0
|
454 // (usually the one returned by GetViewRenderPredictionPose() earlier)
|
nuclear@0
|
455 bool GetTimewarpDeltaStart(Tracking::SensorStateReader* reader, Posef const &renderedPose, Matrix4f& transform);
|
nuclear@0
|
456 bool GetTimewarpDeltaEnd(Tracking::SensorStateReader* reader, Posef const &renderedPose, Matrix4f& transform);
|
nuclear@0
|
457
|
nuclear@0
|
458 // Just-In-Time distortion aims to delay the second sensor reading & distortion
|
nuclear@0
|
459 // until the very last moment to improve prediction. However, it is a little scary,
|
nuclear@0
|
460 // since the delay might wait too long and miss the vsync completely!
|
nuclear@0
|
461 // Use of the JustInTime_* functions is entirely optional, and we advise allowing
|
nuclear@0
|
462 // users to turn it off in their video options to cope with odd machine configurations.
|
nuclear@0
|
463
|
nuclear@0
|
464 // What time should the app wait until before starting distortion?
|
nuclear@0
|
465 double JustInTime_GetDistortionWaitUntilTime();
|
nuclear@0
|
466
|
nuclear@0
|
467 // Used to time the distortion rendering
|
nuclear@0
|
468 bool JustInTime_NeedDistortionTimeMeasurement() const;
|
nuclear@0
|
469 void JustInTime_BeforeDistortionTimeMeasurement(double timeNow);
|
nuclear@0
|
470 void JustInTime_AfterDistortionTimeMeasurement(double timeNow);
|
nuclear@0
|
471 double JustInTime_AverageDistortionTime(); // Just for profiling - use JustInTime_GetDistortionWaitUntilTime() for functionality.
|
nuclear@0
|
472
|
nuclear@0
|
473 private:
|
nuclear@0
|
474 bool VsyncEnabled;
|
nuclear@0
|
475 HmdRenderInfo RenderInfo;
|
nuclear@0
|
476 PredictionValues CurrentPredictionValues;
|
nuclear@0
|
477
|
nuclear@0
|
478 enum { NumDistortionTimes = 100 };
|
nuclear@0
|
479 int DistortionTimeCount;
|
nuclear@0
|
480 double DistortionTimeCurrentStart;
|
nuclear@0
|
481 float DistortionTimes[NumDistortionTimes];
|
nuclear@0
|
482 float DistortionTimeAverage;
|
nuclear@0
|
483
|
nuclear@0
|
484 // Pose at which last time the eye was rendered.
|
nuclear@0
|
485 Posef EyeRenderPoses[2];
|
nuclear@0
|
486
|
nuclear@0
|
487 // Absolute time of the last present+flush
|
nuclear@0
|
488 double LastFramePresentFlushTime;
|
nuclear@0
|
489 // Seconds between present+flushes
|
nuclear@0
|
490 float PresentFlushToPresentFlushSeconds;
|
nuclear@0
|
491 // Predicted absolute time of the next present+flush
|
nuclear@0
|
492 double NextFramePresentFlushTime;
|
nuclear@0
|
493
|
nuclear@0
|
494 };
|
nuclear@0
|
495
|
nuclear@0
|
496
|
nuclear@0
|
497
|
nuclear@0
|
498 }}} // OVR::Util::Render
|
nuclear@0
|
499
|
nuclear@0
|
500 #endif
|