00001 /************************************************************************************ 00002 00003 PublicHeader: OVR.h 00004 Filename : Util_Render_Stereo.h 00005 Content : Sample stereo rendering configuration classes. 00006 Created : October 22, 2012 00007 Authors : Michael Antonov 00008 00009 Copyright : Copyright 2012 Oculus, Inc. All Rights reserved. 00010 00011 Use of this software is subject to the terms of the Oculus Inc license 00012 agreement provided at the time of installation or download, or which 00013 otherwise accompanies this software in either electronic or hard copy form. 00014 00015 *************************************************************************************/ 00016 00017 #ifndef OVR_Util_Render_Stereo_h 00018 #define OVR_Util_Render_Stereo_h 00019 00020 #include "../OVR_Device.h" 00021 00022 namespace OVR { namespace Util { namespace Render { 00023 00024 00025 //----------------------------------------------------------------------------------- 00026 // ***** Stereo Enumerations 00027 00028 // StereoMode describes rendering modes that can be used by StereoConfig. 00029 // These modes control whether stereo rendering is used or not (Stereo_None), 00030 // and how it is implemented. 00031 enum StereoMode 00032 { 00033 Stereo_None = 0, 00034 Stereo_LeftRight_Multipass = 1 00035 }; 00036 00037 00038 // StereoEye specifies which eye we are rendering for; it is used to 00039 // retrieve StereoEyeParams. 00040 enum StereoEye 00041 { 00042 StereoEye_Center, 00043 StereoEye_Left, 00044 StereoEye_Right 00045 }; 00046 00047 00048 //----------------------------------------------------------------------------------- 00049 // ***** Viewport 00050 00051 // Viewport describes a rectangular area used for rendering, in pixels. 00052 struct Viewport 00053 { 00054 int x, y; 00055 int w, h; 00056 00057 Viewport() {} 00058 Viewport(int x1, int y1, int w1, int h1) : x(x1), y(y1), w(w1), h(h1) { } 00059 00060 bool operator == (const Viewport& vp) const 00061 { return (x == vp.x) && (y == vp.y) && (w == vp.w) && (h == vp.h); } 00062 bool operator != (const Viewport& vp) const 00063 { return !operator == (vp); } 00064 }; 00065 00066 00067 //----------------------------------------------------------------------------------- 00068 // ***** DistortionConfig 00069 00070 // DistortionConfig Provides controls for the distortion shader. 00071 // - K[0] - K[3] are coefficients for the distortion function. 00072 // - XCenterOffset is the offset of lens distortion center from the 00073 // center of one-eye screen half. [-1, 1] Range. 00074 // - Scale is a factor of how much larger will the input image be, 00075 // with a factor of 1.0f being no scaling. An inverse of this 00076 // value is applied to sampled UV coordinates (1/Scale). 00077 // - ChromaticAberration is an array of parameters for controlling 00078 // additional Red and Blue scaling in order to reduce chromatic aberration 00079 // caused by the Rift lenses. 00080 class DistortionConfig 00081 { 00082 public: 00083 DistortionConfig(float k0 = 1.0f, float k1 = 0.0f, float k2 = 0.0f, float k3 = 0.0f) 00084 : XCenterOffset(0), YCenterOffset(0), Scale(1.0f) 00085 { 00086 SetCoefficients(k0, k1, k2, k3); 00087 SetChromaticAberration(); 00088 } 00089 00090 void SetCoefficients(float k0, float k1 = 0.0f, float k2 = 0.0f, float k3 = 0.0f) 00091 { K[0] = k0; K[1] = k1; K[2] = k2; K[3] = k3; } 00092 00093 void SetChromaticAberration(float red1 = 1.0f, float red2 = 0.0f, float blue1 = 1.0f, float blue2 = 0.0f) 00094 { ChromaticAberration[0] = red1; ChromaticAberration[1] = red2; ChromaticAberration[2] = blue1; ChromaticAberration[3] = blue2; } 00095 00096 00097 // DistortionFn applies distortion equation to the argument. The returned 00098 // value should match distortion equation used in shader. 00099 float DistortionFn(float r) const 00100 { 00101 float rsq = r * r; 00102 float scale = r * (K[0] + K[1] * rsq + K[2] * rsq * rsq + K[3] * rsq * rsq * rsq); 00103 return scale; 00104 } 00105 00106 // DistortionFnInverse computes the inverse of the distortion function on an argument. 00107 float DistortionFnInverse(float r); 00108 00109 float K[4]; 00110 float XCenterOffset, YCenterOffset; 00111 float Scale; 00112 00113 float ChromaticAberration[4]; // Additional per-channel scaling is applied after distortion: 00114 // Index [0] - Red channel constant coefficient. 00115 // Index [1] - Red channel r^2 coefficient. 00116 // Index [2] - Blue channel constant coefficient. 00117 // Index [3] - Blue channel r^2 coefficient. 00118 }; 00119 00120 00121 //----------------------------------------------------------------------------------- 00122 // ***** StereoEyeParams 00123 00124 // StereoEyeParams describes RenderDevice configuration needed to render 00125 // the scene for one eye. 00126 class StereoEyeParams 00127 { 00128 public: 00129 StereoEye Eye; 00130 Viewport VP; // Viewport that we are rendering to 00131 const DistortionConfig* pDistortion; 00132 00133 Matrix4f ViewAdjust; // Translation to be applied to view matrix. 00134 Matrix4f Projection; // Projection matrix used with this eye. 00135 Matrix4f OrthoProjection; // Orthographic projection used with this eye. 00136 00137 void Init(StereoEye eye, const Viewport &vp, float vofs, 00138 const Matrix4f& proj, const Matrix4f& orthoProj, 00139 const DistortionConfig* distortion = 0) 00140 { 00141 Eye = eye; 00142 VP = vp; 00143 ViewAdjust = Matrix4f::Translation(Vector3f(vofs,0,0)); 00144 Projection = proj; 00145 OrthoProjection = orthoProj; 00146 pDistortion = distortion; 00147 } 00148 }; 00149 00150 00151 //----------------------------------------------------------------------------------- 00152 // ***** StereoConfig 00153 00154 // StereoConfig maintains a scene stereo state and allow switching between different 00155 // stereo rendering modes. To support rendering, StereoConfig keeps track of HMD 00156 // variables such as screen size, eye-to-screen distance and distortion, and computes 00157 // extra data such as FOV and distortion center offsets based on it. Rendering 00158 // parameters are returned though StereoEyeParams for each eye. 00159 // 00160 // Beyond regular 3D projection, this class supports rendering a 2D orthographic 00161 // surface for UI and text. The 2D surface will be defined as fitting within a 2D 00162 // field of view (85 degrees by default) and used [-1,1] coordinate system with 00163 // square pixels. The (0,0) coordinate corresponds to eye center location 00164 // that is properly adjusted during rendering through SterepRenderParams::Adjust2D. 00165 // Genreally speaking, text outside [-1,1] coordinate range will not be readable. 00166 00167 class StereoConfig 00168 { 00169 public: 00170 00171 StereoConfig(StereoMode mode = Stereo_LeftRight_Multipass, 00172 const Viewport& fullViewport = Viewport(0,0, 1280,800)); 00173 00174 00175 // *** Modifiable State Access 00176 00177 // Sets a stereo rendering mode and updates internal cached 00178 // state (matrices, per-eye view) based on it. 00179 void SetStereoMode(StereoMode mode) { Mode = mode; DirtyFlag = true; } 00180 StereoMode GetStereoMode() const { return Mode; } 00181 00182 // Sets HMD parameters; also initializes distortion coefficients. 00183 void SetHMDInfo(const HMDInfo& hmd); 00184 const HMDInfo& GetHMDInfo() const { return HMD; } 00185 00186 // Query physical eye-to-screen distance in meters, which combines screen-to-lens and 00187 // and lens-to-eye pupil distances. Modifying this value adjusts FOV. 00188 float GetEyeToScreenDistance() const { return HMD.EyeToScreenDistance; } 00189 void SetEyeToScreenDistance(float esd) { HMD.EyeToScreenDistance = esd; DirtyFlag = true; } 00190 00191 // Interpupillary distance used for stereo, in meters. Default is 0.064m (64 mm). 00192 void SetIPD(float ipd) { InterpupillaryDistance = ipd; IPDOverride = DirtyFlag = true; } 00193 float GetIPD() const { return InterpupillaryDistance; } 00194 00195 // Set full render target viewport; for HMD this includes both eyes. 00196 void SetFullViewport(const Viewport& vp); 00197 const Viewport& GetFullViewport() const { return FullView; } 00198 00199 // Aspect ratio defaults to ((w/h)*multiplier) computed per eye. 00200 // Aspect multiplier allows adjusting aspect ratio consistently for Stereo/NoStereo. 00201 void SetAspectMultiplier(float m) { AspectMultiplier = m; DirtyFlag = true; } 00202 float GetAspectMultiplier() const { return AspectMultiplier; } 00203 00204 00205 // For the distorted image to fill rendered viewport, input texture render target needs to be 00206 // scaled by DistortionScale before sampling. The scale factor is computed by fitting a point 00207 // on of specified radius from a distortion center, more easily specified as a coordinate. 00208 // SetDistortionFitPointVP sets the (x,y) coordinate of the point that scale will be "fit" to, 00209 // assuming [-1,1] coordinate range for full left-eye viewport. A fit point is a location 00210 // where source (pre-distortion) and target (post-distortion) image match each other. 00211 // For the right eye, the interpretation of 'u' will be inverted. 00212 void SetDistortionFitPointVP(float x, float y); 00213 // SetDistortionFitPointPixels sets the (x,y) coordinate of the point that scale will be "fit" to, 00214 // specified in pixeld for full left-eye texture. 00215 void SetDistortionFitPointPixels(float x, float y); 00216 00217 // Changes all distortion settings. 00218 // Note that setting HMDInfo also changes Distortion coefficients. 00219 void SetDistortionConfig(const DistortionConfig& d) { Distortion = d; DirtyFlag = true; } 00220 00221 // Modify distortion coefficients; useful for adjustment tweaking. 00222 void SetDistortionK(int i, float k) { Distortion.K[i] = k; DirtyFlag = true; } 00223 float GetDistortionK(int i) const { return Distortion.K[i]; } 00224 00225 // Sets the fieldOfView that the 2D coordinate area stretches to. 00226 void Set2DAreaFov(float fovRadians); 00227 00228 00229 // *** Computed State 00230 00231 // Return current aspect ratio. 00232 float GetAspect() { updateIfDirty(); return Aspect; } 00233 00234 // Return computed vertical FOV in radians/degrees. 00235 float GetYFOVRadians() { updateIfDirty(); return YFov; } 00236 float GetYFOVDegrees() { return RadToDegree(GetYFOVRadians()); } 00237 00238 // Query horizontal projection center offset as a distance away from the 00239 // one-eye [-1,1] unit viewport. 00240 // Positive return value should be used for left eye, negative for right eye. 00241 float GetProjectionCenterOffset() { updateIfDirty(); return ProjectionCenterOffset; } 00242 00243 // GetDistortionConfig isn't const because XCenterOffset bay need to be recomputed. 00244 const DistortionConfig& GetDistortionConfig() { updateIfDirty(); return Distortion; } 00245 00246 // Returns DistortionScale factor by which input texture size is increased to make 00247 // post-distortion result distortion fit the viewport. 00248 float GetDistortionScale() { updateIfDirty(); return Distortion.Scale; } 00249 00250 // Returns the size of a pixel within 2D coordinate system. 00251 float Get2DUnitPixel() { updateIfDirty(); return (2.0f / (FovPixels * Distortion.Scale)); } 00252 00253 // Returns full set of Stereo rendering parameters for the specified eye. 00254 const StereoEyeParams& GetEyeRenderParams(StereoEye eye); 00255 00256 private: 00257 00258 void updateIfDirty() { if (DirtyFlag) updateComputedState(); } 00259 void updateComputedState(); 00260 00261 void updateDistortionOffsetAndScale(); 00262 void updateProjectionOffset(); 00263 void update2D(); 00264 void updateEyeParams(); 00265 00266 00267 // *** Modifiable State 00268 00269 StereoMode Mode; 00270 float InterpupillaryDistance; 00271 float AspectMultiplier; // Multiplied into aspect ratio to change it. 00272 HMDInfo HMD; 00273 DistortionConfig Distortion; 00274 float DistortionFitX, DistortionFitY; // In [-1,1] half-screen viewport units. 00275 Viewport FullView; // Entire window viewport. 00276 00277 float Area2DFov; // FOV range mapping to [-1, 1] 2D area. 00278 00279 // *** Computed State 00280 00281 bool DirtyFlag; // Set when any if the modifiable state changed. 00282 bool IPDOverride; // True after SetIPD was called. 00283 float YFov; // Vertical FOV. 00284 float Aspect; // Aspect ratio: (w/h)*AspectMultiplier. 00285 float ProjectionCenterOffset; 00286 StereoEyeParams EyeRenderParams[2]; 00287 00288 00289 // ** 2D Rendering 00290 00291 // Number of 2D pixels in the FOV. This defines [-1,1] coordinate range for 2D. 00292 float FovPixels; 00293 Matrix4f OrthoCenter; 00294 float OrthoPixelOffset; 00295 }; 00296 00297 00298 }}} // OVR::Util::Render 00299 00300 #endif