From 268da92f49360feaf9445ed2b8264d9310d3cebe Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 21 Sep 2013 20:10:19 +0300 Subject: [PATCH] Render eye view with off-center projection to better match visible area --- source/oculusriftcombiner.cpp | 8 +++++--- source/stereocombiner.cpp | 3 ++- source/stereocombiner.h | 2 ++ source/stereoview.cpp | 9 ++++++--- source/stereoview.h | 2 +- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/source/oculusriftcombiner.cpp b/source/oculusriftcombiner.cpp index b15c86b..3ebbcc8 100644 --- a/source/oculusriftcombiner.cpp +++ b/source/oculusriftcombiner.cpp @@ -22,6 +22,7 @@ const char fs_source[] = "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" @@ -29,13 +30,13 @@ const char fs_source[] = "{\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"; @@ -155,6 +156,7 @@ void OculusRiftCombiner::update_parameters() 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 diff --git a/source/stereocombiner.cpp b/source/stereocombiner.cpp index 54ab3e3..a276c3b 100644 --- a/source/stereocombiner.cpp +++ b/source/stereocombiner.cpp @@ -7,7 +7,8 @@ StereoCombiner::StereoCombiner(): width_div(1), height_div(1), keep_aspect(false), - oversize(1.0f) + oversize(1.0f), + frustum_skew(0.0f) { } } // namespace VR diff --git a/source/stereocombiner.h b/source/stereocombiner.h index f078df7..23d4822 100644 --- a/source/stereocombiner.h +++ b/source/stereocombiner.h @@ -15,6 +15,7 @@ protected: bool keep_aspect; Geometry::Angle fov; float oversize; + float frustum_skew; StereoCombiner(); public: @@ -25,6 +26,7 @@ public: bool is_aspect_kept() const { return keep_aspect; } const Geometry::Angle &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; }; diff --git a/source/stereoview.cpp b/source/stereoview.cpp index c528023..08949e6 100644 --- a/source/stereoview.cpp +++ b/source/stereoview.cpp @@ -49,8 +49,10 @@ void StereoView::setup_frame() const 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(); } @@ -98,7 +100,7 @@ void StereoView::Eye::create_target(unsigned w, unsigned h) 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()); @@ -107,6 +109,7 @@ void StereoView::Eye::setup_frame(const GL::Camera &base_camera, const GL::Vecto 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 diff --git a/source/stereoview.h b/source/stereoview.h index fe3d6d6..5516823 100644 --- a/source/stereoview.h +++ b/source/stereoview.h @@ -41,7 +41,7 @@ private: 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; }; -- 2.45.2