diff options
Diffstat (limited to 'LibOVR/Src/Util/Util_Render_Stereo.h')
-rw-r--r-- | LibOVR/Src/Util/Util_Render_Stereo.h | 579 |
1 files changed, 367 insertions, 212 deletions
diff --git a/LibOVR/Src/Util/Util_Render_Stereo.h b/LibOVR/Src/Util/Util_Render_Stereo.h index 492080d..2ad9103 100644 --- a/LibOVR/Src/Util/Util_Render_Stereo.h +++ b/LibOVR/Src/Util/Util_Render_Stereo.h @@ -4,18 +4,18 @@ PublicHeader: OVR.h Filename : Util_Render_Stereo.h Content : Sample stereo rendering configuration classes. Created : October 22, 2012 -Authors : Michael Antonov +Authors : Michael Antonov, Tom Forsyth -Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. +Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. -Licensed under the Oculus VR SDK License Version 2.0 (the "License"); -you may not use the Oculus VR SDK except in compliance with the License, +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, which is provided at the time of installation or download, or which otherwise accompanies this software in either electronic or hard copy form. You may obtain a copy of the License at -http://www.oculusvr.com/licenses/LICENSE-2.0 +http://www.oculusvr.com/licenses/LICENSE-3.1 Unless required by applicable law or agreed to in writing, the Oculus VR SDK distributed under the License is distributed on an "AS IS" BASIS, @@ -28,135 +28,75 @@ limitations under the License. #ifndef OVR_Util_Render_Stereo_h #define OVR_Util_Render_Stereo_h -#include "../OVR_Device.h" +#include "../OVR_Stereo.h" -namespace OVR { namespace Util { namespace Render { +namespace OVR { -//----------------------------------------------------------------------------------- -// ***** Stereo Enumerations +class SensorFusion; -// StereoMode describes rendering modes that can be used by StereoConfig. -// These modes control whether stereo rendering is used or not (Stereo_None), -// and how it is implemented. -enum StereoMode -{ - Stereo_None = 0, - Stereo_LeftRight_Multipass = 1 -}; +namespace Util { namespace Render { -// StereoEye specifies which eye we are rendering for; it is used to -// retrieve StereoEyeParams. -enum StereoEye -{ - StereoEye_Center, - StereoEye_Left, - StereoEye_Right -}; - //----------------------------------------------------------------------------------- -// ***** Viewport - -// Viewport describes a rectangular area used for rendering, in pixels. -struct Viewport -{ - int x, y; - int w, h; - - Viewport() {} - Viewport(int x1, int y1, int w1, int h1) : x(x1), y(y1), w(w1), h(h1) { } +// **** Useful debug functions. +// +// Purely for debugging - the results are not very end-user-friendly. +char const* GetDebugNameEyeCupType ( EyeCupType eyeCupType ); +char const* GetDebugNameHmdType ( HmdTypeEnum hmdType ); - bool operator == (const Viewport& vp) const - { return (x == vp.x) && (y == vp.y) && (w == vp.w) && (h == vp.h); } - bool operator != (const Viewport& vp) const - { return !operator == (vp); } -}; //----------------------------------------------------------------------------------- -// ***** DistortionConfig - -// DistortionConfig Provides controls for the distortion shader. -// - K[0] - K[3] are coefficients for the distortion function. -// - XCenterOffset is the offset of lens distortion center from the -// center of one-eye screen half. [-1, 1] Range. -// - Scale is a factor of how much larger will the input image be, -// with a factor of 1.0f being no scaling. An inverse of this -// value is applied to sampled UV coordinates (1/Scale). -// - ChromaticAberration is an array of parameters for controlling -// additional Red and Blue scaling in order to reduce chromatic aberration -// caused by the Rift lenses. -class DistortionConfig -{ -public: - DistortionConfig(float k0 = 1.0f, float k1 = 0.0f, float k2 = 0.0f, float k3 = 0.0f) - : XCenterOffset(0), YCenterOffset(0), Scale(1.0f) - { - SetCoefficients(k0, k1, k2, k3); - SetChromaticAberration(); - } +// **** Higher-level utility functions. - void SetCoefficients(float k0, float k1 = 0.0f, float k2 = 0.0f, float k3 = 0.0f) - { K[0] = k0; K[1] = k1; K[2] = k2; K[3] = k3; } +Sizei CalculateRecommendedTextureSize ( HmdRenderInfo const &hmd, + bool bRendertargetSharedByBothEyes, + float pixelDensityInCenter = 1.0f ); - void SetChromaticAberration(float red1 = 1.0f, float red2 = 0.0f, float blue1 = 1.0f, float blue2 = 0.0f) - { ChromaticAberration[0] = red1; ChromaticAberration[1] = red2; ChromaticAberration[2] = blue1; ChromaticAberration[3] = blue2; } +FovPort CalculateRecommendedFov ( HmdRenderInfo const &hmd, + StereoEye eyeType, + bool bMakeFovSymmetrical = false); +StereoEyeParams CalculateStereoEyeParams ( HmdRenderInfo const &hmd, + StereoEye eyeType, + Sizei const &actualRendertargetSurfaceSize, + bool bRendertargetSharedByBothEyes, + bool bRightHanded = true, + float zNear = 0.01f, float zFar = 10000.0f, + Sizei const *pOverrideRenderedPixelSize = NULL, + FovPort const *pOverrideFovport = NULL, + float zoomFactor = 1.0f ); - // DistortionFn applies distortion equation to the argument. The returned - // value should match distortion equation used in shader. - float DistortionFn(float r) const - { - float rsq = r * r; - float scale = r * (K[0] + K[1] * rsq + K[2] * rsq * rsq + K[3] * rsq * rsq * rsq); - return scale; - } - - // DistortionFnInverse computes the inverse of the distortion function on an argument. - float DistortionFnInverse(float r); +Vector3f CalculateEyeVirtualCameraOffset(HmdRenderInfo const &hmd, + StereoEye eyeType, bool bMonoRenderingMode ); - float K[4]; - float XCenterOffset, YCenterOffset; - float Scale; - float ChromaticAberration[4]; // Additional per-channel scaling is applied after distortion: - // Index [0] - Red channel constant coefficient. - // Index [1] - Red channel r^2 coefficient. - // Index [2] - Blue channel constant coefficient. - // Index [3] - Blue channel r^2 coefficient. +// These are two components from StereoEyeParams that can be changed +// very easily without full recomputation of everything. +struct ViewportScaleAndOffset +{ + Recti RenderedViewport; + ScaleAndOffset2D EyeToSourceUV; }; +// Three ways to override the size of the render view dynamically. +// None of these require changing the distortion parameters or the regenerating the distortion mesh, +// and can be called every frame if desired. +ViewportScaleAndOffset ModifyRenderViewport ( StereoEyeParams const ¶ms, + Sizei const &actualRendertargetSurfaceSize, + Recti const &renderViewport ); -//----------------------------------------------------------------------------------- -// ***** StereoEyeParams +ViewportScaleAndOffset ModifyRenderSize ( StereoEyeParams const ¶ms, + Sizei const &actualRendertargetSurfaceSize, + Sizei const &requestedRenderSize, + bool bRendertargetSharedByBothEyes = false ); -// StereoEyeParams describes RenderDevice configuration needed to render -// the scene for one eye. -class StereoEyeParams -{ -public: - StereoEye Eye; - Viewport VP; // Viewport that we are rendering to - const DistortionConfig* pDistortion; - - Matrix4f ViewAdjust; // Translation to be applied to view matrix. - Matrix4f Projection; // Projection matrix used with this eye. - Matrix4f OrthoProjection; // Orthographic projection used with this eye. - - void Init(StereoEye eye, const Viewport &vp, float vofs, - const Matrix4f& proj, const Matrix4f& orthoProj, - const DistortionConfig* distortion = 0) - { - Eye = eye; - VP = vp; - ViewAdjust = Matrix4f::Translation(Vector3f(vofs,0,0)); - Projection = proj; - OrthoProjection = orthoProj; - pDistortion = distortion; - } -}; +ViewportScaleAndOffset ModifyRenderDensity ( StereoEyeParams const ¶ms, + Sizei const &actualRendertargetSurfaceSize, + float pixelDensity = 1.0f, + bool bRendertargetSharedByBothEyes = false ); //----------------------------------------------------------------------------------- @@ -169,143 +109,358 @@ public: // parameters are returned though StereoEyeParams for each eye. // // Beyond regular 3D projection, this class supports rendering a 2D orthographic -// surface for UI and text. The 2D surface will be defined as fitting within a 2D -// field of view (85 degrees by default) and used [-1,1] coordinate system with -// square pixels. The (0,0) coordinate corresponds to eye center location -// that is properly adjusted during rendering through SterepRenderParams::Adjust2D. -// Genreally speaking, text outside [-1,1] coordinate range will not be readable. +// surface for UI and text. The 2D surface will be defined by CreateOrthoSubProjection(). +// The (0,0) coordinate corresponds to eye center location. +// +// Applications are not required to use this class, but they should be doing very +// similar sequences of operations, and it may be useful to start with this class +// and modify it. + +struct StereoEyeParamsWithOrtho +{ + StereoEyeParams StereoEye; + Matrix4f OrthoProjection; +}; + +struct ViewportScaleAndOffsetBothEyes +{ + ViewportScaleAndOffset Left; + ViewportScaleAndOffset Right; +}; class StereoConfig { public: - StereoConfig(StereoMode mode = Stereo_LeftRight_Multipass, - const Viewport& fullViewport = Viewport(0,0, 1280,800)); + // StereoMode describes rendering modes that can be used by StereoConfig. + // These modes control whether stereo rendering is used or not (Stereo_None), + // and how it is implemented. + enum StereoMode + { + Stereo_None = 0, // Single eye + Stereo_LeftRight_Multipass = 1, // One frustum per eye + }; + + + StereoConfig(StereoMode mode = Stereo_LeftRight_Multipass); + //--------------------------------------------------------------------------------------------- + // *** Core functions - every app MUST call these functions at least once. + + // Sets HMD parameters; also initializes distortion coefficients. + void SetHmdRenderInfo(const HmdRenderInfo& hmd); + + // Set the physical size of the rendertarget surface the app created, + // and whether one RT is shared by both eyes, or each eye has its own RT: + // true: both eyes are rendered to the same RT. Left eye starts at top-left, right eye starts at top-middle. + // false: each eye is rendered to its own RT. Some GPU architectures prefer this arrangement. + // Typically, the app would call CalculateRecommendedTextureSize() to suggest the choice of RT size. + // This setting must be exactly the size of the actual RT created, or the UVs produced will be incorrect. + // If the app wants to render to a subsection of the RT, it should use SetRenderSize() + void SetRendertargetSize (Size<int> const rendertargetSize, + bool rendertargetIsSharedByBothEyes ); + + // Returns full set of Stereo rendering parameters for the specified eye. + const StereoEyeParamsWithOrtho& GetEyeRenderParams(StereoEye eye); + + + + //--------------------------------------------------------------------------------------------- + // *** Optional functions - an app may call these to override default behaviours. + + const HmdRenderInfo& GetHmdRenderInfo() const { return Hmd; } - // *** Modifiable State Access + // Returns the recommended size of rendertargets. + // If rendertargetIsSharedByBothEyes is true, this is the size of the combined buffer. + // If rendertargetIsSharedByBothEyes is false, this is the size of each individual buffer. + // pixelDensityInCenter may be set to any number - by default it will match the HMD resolution in the center of the image. + // After creating the rendertargets, the application MUST call SetRendertargetSize() with the actual size created + // (which can be larger or smaller as the app wishes, but StereoConfig needs to know either way) + Sizei CalculateRecommendedTextureSize ( bool rendertargetSharedByBothEyes, + float pixelDensityInCenter = 1.0f ); // Sets a stereo rendering mode and updates internal cached // state (matrices, per-eye view) based on it. void SetStereoMode(StereoMode mode) { Mode = mode; DirtyFlag = true; } StereoMode GetStereoMode() const { return Mode; } - // Sets HMD parameters; also initializes distortion coefficients. - void SetHMDInfo(const HMDInfo& hmd); - const HMDInfo& GetHMDInfo() const { return HMD; } + // Sets the fieldOfView that the 2D coordinate area stretches to. + void Set2DAreaFov(float fovRadians); - // Query physical eye-to-screen distance in meters, which combines screen-to-lens and - // and lens-to-eye pupil distances. Modifying this value adjusts FOV. - float GetEyeToScreenDistance() const { return HMD.EyeToScreenDistance; } - void SetEyeToScreenDistance(float esd) { HMD.EyeToScreenDistance = esd; DirtyFlag = true; } + // Really only for science experiments - no normal app should ever need to override + // the HMD's lens descriptors. Passing NULL removes the override. + // Supply both = set left and right. + // Supply just left = set both to the same. + // Supply neither = remove override. + void SetLensOverride ( LensConfig const *pLensOverrideLeft = NULL, + LensConfig const *pLensOverrideRight = NULL ); + + // Override the rendered FOV in various ways. All angles in tangent units. + // This is not clamped to the physical FOV of the display - you'll need to do that yourself! + // Supply both = set left and right. + // Supply just left = set both to the same. + // Supply neither = remove override. + void SetFov ( FovPort const *pfovLeft = NULL, + FovPort const *pfovRight = NULL ); + + void SetFovPortRadians ( float horizontal, float vertical ) + { + FovPort fov = FovPort::CreateFromRadians(horizontal, vertical); + SetFov( &fov, &fov ); + } - // Interpupillary distance used for stereo, in meters. Default is 0.064m (64 mm). - void SetIPD(float ipd) { InterpupillaryDistance = ipd; IPDOverride = DirtyFlag = true; } - float GetIPD() const { return InterpupillaryDistance; } - // Set full render target viewport; for HMD this includes both eyes. - void SetFullViewport(const Viewport& vp); - const Viewport& GetFullViewport() const { return FullView; } + // This forces a "zero IPD" mode where there is just a single render with an FOV that + // is the union of the two calculated FOVs. + // The calculated render is for the left eye. Any size & FOV overrides for the right + // eye will be ignored. + // If you query the right eye's size, you will get the same render + // size & position as the left eye - you should not actually do the render of course! + // The distortion values will be different, because it goes to a different place on the framebuffer. + // Note that if you do this, the rendertarget does not need to be twice the width of + // the render size any more. + void SetZeroVirtualIpdOverride ( bool enableOverride ); - // Aspect ratio defaults to ((w/h)*multiplier) computed per eye. - // Aspect multiplier allows adjusting aspect ratio consistently for Stereo/NoStereo. - void SetAspectMultiplier(float m) { AspectMultiplier = m; DirtyFlag = true; } - float GetAspectMultiplier() const { return AspectMultiplier; } + // Allows the app to specify near and far clip planes and the right/left-handedness of the projection matrix. + void SetZClipPlanesAndHandedness ( float zNear = 0.01f, float zFar = 10000.0f, + bool rightHandedProjection = true ); - - // For the distorted image to fill rendered viewport, input texture render target needs to be - // scaled by DistortionScale before sampling. The scale factor is computed by fitting a point - // on of specified radius from a distortion center, more easily specified as a coordinate. - // SetDistortionFitPointVP sets the (x,y) coordinate of the point that scale will be "fit" to, - // assuming [-1,1] coordinate range for full left-eye viewport. A fit point is a location - // where source (pre-distortion) and target (post-distortion) image match each other. - // For the right eye, the interpretation of 'u' will be inverted. - void SetDistortionFitPointVP(float x, float y); - // SetDistortionFitPointPixels sets the (x,y) coordinate of the point that scale will be "fit" to, - // specified in pixeld for full left-eye texture. - void SetDistortionFitPointPixels(float x, float y); - - // Changes all distortion settings. - // Note that setting HMDInfo also changes Distortion coefficients. - void SetDistortionConfig(const DistortionConfig& d) { Distortion = d; DirtyFlag = true; } - - // Modify distortion coefficients; useful for adjustment tweaking. - void SetDistortionK(int i, float k) { Distortion.K[i] = k; DirtyFlag = true; } - float GetDistortionK(int i) const { return Distortion.K[i]; } + // Allows the app to specify how much extra eye rotation to allow when determining the visible FOV. + void SetExtraEyeRotation ( float extraEyeRotationInRadians = 0.0f ); - // Sets the fieldOfView that the 2D coordinate area stretches to. - void Set2DAreaFov(float fovRadians); + // The dirty flag is set by any of the above calls. Just handy for the app to know + // if e.g. the distortion mesh needs regeneration. + void SetDirty() { DirtyFlag = true; } + bool IsDirty() { return DirtyFlag; } + + // An app never needs to call this - GetEyeRenderParams will call it internally if + // the state is dirty. However apps can call this explicitly to control when and where + // computation is performed (e.g. not inside critical loops) + void UpdateComputedState(); + + // This returns the projection matrix with a "zoom". Does not modify any internal state. + Matrix4f GetProjectionWithZoom ( StereoEye eye, float fovZoom ) const; + //--------------------------------------------------------------------------------------------- + // The SetRender* functions are special. + // + // They do not require a full recalculation of state, and they do not change anything but the + // ViewportScaleAndOffset data for the eyes (which they return), and do not set the dirty flag! + // This means they can be called without regenerating the distortion mesh, and thus + // can happily be called every frame without causing performance problems. Dynamic rescaling + // of the rendertarget can help keep framerate up in demanding VR applications. + // See the documentation for more details on their use. + + // Specify a pixel density - how many rendered pixels per pixel in the physical display. + ViewportScaleAndOffsetBothEyes SetRenderDensity ( float pixelsPerDisplayPixel ); + + // Supply the size directly. Will be clamped to the physical rendertarget size. + ViewportScaleAndOffsetBothEyes SetRenderSize ( Sizei const &renderSizeLeft, Sizei const &renderSizeRight ); + + // Supply the viewport directly. This is not clamped to the physical rendertarget - careful now! + ViewportScaleAndOffsetBothEyes SetRenderViewport ( Recti const &renderViewportLeft, Recti const &renderViewportRight ); + +private: + + // *** Modifiable State + + StereoMode Mode; + HmdRenderInfo Hmd; + + float Area2DFov; // FOV range mapping to the 2D area. + + // Only one of these three overrides can be true! + enum SetViewportModeEnum + { + SVPM_Density, + SVPM_Size, + SVPM_Viewport, + } SetViewportMode; + // ...and depending which it is, one of the following are used. + float SetViewportPixelsPerDisplayPixel; + Sizei SetViewportSize[2]; + Recti SetViewport[2]; + + // Other overrides. + bool OverrideLens; + LensConfig LensOverrideLeft; + LensConfig LensOverrideRight; + Sizei RendertargetSize; + bool OverrideTanHalfFov; + FovPort FovOverrideLeft; + FovPort FovOverrideRight; + bool OverrideZeroIpd; + float ZNear; + float ZFar; + float ExtraEyeRotationInRadians; + bool IsRendertargetSharedByBothEyes; + bool RightHandedProjection; + + bool DirtyFlag; // Set when any if the modifiable state changed. Does NOT get set by SetRender*() + + // Utility function. + ViewportScaleAndOffsetBothEyes setupViewportScaleAndOffsets(); + // *** Computed State - // Return current aspect ratio. - float GetAspect() { updateIfDirty(); return Aspect; } - - // Return computed vertical FOV in radians/degrees. - float GetYFOVRadians() { updateIfDirty(); return YFov; } - float GetYFOVDegrees() { return RadToDegree(GetYFOVRadians()); } +public: // Small hack for the config tool. Normal code should never read EyeRenderParams directly - use GetEyeRenderParams() instead. + // 0/1 = left/right main views. + StereoEyeParamsWithOrtho EyeRenderParams[2]; +}; - // Query horizontal projection center offset as a distance away from the - // one-eye [-1,1] unit viewport. - // Positive return value should be used for left eye, negative for right eye. - float GetProjectionCenterOffset() { updateIfDirty(); return ProjectionCenterOffset; } - // GetDistortionConfig isn't const because XCenterOffset bay need to be recomputed. - const DistortionConfig& GetDistortionConfig() { updateIfDirty(); return Distortion; } +//----------------------------------------------------------------------------------- +// ***** Distortion Mesh Rendering +// - // Returns DistortionScale factor by which input texture size is increased to make - // post-distortion result distortion fit the viewport. - float GetDistortionScale() { updateIfDirty(); return Distortion.Scale; } +// Stores both texture UV coords, or tan(angle) values. +// Use whichever set of data the specific distortion algorithm requires. +// This struct *must* be binary compatible with CAPI ovrDistortionVertex. +struct DistortionMeshVertexData +{ + // [-1,+1],[-1,+1] over the entire framebuffer. + Vector2f ScreenPosNDC; + // [0.0-1.0] interpolation value for timewarping - see documentation for details. + float TimewarpLerp; + // [0.0-1.0] fade-to-black at the edges to reduce peripheral vision noise. + float Shade; + // The red, green, and blue vectors in tan(angle) space. + // Scale and offset by the values in StereoEyeParams.EyeToSourceUV.Scale + // and StereoParams.EyeToSourceUV.Offset to get to real texture UV coords. + Vector2f TanEyeAnglesR; + Vector2f TanEyeAnglesG; + Vector2f TanEyeAnglesB; +}; - // Returns the size of a pixel within 2D coordinate system. - float Get2DUnitPixel() { updateIfDirty(); return (2.0f / (FovPixels * Distortion.Scale)); } - // Returns full set of Stereo rendering parameters for the specified eye. - const StereoEyeParams& GetEyeRenderParams(StereoEye eye); +void DistortionMeshCreate ( DistortionMeshVertexData **ppVertices, UInt16 **ppTriangleListIndices, + int *pNumVertices, int *pNumTriangles, + const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo ); + +// Generate distortion mesh for a eye. This version requires less data then stereoParms, supporting +// dynamic change in render target viewport. +void DistortionMeshCreate( DistortionMeshVertexData **ppVertices, UInt16 **ppTriangleListIndices, + int *pNumVertices, int *pNumTriangles, + bool rightEye, + const HmdRenderInfo &hmdRenderInfo, + const DistortionRenderDesc &distortion, const ScaleAndOffset2D &eyeToSourceNDC ); + +void DistortionMeshDestroy ( DistortionMeshVertexData *pVertices, UInt16 *pTriangleMeshIndices ); + + + + +//----------------------------------------------------------------------------------- +// ***** Prediction and timewarp. +// + +struct PredictionValues +{ + // All values in seconds. + // These are the times in seconds from a present+flush to the relevant display element. + // The time is measured to the middle of that element's visibility window, + // e.g. if the device is a full-persistence display, the element will be visible for + // an entire frame, so the time measures to the middle of that period, i.e. half the frame time. + float PresentFlushToRenderedScene; // To the overall rendered 3D scene being visible. + float PresentFlushToTimewarpStart; // To when the first timewarped scanline will be visible. + float PresentFlushToTimewarpEnd; // To when the last timewarped scanline will be visible. + float PresentFlushToPresentFlush; // To the next present+flush, i.e. the ideal framerate. + + bool WithTimewarp; + bool WithVsync; +}; + +// Calculates the values from the HMD info. +PredictionValues PredictionGetDeviceValues ( const HmdRenderInfo &hmdRenderInfo, + bool withTimewarp = true, + bool withVsync = true ); + +// Pass in an orientation used to render the scene, and then the predicted orientation +// (which may have been computed later on, and thus is more accurate), and this +// will return the matrix to pass to the timewarp distortion shader. +// TODO: deal with different handedness? +Matrix4f TimewarpComputePoseDelta ( Matrix4f const &renderedViewFromWorld, Matrix4f const &predictedViewFromWorld ); + + + +// TimewarpMachine helps keep track of rendered frame timing and +// handles predictions for time-warp rendering. +class TimewarpMachine +{ +public: + TimewarpMachine(); -private: + // Call this on and every time something about the setup changes. + void Reset ( HmdRenderInfo& renderInfo, bool vsyncEnabled, double timeNow ); - void updateIfDirty() { if (DirtyFlag) updateComputedState(); } - void updateComputedState(); + // The only reliable time in most engines is directly after the frame-present and GPU flush-and-wait. + // This call should be done right after that to give this system the timing info it needs. + void AfterPresentAndFlush(double timeNow); - void updateDistortionOffsetAndScale(); - void updateProjectionOffset(); - void update2D(); - void updateEyeParams(); + // The "average" time the rendered frame will show up, + // and the predicted pose of the HMD at that time. + // You usually only need to call one of these functions. + double GetViewRenderPredictionTime(); + Posef GetViewRenderPredictionPose(SensorFusion &sfusion); - // *** Modifiable State + // Timewarp prediction functions. You usually only need to call one of these three sets of functions. + + // The predicted times that the first and last pixel will be visible on-screen. + double GetVisiblePixelTimeStart(); + double GetVisiblePixelTimeEnd(); + // Predicted poses of the HMD at those first and last pixels. + Posef GetPredictedVisiblePixelPoseStart(SensorFusion &sfusion); + Posef GetPredictedVisiblePixelPoseEnd (SensorFusion &sfusion); + // The delta matrices to feed to the timewarp distortion code, + // given the pose that was used for rendering. + // (usually the one returned by GetViewRenderPredictionPose() earlier) + Matrix4f GetTimewarpDeltaStart(SensorFusion &sfusion, Posef const &renderedPose); + Matrix4f GetTimewarpDeltaEnd (SensorFusion &sfusion, Posef const &renderedPose); + + + // Just-In-Time distortion aims to delay the second sensor reading & distortion + // until the very last moment to improve prediction. However, it is a little scary, + // since the delay might wait too long and miss the vsync completely! + // Use of the JustInTime_* functions is entirely optional, and we advise allowing + // users to turn it off in their video options to cope with odd machine configurations. + + // What time should the app wait until before starting distortion? + double JustInTime_GetDistortionWaitUntilTime(); + + // Used to time the distortion rendering + bool JustInTime_NeedDistortionTimeMeasurement() const; + void JustInTime_BeforeDistortionTimeMeasurement(double timeNow); + void JustInTime_AfterDistortionTimeMeasurement(double timeNow); + + +private: + + bool VsyncEnabled; + HmdRenderInfo RenderInfo; + PredictionValues CurrentPredictionValues; + + enum { NumDistortionTimes = 10 }; + int DistortionTimeCount; + double DistortionTimeCurrentStart; + float DistortionTimes[NumDistortionTimes]; + float DistortionTimeAverage; + + // Pose at which last time the eye was rendered. + Posef EyeRenderPoses[2]; + + // Absolute time of the last present+flush + double LastFramePresentFlushTime; + // Seconds between presentflushes + float PresentFlushToPresentFlushSeconds; + // Predicted absolute time of the next present+flush + double NextFramePresentFlushTime; - StereoMode Mode; - float InterpupillaryDistance; - float AspectMultiplier; // Multiplied into aspect ratio to change it. - HMDInfo HMD; - DistortionConfig Distortion; - float DistortionFitX, DistortionFitY; // In [-1,1] half-screen viewport units. - Viewport FullView; // Entire window viewport. - - float Area2DFov; // FOV range mapping to [-1, 1] 2D area. - - // *** Computed State - - bool DirtyFlag; // Set when any if the modifiable state changed. - bool IPDOverride; // True after SetIPD was called. - float YFov; // Vertical FOV. - float Aspect; // Aspect ratio: (w/h)*AspectMultiplier. - float ProjectionCenterOffset; - StereoEyeParams EyeRenderParams[2]; - - - // ** 2D Rendering - - // Number of 2D pixels in the FOV. This defines [-1,1] coordinate range for 2D. - float FovPixels; - Matrix4f OrthoCenter; - float OrthoPixelOffset; }; + }}} // OVR::Util::Render #endif |