From: Mikko Rasa Date: Fri, 13 Sep 2013 13:27:55 +0000 (+0300) Subject: Stereographic rendering moved to a separate library (mspvr) X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=78328c5f6e4dcbe883a3f5e4fe0974ab490be3f7 Stereographic rendering moved to a separate library (mspvr) --- diff --git a/source/oculusriftcombiner.cpp b/source/oculusriftcombiner.cpp deleted file mode 100644 index 9d985d92..00000000 --- a/source/oculusriftcombiner.cpp +++ /dev/null @@ -1,170 +0,0 @@ -#include -#include "meshbuilder.h" -#include "oculusriftcombiner.h" -#include "texture2d.h" - -using namespace std; - -namespace { - -const char vs_source[] = - "uniform float offset;\n" - "uniform vec2 lens_center;\n" - "uniform vec3 scale;\n" - "varying vec2 texcoord;\n" - "void main()\n" - "{\n" - " gl_Position = vec4(gl_Vertex.x*0.5+offset, gl_Vertex.yzw);\n" - " texcoord = (gl_Vertex.xy*0.5+0.5-lens_center)*scale.xy;\n" - "}\n"; - -const char fs_source[] = - "uniform sampler2D texture;\n" - "uniform vec4 distortion;\n" - "uniform vec2 eye_center;\n" - "uniform vec3 scale;\n" - "varying vec2 texcoord;\n" - "vec2 distort(vec2 coord)\n" - "{\n" - " float r_sq = dot(coord, coord);\n" - " return coord*dot(distortion, vec4(1.0, r_sq, r_sq*r_sq, r_sq*r_sq*r_sq));\n" - "}\n" - "void main()\n" - "{\n" - " vec2 dtc = (distort(texcoord)-eye_center)/(scale.xy*scale.z)+0.5;\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" - " gl_FragColor = texture2D(texture, dtc);\n" - "}\n"; - -} - -namespace Msp { -namespace GL { - -OculusRiftCombiner::OculusRiftCombiner(): - mesh(VERTEX2), - shprog(vs_source, fs_source), - // Default values copied from the SDK - view_distance(0.438f), - lens_separation(0.424f), - eye_separation(0.42735f), - fill_factor(0.95f) -{ - width_div = 2; - - left_shdata.uniform("texture", 0); - left_shdata.uniform("offset", -0.5f); - right_shdata.uniform("texture", 0); - right_shdata.uniform("offset", 0.5f); - - // This will also call update_parameters - set_distortion(1.0f, 0.22f, 0.24f); - - MeshBuilder bld(mesh); - bld.begin(TRIANGLE_STRIP); - bld.vertex(-1, 1); - bld.vertex(-1, -1); - bld.vertex(1, 1); - bld.vertex(1, -1); - bld.end(); -} - -void OculusRiftCombiner::set_view_distance(float d) -{ - view_distance = d; - update_parameters(); -} - -void OculusRiftCombiner::set_lens_separation(float s) -{ - lens_separation = s; - update_parameters(); -} - -void OculusRiftCombiner::set_eye_separation(float s) -{ - eye_separation = s; - update_parameters(); -} - -void OculusRiftCombiner::set_distortion(float d0, float d1, float d2, float d3) -{ - distortion[0] = d0; - distortion[1] = d1; - distortion[2] = d2; - distortion[3] = d3; - - update_parameters(); -} - -void OculusRiftCombiner::set_fill_factor(float f) -{ - fill_factor = f; - update_parameters(); -} - -void OculusRiftCombiner::update_parameters() -{ - left_shdata.uniform4("distortion", distortion); - right_shdata.uniform4("distortion", distortion); - - // Set lens center positions, in output texture coordinates - left_shdata.uniform("lens_center", 1.0f-lens_separation, 0.5); - right_shdata.uniform("lens_center", lens_separation, 0.5); - - /* Compute distance between eye and lens centers, in sampling texture - coordinates. */ - float eye_offset = distort((eye_separation-lens_separation)*2); - left_shdata.uniform("eye_center", -eye_offset, 0.0f); - right_shdata.uniform("eye_center", eye_offset, 0.0f); - - /* Determine the necessary scaling factor to avoid quality degradation in - the center of the screen. */ - float horiz_oversize = distort((fill_factor-lens_separation)*2)-eye_offset; - float vert_oversize = distort(1.25f*fill_factor)/(1.25f*fill_factor); - oversize = min(horiz_oversize, vert_oversize); - - left_shdata.uniform("scale", 2.0f, 2.5f, oversize); - right_shdata.uniform("scale", 2.0f, 2.5f, oversize); - - fov = Geometry::atan(oversize*0.625f/view_distance)*2.0f; -} - -float OculusRiftCombiner::distort(float r) const -{ - float r_sq = r*r; - return r*(distortion[0]+(distortion[1]+(distortion[2]+distortion[3]*r_sq)*r_sq)*r_sq); -} - -float OculusRiftCombiner::undistort(float r) const -{ - float x = r; - while(1) - { - float y = distort(x); - if(abs(r-y)<1e-5) - return x; - - float x_sq = x*x; - float d = distortion[0]+(3*distortion[1]+(5*distortion[2]+7*distortion[3]*x_sq)*x_sq)*x_sq; - x -= (y-r)/d; - } -} - -void OculusRiftCombiner::render(const Texture2D &left, const Texture2D &right) const -{ - Bind bind_shprog(shprog); - - Bind bind_tex(left); - left_shdata.apply(); - mesh.draw(); - - right.bind(); - right_shdata.apply(); - mesh.draw(); -} - -} // namespace GL -} // namespace Msp diff --git a/source/oculusriftcombiner.h b/source/oculusriftcombiner.h deleted file mode 100644 index ede2fe91..00000000 --- a/source/oculusriftcombiner.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef MSP_GL_OCULUSRIFTCOMBINER_H_ -#define MSP_GL_OCULUSRIFTCOMBINER_H_ - -#include "mesh.h" -#include "program.h" -#include "programdata.h" -#include "stereocombiner.h" - -namespace Msp { -namespace GL { - -/** -Presents a stereo view in a way suitable for an Oculus Rift HMD. All distances -are specified in multiples of the screen width. -*/ -class OculusRiftCombiner: public StereoCombiner -{ -private: - Mesh mesh; - Program shprog; - ProgramData left_shdata; - ProgramData right_shdata; - float view_distance; - float lens_separation; - float eye_separation; - float distortion[4]; - float fill_factor; - -public: - OculusRiftCombiner(); - - void set_view_distance(float); - void set_lens_separation(float); - void set_eye_separation(float); - void set_distortion(float = 1.0f, float = 0.0f, float = 0.0f, float = 0.0f); - void set_fill_factor(float); -private: - void update_parameters(); - - float distort(float) const; - float undistort(float) const; - -public: - virtual void render(const Texture2D &, const Texture2D &) const; -}; - -} // namespace GL -} // namespace Msp - -#endif diff --git a/source/sidebysidecombiner.cpp b/source/sidebysidecombiner.cpp deleted file mode 100644 index b9d1d89c..00000000 --- a/source/sidebysidecombiner.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "meshbuilder.h" -#include "sidebysidecombiner.h" -#include "texture2d.h" - -namespace { - -const char vs_source[] = - "uniform float offset;\n" - "varying vec2 texcoord;\n" - "void main()\n" - "{\n" - " gl_Position = vec4(gl_Vertex.x*0.5+offset, gl_Vertex.yzw);\n" - " texcoord = gl_Vertex.xy*0.5+0.5;\n" - "}\n"; - -const char fs_source[] = - "uniform sampler2D texture;\n" - "varying vec2 texcoord;\n" - "void main()\n" - "{\n" - " gl_FragColor = texture2D(texture, texcoord);\n" - "}\n"; - -} - -namespace Msp { -namespace GL { - -SideBySideCombiner::SideBySideCombiner(bool c): - mesh(VERTEX2), - shprog(vs_source, fs_source) -{ - width_div = 2; - - left_shdata.uniform("texture", 0); - right_shdata.uniform("texture", 0); - - set_cross_eyed(c); - - MeshBuilder bld(mesh); - bld.begin(TRIANGLE_STRIP); - bld.vertex(-1, 1); - bld.vertex(-1, -1); - bld.vertex(1, 1); - bld.vertex(1, -1); - bld.end(); -} - -void SideBySideCombiner::set_cross_eyed(bool c) -{ - cross_eyed = c; - float m = (cross_eyed ? -0.5f : 0.5f); - left_shdata.uniform("offset", -m); - right_shdata.uniform("offset", m); -} - -void SideBySideCombiner::render(const Texture2D &left, const Texture2D &right) const -{ - Bind bind_shprog(shprog); - - Bind bind_tex(left); - left_shdata.apply(); - mesh.draw(); - - right.bind(); - right_shdata.apply(); - mesh.draw(); -} - -} // namespace GL -} // namespace Msp diff --git a/source/sidebysidecombiner.h b/source/sidebysidecombiner.h deleted file mode 100644 index f6ec593a..00000000 --- a/source/sidebysidecombiner.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef MSP_GL_SIDEBYSIDECOMBINER_H_ -#define MSP_GL_SIDEBYSIDECOMBINER_H_ - -#include "mesh.h" -#include "program.h" -#include "programdata.h" -#include "stereocombiner.h" - -namespace Msp { -namespace GL { - -class SideBySideCombiner: public StereoCombiner -{ -private: - Mesh mesh; - Program shprog; - ProgramData left_shdata; - ProgramData right_shdata; - bool cross_eyed; - -public: - SideBySideCombiner(bool = false); - - void set_cross_eyed(bool); - - virtual void render(const Texture2D &, const Texture2D &) const; -}; - -} // namespace GL -} // namespace Msp - -#endif diff --git a/source/stereocombiner.cpp b/source/stereocombiner.cpp deleted file mode 100644 index ba71818d..00000000 --- a/source/stereocombiner.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "stereocombiner.h" - -namespace Msp { -namespace GL { - -StereoCombiner::StereoCombiner(): - width_div(1), - height_div(1), - keep_aspect(false), - oversize(1.0f) -{ } - -} // namespace GL -} // namespace Msp diff --git a/source/stereocombiner.h b/source/stereocombiner.h deleted file mode 100644 index 5fb8dec7..00000000 --- a/source/stereocombiner.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef MSP_GL_STEREOCOMBINER_H_ -#define MSP_GL_STEREOCOMBINER_H_ - -#include - -namespace Msp { -namespace GL { - -class Texture2D; - -class StereoCombiner -{ -protected: - unsigned width_div; - unsigned height_div; - bool keep_aspect; - Geometry::Angle fov; - float oversize; - - StereoCombiner(); -public: - virtual ~StereoCombiner() { } - - unsigned get_width_divisor() const { return width_div; } - unsigned get_height_divisor() const { return height_div; } - bool is_aspect_kept() const { return keep_aspect; } - const Geometry::Angle &get_field_of_view() const { return fov; } - float get_oversize() const { return oversize; } - - virtual void render(const Texture2D &, const Texture2D &) const = 0; -}; - -} // namespace GL -} // namespace Msp - -#endif diff --git a/source/stereoview.cpp b/source/stereoview.cpp deleted file mode 100644 index 53c6445f..00000000 --- a/source/stereoview.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "renderer.h" -#include "stereocombiner.h" -#include "stereoview.h" - -using namespace std; - -namespace Msp { -namespace GL { - -StereoView::StereoView(unsigned w, unsigned h, const Camera &c, const Renderable &r, const StereoCombiner &m): - width(w), - height(h), - base_camera(c), - renderable(r), - combiner(0) -{ - set_combiner(m); - set_eye_spacing(0.07); -} - -void StereoView::set_combiner(const StereoCombiner &c) -{ - combiner = &c; - - unsigned w = width/combiner->get_width_divisor()*combiner->get_oversize(); - unsigned h = height/combiner->get_height_divisor()*combiner->get_oversize(); - left.create_target(w, h); - right.create_target(w, h); -} - -void StereoView::set_eye_spacing(float s) -{ - eye_spacing = s; -} - -void StereoView::setup_frame() const -{ - offset_axis = normalize(cross(base_camera.get_look_direction(), base_camera.get_up_direction()))*0.5f; - - EyeParams params; - params.fov = combiner->get_field_of_view(); - if(params.fov==Geometry::Angle::zero()) - params.fov = base_camera.get_field_of_view(); - - params.aspect = base_camera.get_aspect(); - if(!combiner->is_aspect_kept()) - params.aspect = params.aspect*combiner->get_height_divisor()/combiner->get_width_divisor(); - - 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); - - renderable.setup_frame(); -} - -void StereoView::finish_frame() const -{ - renderable.finish_frame(); -} - -void StereoView::render(const Tag &tag) const -{ - setup_frame(); - left.render(renderable, tag); - right.render(renderable, tag); - combiner->render(left.target->color, right.target->color); - finish_frame(); -} - -void StereoView::render(Renderer &renderer, const Tag &tag) const -{ - renderer.escape(); - return render(tag); -} - - -StereoView::RenderTarget::RenderTarget(unsigned width, unsigned height) -{ - color.set_min_filter(LINEAR); - color.set_wrap(CLAMP_TO_EDGE); - color.storage(RGB, width, height); - fbo.attach(COLOR_ATTACHMENT0, color); - - depth.storage(DEPTH_COMPONENT, width, height); - fbo.attach(DEPTH_ATTACHMENT, depth); -} - - -StereoView::Eye::Eye(): - target(0) -{ } - -void StereoView::Eye::create_target(unsigned w, unsigned h) -{ - delete target; - target = new RenderTarget(w, h); -} - -void StereoView::Eye::setup_frame(const Camera &base_camera, const Vector3 &offset, const EyeParams ¶ms) const -{ - camera.set_position(base_camera.get_position()+offset); - camera.set_up_direction(base_camera.get_up_direction()); - camera.set_look_direction(base_camera.get_look_direction()); - - camera.set_field_of_view(params.fov); - camera.set_aspect(params.aspect); - camera.set_depth_clip(params.near_clip, params.far_clip); -} - -void StereoView::Eye::render(const Renderable &renderable, const Tag &tag) const -{ - Bind bind_fbo(target->fbo); - Renderer renderer(&camera); - renderable.render(renderer, tag); -} - -} // namespace GL -} // namespace Msp diff --git a/source/stereoview.h b/source/stereoview.h deleted file mode 100644 index 4dce63b9..00000000 --- a/source/stereoview.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef MSP_GL_STEREOVIEW_H_ -#define MSP_GL_STEREOVIEW_H_ - -#include -#include "camera.h" -#include "framebuffer.h" -#include "renderable.h" -#include "renderbuffer.h" -#include "texture2d.h" - -namespace Msp { -namespace GL { - -class StereoCombiner; - -class StereoView: public Renderable -{ -private: - struct RenderTarget - { - Framebuffer fbo; - Texture2D color; - Renderbuffer depth; - - RenderTarget(unsigned, unsigned); - }; - - struct EyeParams - { - Geometry::Angle fov; - float aspect; - float near_clip; - float far_clip; - }; - - struct Eye - { - mutable Camera camera; - RenderTarget *target; - - Eye(); - - void create_target(unsigned, unsigned); - void setup_frame(const Camera &, const Vector3 &, const EyeParams &) const; - void render(const Renderable &, const Tag &) const; - }; - - unsigned width; - unsigned height; - const Camera &base_camera; - const Renderable &renderable; - const StereoCombiner *combiner; - Eye left; - Eye right; - float eye_spacing; - mutable Vector3 offset_axis; - -public: - StereoView(unsigned, unsigned, const Camera &, const Renderable &, const StereoCombiner &); - - void set_combiner(const StereoCombiner &); - void set_eye_spacing(float); - - virtual void setup_frame() const; - virtual void finish_frame() const; - - virtual void render(const Tag & = Tag()) const; - virtual void render(Renderer &, const Tag & = Tag()) const; -}; - -} // namespace GL -} // namespace Msp - -#endif