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