2 #include <msp/gl/meshbuilder.h>
3 #include <msp/gl/texture2d.h>
4 #include "oculusriftcombiner.h"
10 const char vs_source[] =
11 "uniform float offset;\n"
12 "uniform vec2 lens_center;\n"
13 "uniform vec3 scale;\n"
14 "varying vec2 texcoord;\n"
17 " gl_Position = vec4(gl_Vertex.x*0.5+offset, gl_Vertex.yzw);\n"
18 " texcoord = (gl_Vertex.xy*0.5+0.5-lens_center)*scale.xy;\n"
21 const char fs_source[] =
22 "uniform sampler2D texture;\n"
23 "uniform vec4 distortion;\n"
24 "uniform vec4 chromatic;\n"
25 "uniform vec2 lens_center;\n"
26 "uniform vec2 eye_center;\n"
27 "uniform vec3 scale;\n"
28 "varying vec2 texcoord;\n"
31 " float r_sq = dot(texcoord, texcoord);\n"
32 " float f = dot(distortion, vec4(1.0, r_sq, r_sq*r_sq, r_sq*r_sq*r_sq));\n"
33 " vec2 dtc = (texcoord*f-eye_center)/(scale.xy*scale.z)+lens_center;\n"
34 " if(dtc.x<0.0 || dtc.y<0.0 || dtc.x>1.0 || dtc.y>1.0)\n"
35 " gl_FragColor = vec4(0.0);\n"
38 " vec2 red_dtc = (texcoord*f*(chromatic[0]+chromatic[1]*r_sq)-eye_center)/(scale.xy*scale.z)+lens_center;\n"
39 " vec2 blue_dtc = (texcoord*f*(chromatic[2]+chromatic[3]*r_sq)-eye_center)/(scale.xy*scale.z)+lens_center;\n"
40 " gl_FragColor = vec4(texture2D(texture, red_dtc).r, texture2D(texture, dtc).g, texture2D(texture, blue_dtc).b, 1.0);\n"
49 OculusRiftCombiner::OculusRiftCombiner():
51 shprog(vs_source, fs_source),
52 // Default values copied from the SDK
53 view_distance(0.438f),
54 lens_separation(0.424f),
55 eye_separation(0.42735f),
60 left_shdata.uniform("texture", 0);
61 left_shdata.uniform("offset", -0.5f);
62 right_shdata.uniform("texture", 0);
63 right_shdata.uniform("offset", 0.5f);
70 // This will also call update_parameters
71 set_distortion(1.0f, 0.22f, 0.24f);
73 GL::MeshBuilder bld(mesh);
74 bld.begin(GL::TRIANGLE_STRIP);
82 void OculusRiftCombiner::set_view_distance(float d)
88 void OculusRiftCombiner::set_lens_separation(float s)
94 void OculusRiftCombiner::set_eye_separation(float s)
100 void OculusRiftCombiner::set_distortion(float d0, float d1, float d2, float d3)
110 void OculusRiftCombiner::set_red_aberration(float c0, float c1)
118 void OculusRiftCombiner::set_blue_aberration(float c2, float c3)
126 void OculusRiftCombiner::set_fill_factor(float f)
132 void OculusRiftCombiner::update_parameters()
134 left_shdata.uniform4("distortion", distortion);
135 left_shdata.uniform4("chromatic", chromatic);
136 right_shdata.uniform4("distortion", distortion);
137 right_shdata.uniform4("chromatic", chromatic);
139 // Set lens center positions, in output texture coordinates
140 left_shdata.uniform("lens_center", 1.0f-lens_separation, 0.5);
141 right_shdata.uniform("lens_center", lens_separation, 0.5);
143 /* Compute distance between eye and lens centers, in sampling texture
145 float eye_offset = distort((eye_separation-lens_separation)*2);
146 left_shdata.uniform("eye_center", -eye_offset, 0.0f);
147 right_shdata.uniform("eye_center", eye_offset, 0.0f);
149 /* Determine the necessary scaling factor to avoid quality degradation in
150 the center of the screen. */
151 float horiz_oversize = distort((fill_factor-lens_separation)*2)/((fill_factor-lens_separation)*2)-eye_offset;
152 float vert_oversize = distort(1.25f*fill_factor)/(1.25f*fill_factor);
153 oversize = min(horiz_oversize, vert_oversize);
155 left_shdata.uniform("scale", 2.0f, 2.5f, oversize);
156 right_shdata.uniform("scale", 2.0f, 2.5f, oversize);
158 fov = Geometry::atan(oversize*0.625f/view_distance/2)*2.0f;
159 frustum_skew = lens_separation*2-1;
162 float OculusRiftCombiner::distort(float r) const
165 return r*(distortion[0]+(distortion[1]+(distortion[2]+distortion[3]*r_sq)*r_sq)*r_sq);
168 float OculusRiftCombiner::undistort(float r) const
173 float y = distort(x);
178 float d = distortion[0]+(3*distortion[1]+(5*distortion[2]+7*distortion[3]*x_sq)*x_sq)*x_sq;
183 void OculusRiftCombiner::render(const GL::Texture2D &left, const GL::Texture2D &right) const
185 GL::Bind bind_shprog(shprog);
187 GL::Bind bind_tex(left);
192 right_shdata.apply();