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
|