X-Git-Url: http://git.tdb.fi/?p=libs%2Fvr.git;a=blobdiff_plain;f=source%2Foculusriftcombiner.cpp;h=492f5fdbcb220ee40b5f73207fb0f7ee6a94a12c;hp=9d985d9268e679584419bb2c75bb4947ce22aeef;hb=b17410965e84e378c4cc85ffb732365552edc584;hpb=3d83f3acedfdd428807313986eefaf5bcd64b7e8 diff --git a/source/oculusriftcombiner.cpp b/source/oculusriftcombiner.cpp index 9d985d9..492f5fd 100644 --- a/source/oculusriftcombiner.cpp +++ b/source/oculusriftcombiner.cpp @@ -1,170 +1,124 @@ #include -#include "meshbuilder.h" +#include +#include #include "oculusriftcombiner.h" -#include "texture2d.h" +#include "oculusriftdevice.h" +#include "oculusriftdevice_private.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" + "varying vec2 texcoord_r;\n" + "varying vec2 texcoord_g;\n" + "varying vec2 texcoord_b;\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" + " gl_Position = vec4(gl_Vertex.xy, 0.5, 1.0);\n" + " texcoord_r = gl_MultiTexCoord0.xy;\n" + " texcoord_g = gl_MultiTexCoord1.xy;\n" + " texcoord_b = gl_MultiTexCoord2.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" + "varying vec2 texcoord_r;\n" + "varying vec2 texcoord_g;\n" + "varying vec2 texcoord_b;\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" + " float r = texture2D(texture, texcoord_r).r;\n" + " float g = texture2D(texture, texcoord_g).g;\n" + " float b = texture2D(texture, texcoord_b).b;\n" + " gl_FragColor = vec4(r, g, b, 1.0);\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) +void create_distortion_mesh(Msp::GL::Mesh &mesh, ovrHmd hmd, ovrEyeType eye, const ovrFovPort &fov) { - 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(); -} + ovrDistortionMesh ovr_mesh; + ovrHmd_CreateDistortionMesh(hmd, eye, fov, ovrDistortionCap_Chromatic, &ovr_mesh); + + ovrSizei tex_size = ovrHmd_GetFovTextureSize(hmd, eye, fov, 1.0); + ovrRecti view_rect; + view_rect.Pos.x = 0; + view_rect.Pos.y = 0; + view_rect.Size = tex_size; + ovrVector2f uv_scale_offset[2]; + ovrHmd_GetRenderScaleAndOffset(fov, tex_size, view_rect, uv_scale_offset); + ovrVector2f &scale = uv_scale_offset[0]; + ovrVector2f &offset = uv_scale_offset[1]; + + Msp::GL::MeshBuilder bld(mesh); + for(unsigned i=0; i(ovr_mesh.pIndexData, ovr_mesh.pIndexData+ovr_mesh.IndexCount)); + mesh.add_batch(batch); -void OculusRiftCombiner::set_eye_separation(float s) -{ - eye_separation = s; - update_parameters(); + ovrHmd_DestroyDistortionMesh(&ovr_mesh); } -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(); -} +namespace Msp { +namespace VR { -void OculusRiftCombiner::update_parameters() +OculusRiftCombiner::OculusRiftCombiner(const OculusRiftDevice &d): + device(d), + left_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2)), + right_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2)), + shprog(vs_source, fs_source) { - left_shdata.uniform4("distortion", distortion); - right_shdata.uniform4("distortion", distortion); + const OculusRiftDevice::Private &dev_priv = device.get_private(); + ovrHmd hmd = dev_priv.ovr_hmd; - // 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); + ovrFovPort left_fov = hmd->DefaultEyeFov[ovrEye_Left]; + ovrFovPort right_fov = hmd->DefaultEyeFov[ovrEye_Right]; + float vertical = max(max(left_fov.UpTan, left_fov.DownTan), max(right_fov.UpTan, right_fov.DownTan)); + fov = Geometry::atan(vertical)*2.0f; - /* 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); + float inner = max(left_fov.RightTan, right_fov.LeftTan); + float outer = max(left_fov.LeftTan, right_fov.RightTan); + frustum_skew = (inner-outer)*2/(inner+outer); - /* 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_fov.UpTan = right_fov.UpTan = vertical; + left_fov.DownTan = right_fov.DownTan = vertical; + left_fov.RightTan = right_fov.LeftTan = inner; + left_fov.LeftTan = right_fov.RightTan = outer; - left_shdata.uniform("scale", 2.0f, 2.5f, oversize); - right_shdata.uniform("scale", 2.0f, 2.5f, oversize); + create_distortion_mesh(left_mesh, hmd, ovrEye_Left, left_fov); + create_distortion_mesh(right_mesh, hmd, ovrEye_Right, right_fov); - fov = Geometry::atan(oversize*0.625f/view_distance)*2.0f; -} + ovrSizei tex_size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, left_fov, 1.0); + width_factor = tex_size.w*1.0f/hmd->Resolution.w; + height_factor = tex_size.h*1.0f/hmd->Resolution.h; + float aspect = (inner+outer)/(vertical*2); + aspect_factor = aspect*hmd->Resolution.h/hmd->Resolution.w; -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; + shdata.uniform("texture", 0); - 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 +void OculusRiftCombiner::render(const GL::Texture2D &left, const GL::Texture2D &right) const { - Bind bind_shprog(shprog); + GL::Bind bind_shprog(shprog); + shdata.apply(); - Bind bind_tex(left); - left_shdata.apply(); - mesh.draw(); + GL::Bind bind_tex(left); + left_mesh.draw(); right.bind(); - right_shdata.apply(); - mesh.draw(); + right_mesh.draw(); } -} // namespace GL +} // namespace VR } // namespace Msp