aboutsummaryrefslogtreecommitdiffstats
path: root/LibOVR/Src/Util/Util_Render_Stereo.h
diff options
context:
space:
mode:
Diffstat (limited to 'LibOVR/Src/Util/Util_Render_Stereo.h')
-rw-r--r--LibOVR/Src/Util/Util_Render_Stereo.h299
1 files changed, 299 insertions, 0 deletions
diff --git a/LibOVR/Src/Util/Util_Render_Stereo.h b/LibOVR/Src/Util/Util_Render_Stereo.h
new file mode 100644
index 0000000..9dc110c
--- /dev/null
+++ b/LibOVR/Src/Util/Util_Render_Stereo.h
@@ -0,0 +1,299 @@
+/************************************************************************************
+
+PublicHeader: OVR.h
+Filename : Util_Render_Stereo.h
+Content : Sample stereo rendering configuration classes.
+Created : October 22, 2012
+Authors : Michael Antonov
+
+Copyright : Copyright 2012 Oculus, Inc. All Rights reserved.
+
+Use of this software is subject to the terms of the Oculus Inc license
+agreement provided at the time of installation or download, or which
+otherwise accompanies this software in either electronic or hard copy form.
+
+*************************************************************************************/
+
+#ifndef OVR_Util_Render_Stereo_h
+#define OVR_Util_Render_Stereo_h
+
+#include "../OVR_Device.h"
+
+namespace OVR { namespace Util { namespace Render {
+
+
+//-----------------------------------------------------------------------------------
+// ***** Stereo Enumerations
+
+// 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
+};
+
+
+// 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) { }
+
+ 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();
+ }
+
+ 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; }
+
+ 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; }
+
+
+ // 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);
+
+ 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.
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** StereoEyeParams
+
+// 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;
+ }
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** StereoConfig
+
+// StereoConfig maintains a scene stereo state and allow switching between different
+// stereo rendering modes. To support rendering, StereoConfig keeps track of HMD
+// variables such as screen size, eye-to-screen distance and distortion, and computes
+// extra data such as FOV and distortion center offsets based on it. Rendering
+// 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.
+
+class StereoConfig
+{
+public:
+
+ StereoConfig(StereoMode mode = Stereo_LeftRight_Multipass,
+ const Viewport& fullViewport = Viewport(0,0, 1280,800));
+
+
+ // *** Modifiable State Access
+
+ // 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; }
+
+ // 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; }
+
+ // Interpupillary distance used for stereo, in meters. Default is 0.064m (64 mm).
+ void SetIPD(float ipd) { InterpupillaryDistance = ipd; 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; }
+
+ // 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; }
+
+
+ // 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]; }
+
+ // Sets the fieldOfView that the 2D coordinate area stretches to.
+ void Set2DAreaFov(float fovRadians);
+
+
+ // *** 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()); }
+
+ // 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; }
+
+ // 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; }
+
+ // 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);
+
+private:
+
+ void updateIfDirty() { if (DirtyFlag) updateComputedState(); }
+ void updateComputedState();
+
+ void updateDistortionOffsetAndScale();
+ void updateProjectionOffset();
+ void update2D();
+ void updateEyeParams();
+
+
+ // *** Modifiable State
+
+ 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.
+ 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