"uniform sampler2D texture;\n"
"uniform vec4 distortion;\n"
"uniform vec4 chromatic;\n"
+ "uniform vec2 lens_center;\n"
"uniform vec2 eye_center;\n"
"uniform vec3 scale;\n"
"varying vec2 texcoord;\n"
"{\n"
" float r_sq = dot(texcoord, texcoord);\n"
" float f = dot(distortion, vec4(1.0, r_sq, r_sq*r_sq, r_sq*r_sq*r_sq));\n"
- " vec2 dtc = (texcoord*f-eye_center)/(scale.xy*scale.z)+0.5;\n"
+ " vec2 dtc = (texcoord*f-eye_center)/(scale.xy*scale.z)+lens_center;\n"
" if(dtc.x<0.0 || dtc.y<0.0 || dtc.x>1.0 || dtc.y>1.0)\n"
" gl_FragColor = vec4(0.0);\n"
" else\n"
" {\n"
- " vec2 red_dtc = (texcoord*f*(chromatic[0]+chromatic[1]*r_sq)-eye_center)/(scale.xy*scale.z)+0.5;\n"
- " vec2 blue_dtc = (texcoord*f*(chromatic[2]+chromatic[3]*r_sq)-eye_center)/(scale.xy*scale.z)+0.5;\n"
+ " vec2 red_dtc = (texcoord*f*(chromatic[0]+chromatic[1]*r_sq)-eye_center)/(scale.xy*scale.z)+lens_center;\n"
+ " vec2 blue_dtc = (texcoord*f*(chromatic[2]+chromatic[3]*r_sq)-eye_center)/(scale.xy*scale.z)+lens_center;\n"
" gl_FragColor = vec4(texture2D(texture, red_dtc).r, texture2D(texture, dtc).g, texture2D(texture, blue_dtc).b, 1.0);\n"
" }\n"
"}\n";
right_shdata.uniform("scale", 2.0f, 2.5f, oversize);
fov = Geometry::atan(oversize*0.625f/view_distance)*2.0f;
+ frustum_skew = lens_separation*2-1;
}
float OculusRiftCombiner::distort(float r) const
width_div(1),
height_div(1),
keep_aspect(false),
- oversize(1.0f)
+ oversize(1.0f),
+ frustum_skew(0.0f)
{ }
} // namespace VR
bool keep_aspect;
Geometry::Angle<float> fov;
float oversize;
+ float frustum_skew;
StereoCombiner();
public:
bool is_aspect_kept() const { return keep_aspect; }
const Geometry::Angle<float> &get_field_of_view() const { return fov; }
float get_oversize() const { return oversize; }
+ float get_frustum_skew() const { return frustum_skew; }
virtual void render(const GL::Texture2D &, const GL::Texture2D &) const = 0;
};
params.near_clip = base_camera.get_near_clip();
params.far_clip = base_camera.get_far_clip();
- left.setup_frame(base_camera, offset_axis*-eye_spacing, params);
- right.setup_frame(base_camera, offset_axis*eye_spacing, params);
+ float frustum_skew = combiner->get_frustum_skew();
+
+ left.setup_frame(base_camera, offset_axis*-eye_spacing, frustum_skew, params);
+ right.setup_frame(base_camera, offset_axis*eye_spacing, -frustum_skew, params);
renderable.setup_frame();
}
target = new RenderTarget(w, h);
}
-void StereoView::Eye::setup_frame(const GL::Camera &base_camera, const GL::Vector3 &offset, const EyeParams ¶ms) const
+void StereoView::Eye::setup_frame(const GL::Camera &base_camera, const GL::Vector3 &offset, float frustum_skew, const EyeParams ¶ms) const
{
camera.set_position(base_camera.get_position()+offset);
camera.set_up_direction(base_camera.get_up_direction());
camera.set_field_of_view(params.fov);
camera.set_aspect(params.aspect);
camera.set_depth_clip(params.near_clip, params.far_clip);
+ camera.set_frustum_axis(frustum_skew, 0);
}
void StereoView::Eye::render(const GL::Renderable &renderable, const GL::Tag &tag) const
Eye();
void create_target(unsigned, unsigned);
- void setup_frame(const GL::Camera &, const GL::Vector3 &, const EyeParams &) const;
+ void setup_frame(const GL::Camera &, const GL::Vector3 &, float, const EyeParams &) const;
void render(const GL::Renderable &, const GL::Tag &) const;
};