oculus1

annotate libovr/Src/Util/Util_Render_Stereo.h @ 29:9a973ef0e2a3

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