2 #include "meshbuilder.h"
3 #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 vec2 eye_center;\n"
25 "uniform vec3 scale;\n"
26 "varying vec2 texcoord;\n"
27 "vec2 distort(vec2 coord)\n"
29 " float r_sq = dot(coord, coord);\n"
30 " return coord*dot(distortion, vec4(1.0, r_sq, r_sq*r_sq, r_sq*r_sq*r_sq));\n"
34 " vec2 dtc = (distort(texcoord)-eye_center)/(scale.xy*scale.z)+0.5;\n"
35 " if(dtc.x<0.0 || dtc.y<0.0 || dtc.x>1.0 || dtc.y>1.0)\n"
36 " gl_FragColor = vec4(0.0);\n"
38 " gl_FragColor = texture2D(texture, dtc);\n"
46 OculusRiftCombiner::OculusRiftCombiner():
48 shprog(vs_source, fs_source),
49 // Default values copied from the SDK
50 view_distance(0.438f),
51 lens_separation(0.424f),
52 eye_separation(0.42735f),
57 left_shdata.uniform("texture", 0);
58 left_shdata.uniform("offset", -0.5f);
59 right_shdata.uniform("texture", 0);
60 right_shdata.uniform("offset", 0.5f);
62 // This will also call update_parameters
63 set_distortion(1.0f, 0.22f, 0.24f);
65 MeshBuilder bld(mesh);
66 bld.begin(TRIANGLE_STRIP);
74 void OculusRiftCombiner::set_view_distance(float d)
80 void OculusRiftCombiner::set_lens_separation(float s)
86 void OculusRiftCombiner::set_eye_separation(float s)
92 void OculusRiftCombiner::set_distortion(float d0, float d1, float d2, float d3)
102 void OculusRiftCombiner::set_fill_factor(float f)
108 void OculusRiftCombiner::update_parameters()
110 left_shdata.uniform4("distortion", distortion);
111 right_shdata.uniform4("distortion", distortion);
113 // Set lens center positions, in output texture coordinates
114 left_shdata.uniform("lens_center", 1.0f-lens_separation, 0.5);
115 right_shdata.uniform("lens_center", lens_separation, 0.5);
117 /* Compute distance between eye and lens centers, in sampling texture
119 float eye_offset = distort((eye_separation-lens_separation)*2);
120 left_shdata.uniform("eye_center", -eye_offset, 0.0f);
121 right_shdata.uniform("eye_center", eye_offset, 0.0f);
123 /* Determine the necessary scaling factor to avoid quality degradation in
124 the center of the screen. */
125 float horiz_oversize = distort((fill_factor-lens_separation)*2)-eye_offset;
126 float vert_oversize = distort(1.25f*fill_factor)/(1.25f*fill_factor);
127 oversize = min(horiz_oversize, vert_oversize);
129 left_shdata.uniform("scale", 2.0f, 2.5f, oversize);
130 right_shdata.uniform("scale", 2.0f, 2.5f, oversize);
132 fov = Geometry::atan(oversize*0.625f/view_distance)*2.0f;
135 float OculusRiftCombiner::distort(float r) const
138 return r*(distortion[0]+(distortion[1]+(distortion[2]+distortion[3]*r_sq)*r_sq)*r_sq);
141 float OculusRiftCombiner::undistort(float r) const
146 float y = distort(x);
151 float d = distortion[0]+(3*distortion[1]+(5*distortion[2]+7*distortion[3]*x_sq)*x_sq)*x_sq;
156 void OculusRiftCombiner::render(const Texture2D &left, const Texture2D &right) const
158 Bind bind_shprog(shprog);
165 right_shdata.apply();