oculus1

annotate libovr/Src/Util/Util_Render_Stereo.h @ 1:e2f9e4603129

added LibOVR and started a simple vr wrapper.
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 14 Sep 2013 16:14:59 +0300
parents
children b069a5c27388
rev   line source
nuclear@1 1 /************************************************************************************
nuclear@1 2
nuclear@1 3 PublicHeader: OVR.h
nuclear@1 4 Filename : Util_Render_Stereo.h
nuclear@1 5 Content : Sample stereo rendering configuration classes.
nuclear@1 6 Created : October 22, 2012
nuclear@1 7 Authors : Michael Antonov
nuclear@1 8
nuclear@1 9 Copyright : Copyright 2012 Oculus, Inc. All Rights reserved.
nuclear@1 10
nuclear@1 11 Use of this software is subject to the terms of the Oculus Inc license
nuclear@1 12 agreement provided at the time of installation or download, or which
nuclear@1 13 otherwise accompanies this software in either electronic or hard copy form.
nuclear@1 14
nuclear@1 15 *************************************************************************************/
nuclear@1 16
nuclear@1 17 #ifndef OVR_Util_Render_Stereo_h
nuclear@1 18 #define OVR_Util_Render_Stereo_h
nuclear@1 19
nuclear@1 20 #include "../OVR_Device.h"
nuclear@1 21
nuclear@1 22 namespace OVR { namespace Util { namespace Render {
nuclear@1 23
nuclear@1 24
nuclear@1 25 //-----------------------------------------------------------------------------------
nuclear@1 26 // ***** Stereo Enumerations
nuclear@1 27
nuclear@1 28 // StereoMode describes rendering modes that can be used by StereoConfig.
nuclear@1 29 // These modes control whether stereo rendering is used or not (Stereo_None),
nuclear@1 30 // and how it is implemented.
nuclear@1 31 enum StereoMode
nuclear@1 32 {
nuclear@1 33 Stereo_None = 0,
nuclear@1 34 Stereo_LeftRight_Multipass = 1
nuclear@1 35 };
nuclear@1 36
nuclear@1 37
nuclear@1 38 // StereoEye specifies which eye we are rendering for; it is used to
nuclear@1 39 // retrieve StereoEyeParams.
nuclear@1 40 enum StereoEye
nuclear@1 41 {
nuclear@1 42 StereoEye_Center,
nuclear@1 43 StereoEye_Left,
nuclear@1 44 StereoEye_Right
nuclear@1 45 };
nuclear@1 46
nuclear@1 47
nuclear@1 48 //-----------------------------------------------------------------------------------
nuclear@1 49 // ***** Viewport
nuclear@1 50
nuclear@1 51 // Viewport describes a rectangular area used for rendering, in pixels.
nuclear@1 52 struct Viewport
nuclear@1 53 {
nuclear@1 54 int x, y;
nuclear@1 55 int w, h;
nuclear@1 56
nuclear@1 57 Viewport() {}
nuclear@1 58 Viewport(int x1, int y1, int w1, int h1) : x(x1), y(y1), w(w1), h(h1) { }
nuclear@1 59
nuclear@1 60 bool operator == (const Viewport& vp) const
nuclear@1 61 { return (x == vp.x) && (y == vp.y) && (w == vp.w) && (h == vp.h); }
nuclear@1 62 bool operator != (const Viewport& vp) const
nuclear@1 63 { return !operator == (vp); }
nuclear@1 64 };
nuclear@1 65
nuclear@1 66
nuclear@1 67 //-----------------------------------------------------------------------------------
nuclear@1 68 // ***** DistortionConfig
nuclear@1 69
nuclear@1 70 // DistortionConfig Provides controls for the distortion shader.
nuclear@1 71 // - K[0] - K[3] are coefficients for the distortion function.
nuclear@1 72 // - XCenterOffset is the offset of lens distortion center from the
nuclear@1 73 // center of one-eye screen half. [-1, 1] Range.
nuclear@1 74 // - Scale is a factor of how much larger will the input image be,
nuclear@1 75 // with a factor of 1.0f being no scaling. An inverse of this
nuclear@1 76 // value is applied to sampled UV coordinates (1/Scale).
nuclear@1 77 // - ChromaticAberration is an array of parameters for controlling
nuclear@1 78 // additional Red and Blue scaling in order to reduce chromatic aberration
nuclear@1 79 // caused by the Rift lenses.
nuclear@1 80 class DistortionConfig
nuclear@1 81 {
nuclear@1 82 public:
nuclear@1 83 DistortionConfig(float k0 = 1.0f, float k1 = 0.0f, float k2 = 0.0f, float k3 = 0.0f)
nuclear@1 84 : XCenterOffset(0), YCenterOffset(0), Scale(1.0f)
nuclear@1 85 {
nuclear@1 86 SetCoefficients(k0, k1, k2, k3);
nuclear@1 87 SetChromaticAberration();
nuclear@1 88 }
nuclear@1 89
nuclear@1 90 void SetCoefficients(float k0, float k1 = 0.0f, float k2 = 0.0f, float k3 = 0.0f)
nuclear@1 91 { K[0] = k0; K[1] = k1; K[2] = k2; K[3] = k3; }
nuclear@1 92
nuclear@1 93 void SetChromaticAberration(float red1 = 1.0f, float red2 = 0.0f, float blue1 = 1.0f, float blue2 = 0.0f)
nuclear@1 94 { ChromaticAberration[0] = red1; ChromaticAberration[1] = red2; ChromaticAberration[2] = blue1; ChromaticAberration[3] = blue2; }
nuclear@1 95
nuclear@1 96
nuclear@1 97 // DistortionFn applies distortion equation to the argument. The returned
nuclear@1 98 // value should match distortion equation used in shader.
nuclear@1 99 float DistortionFn(float r) const
nuclear@1 100 {
nuclear@1 101 float rsq = r * r;
nuclear@1 102 float scale = r * (K[0] + K[1] * rsq + K[2] * rsq * rsq + K[3] * rsq * rsq * rsq);
nuclear@1 103 return scale;
nuclear@1 104 }
nuclear@1 105
nuclear@1 106 // DistortionFnInverse computes the inverse of the distortion function on an argument.
nuclear@1 107 float DistortionFnInverse(float r);
nuclear@1 108
nuclear@1 109 float K[4];
nuclear@1 110 float XCenterOffset, YCenterOffset;
nuclear@1 111 float Scale;
nuclear@1 112
nuclear@1 113 float ChromaticAberration[4]; // Additional per-channel scaling is applied after distortion:
nuclear@1 114 // Index [0] - Red channel constant coefficient.
nuclear@1 115 // Index [1] - Red channel r^2 coefficient.
nuclear@1 116 // Index [2] - Blue channel constant coefficient.
nuclear@1 117 // Index [3] - Blue channel r^2 coefficient.
nuclear@1 118 };
nuclear@1 119
nuclear@1 120
nuclear@1 121 //-----------------------------------------------------------------------------------
nuclear@1 122 // ***** StereoEyeParams
nuclear@1 123
nuclear@1 124 // StereoEyeParams describes RenderDevice configuration needed to render
nuclear@1 125 // the scene for one eye.
nuclear@1 126 class StereoEyeParams
nuclear@1 127 {
nuclear@1 128 public:
nuclear@1 129 StereoEye Eye;
nuclear@1 130 Viewport VP; // Viewport that we are rendering to
nuclear@1 131 const DistortionConfig* pDistortion;
nuclear@1 132
nuclear@1 133 Matrix4f ViewAdjust; // Translation to be applied to view matrix.
nuclear@1 134 Matrix4f Projection; // Projection matrix used with this eye.
nuclear@1 135 Matrix4f OrthoProjection; // Orthographic projection used with this eye.
nuclear@1 136
nuclear@1 137 void Init(StereoEye eye, const Viewport &vp, float vofs,
nuclear@1 138 const Matrix4f& proj, const Matrix4f& orthoProj,
nuclear@1 139 const DistortionConfig* distortion = 0)
nuclear@1 140 {
nuclear@1 141 Eye = eye;
nuclear@1 142 VP = vp;
nuclear@1 143 ViewAdjust = Matrix4f::Translation(Vector3f(vofs,0,0));
nuclear@1 144 Projection = proj;
nuclear@1 145 OrthoProjection = orthoProj;
nuclear@1 146 pDistortion = distortion;
nuclear@1 147 }
nuclear@1 148 };
nuclear@1 149
nuclear@1 150
nuclear@1 151 //-----------------------------------------------------------------------------------
nuclear@1 152 // ***** StereoConfig
nuclear@1 153
nuclear@1 154 // StereoConfig maintains a scene stereo state and allow switching between different
nuclear@1 155 // stereo rendering modes. To support rendering, StereoConfig keeps track of HMD
nuclear@1 156 // variables such as screen size, eye-to-screen distance and distortion, and computes
nuclear@1 157 // extra data such as FOV and distortion center offsets based on it. Rendering
nuclear@1 158 // parameters are returned though StereoEyeParams for each eye.
nuclear@1 159 //
nuclear@1 160 // Beyond regular 3D projection, this class supports rendering a 2D orthographic
nuclear@1 161 // surface for UI and text. The 2D surface will be defined as fitting within a 2D
nuclear@1 162 // field of view (85 degrees by default) and used [-1,1] coordinate system with
nuclear@1 163 // square pixels. The (0,0) coordinate corresponds to eye center location
nuclear@1 164 // that is properly adjusted during rendering through SterepRenderParams::Adjust2D.
nuclear@1 165 // Genreally speaking, text outside [-1,1] coordinate range will not be readable.
nuclear@1 166
nuclear@1 167 class StereoConfig
nuclear@1 168 {
nuclear@1 169 public:
nuclear@1 170
nuclear@1 171 StereoConfig(StereoMode mode = Stereo_LeftRight_Multipass,
nuclear@1 172 const Viewport& fullViewport = Viewport(0,0, 1280,800));
nuclear@1 173
nuclear@1 174
nuclear@1 175 // *** Modifiable State Access
nuclear@1 176
nuclear@1 177 // Sets a stereo rendering mode and updates internal cached
nuclear@1 178 // state (matrices, per-eye view) based on it.
nuclear@1 179 void SetStereoMode(StereoMode mode) { Mode = mode; DirtyFlag = true; }
nuclear@1 180 StereoMode GetStereoMode() const { return Mode; }
nuclear@1 181
nuclear@1 182 // Sets HMD parameters; also initializes distortion coefficients.
nuclear@1 183 void SetHMDInfo(const HMDInfo& hmd);
nuclear@1 184 const HMDInfo& GetHMDInfo() const { return HMD; }
nuclear@1 185
nuclear@1 186 // Query physical eye-to-screen distance in meters, which combines screen-to-lens and
nuclear@1 187 // and lens-to-eye pupil distances. Modifying this value adjusts FOV.
nuclear@1 188 float GetEyeToScreenDistance() const { return HMD.EyeToScreenDistance; }
nuclear@1 189 void SetEyeToScreenDistance(float esd) { HMD.EyeToScreenDistance = esd; DirtyFlag = true; }
nuclear@1 190
nuclear@1 191 // Interpupillary distance used for stereo, in meters. Default is 0.064m (64 mm).
nuclear@1 192 void SetIPD(float ipd) { InterpupillaryDistance = ipd; IPDOverride = DirtyFlag = true; }
nuclear@1 193 float GetIPD() const { return InterpupillaryDistance; }
nuclear@1 194
nuclear@1 195 // Set full render target viewport; for HMD this includes both eyes.
nuclear@1 196 void SetFullViewport(const Viewport& vp);
nuclear@1 197 const Viewport& GetFullViewport() const { return FullView; }
nuclear@1 198
nuclear@1 199 // Aspect ratio defaults to ((w/h)*multiplier) computed per eye.
nuclear@1 200 // Aspect multiplier allows adjusting aspect ratio consistently for Stereo/NoStereo.
nuclear@1 201 void SetAspectMultiplier(float m) { AspectMultiplier = m; DirtyFlag = true; }
nuclear@1 202 float GetAspectMultiplier() const { return AspectMultiplier; }
nuclear@1 203
nuclear@1 204
nuclear@1 205 // For the distorted image to fill rendered viewport, input texture render target needs to be
nuclear@1 206 // scaled by DistortionScale before sampling. The scale factor is computed by fitting a point
nuclear@1 207 // on of specified radius from a distortion center, more easily specified as a coordinate.
nuclear@1 208 // SetDistortionFitPointVP sets the (x,y) coordinate of the point that scale will be "fit" to,
nuclear@1 209 // assuming [-1,1] coordinate range for full left-eye viewport. A fit point is a location
nuclear@1 210 // where source (pre-distortion) and target (post-distortion) image match each other.
nuclear@1 211 // For the right eye, the interpretation of 'u' will be inverted.
nuclear@1 212 void SetDistortionFitPointVP(float x, float y);
nuclear@1 213 // SetDistortionFitPointPixels sets the (x,y) coordinate of the point that scale will be "fit" to,
nuclear@1 214 // specified in pixeld for full left-eye texture.
nuclear@1 215 void SetDistortionFitPointPixels(float x, float y);
nuclear@1 216
nuclear@1 217 // Changes all distortion settings.
nuclear@1 218 // Note that setting HMDInfo also changes Distortion coefficients.
nuclear@1 219 void SetDistortionConfig(const DistortionConfig& d) { Distortion = d; DirtyFlag = true; }
nuclear@1 220
nuclear@1 221 // Modify distortion coefficients; useful for adjustment tweaking.
nuclear@1 222 void SetDistortionK(int i, float k) { Distortion.K[i] = k; DirtyFlag = true; }
nuclear@1 223 float GetDistortionK(int i) const { return Distortion.K[i]; }
nuclear@1 224
nuclear@1 225 // Sets the fieldOfView that the 2D coordinate area stretches to.
nuclear@1 226 void Set2DAreaFov(float fovRadians);
nuclear@1 227
nuclear@1 228
nuclear@1 229 // *** Computed State
nuclear@1 230
nuclear@1 231 // Return current aspect ratio.
nuclear@1 232 float GetAspect() { updateIfDirty(); return Aspect; }
nuclear@1 233
nuclear@1 234 // Return computed vertical FOV in radians/degrees.
nuclear@1 235 float GetYFOVRadians() { updateIfDirty(); return YFov; }
nuclear@1 236 float GetYFOVDegrees() { return RadToDegree(GetYFOVRadians()); }
nuclear@1 237
nuclear@1 238 // Query horizontal projection center offset as a distance away from the
nuclear@1 239 // one-eye [-1,1] unit viewport.
nuclear@1 240 // Positive return value should be used for left eye, negative for right eye.
nuclear@1 241 float GetProjectionCenterOffset() { updateIfDirty(); return ProjectionCenterOffset; }
nuclear@1 242
nuclear@1 243 // GetDistortionConfig isn't const because XCenterOffset bay need to be recomputed.
nuclear@1 244 const DistortionConfig& GetDistortionConfig() { updateIfDirty(); return Distortion; }
nuclear@1 245
nuclear@1 246 // Returns DistortionScale factor by which input texture size is increased to make
nuclear@1 247 // post-distortion result distortion fit the viewport.
nuclear@1 248 float GetDistortionScale() { updateIfDirty(); return Distortion.Scale; }
nuclear@1 249
nuclear@1 250 // Returns the size of a pixel within 2D coordinate system.
nuclear@1 251 float Get2DUnitPixel() { updateIfDirty(); return (2.0f / (FovPixels * Distortion.Scale)); }
nuclear@1 252
nuclear@1 253 // Returns full set of Stereo rendering parameters for the specified eye.
nuclear@1 254 const StereoEyeParams& GetEyeRenderParams(StereoEye eye);
nuclear@1 255
nuclear@1 256 private:
nuclear@1 257
nuclear@1 258 void updateIfDirty() { if (DirtyFlag) updateComputedState(); }
nuclear@1 259 void updateComputedState();
nuclear@1 260
nuclear@1 261 void updateDistortionOffsetAndScale();
nuclear@1 262 void updateProjectionOffset();
nuclear@1 263 void update2D();
nuclear@1 264 void updateEyeParams();
nuclear@1 265
nuclear@1 266
nuclear@1 267 // *** Modifiable State
nuclear@1 268
nuclear@1 269 StereoMode Mode;
nuclear@1 270 float InterpupillaryDistance;
nuclear@1 271 float AspectMultiplier; // Multiplied into aspect ratio to change it.
nuclear@1 272 HMDInfo HMD;
nuclear@1 273 DistortionConfig Distortion;
nuclear@1 274 float DistortionFitX, DistortionFitY; // In [-1,1] half-screen viewport units.
nuclear@1 275 Viewport FullView; // Entire window viewport.
nuclear@1 276
nuclear@1 277 float Area2DFov; // FOV range mapping to [-1, 1] 2D area.
nuclear@1 278
nuclear@1 279 // *** Computed State
nuclear@1 280
nuclear@1 281 bool DirtyFlag; // Set when any if the modifiable state changed.
nuclear@1 282 bool IPDOverride; // True after SetIPD was called.
nuclear@1 283 float YFov; // Vertical FOV.
nuclear@1 284 float Aspect; // Aspect ratio: (w/h)*AspectMultiplier.
nuclear@1 285 float ProjectionCenterOffset;
nuclear@1 286 StereoEyeParams EyeRenderParams[2];
nuclear@1 287
nuclear@1 288
nuclear@1 289 // ** 2D Rendering
nuclear@1 290
nuclear@1 291 // Number of 2D pixels in the FOV. This defines [-1,1] coordinate range for 2D.
nuclear@1 292 float FovPixels;
nuclear@1 293 Matrix4f OrthoCenter;
nuclear@1 294 float OrthoPixelOffset;
nuclear@1 295 };
nuclear@1 296
nuclear@1 297
nuclear@1 298 }}} // OVR::Util::Render
nuclear@1 299
nuclear@1 300 #endif