namespace {
const char vs_source[] =
+ "uniform mat4 timewarp[2];\n"
+ "uniform vec2 uv_scale;\n"
+ "uniform vec2 uv_offset;\n"
"varying vec2 texcoord_r;\n"
"varying vec2 texcoord_g;\n"
"varying vec2 texcoord_b;\n"
"varying float vignette;\n"
+ "vec2 apply_timewarp(vec2 coords, float factor)\n"
+ "{\n"
+ " vec4 coords4 = vec4(coords, 1.0, 1.0);\n"
+ " vec4 warped = mix(timewarp[0]*coords4, timewarp[1]*coords4, factor);\n"
+ " return (warped.xy/warped.z)*uv_scale+uv_offset;\n"
+ "}\n"
"void main()\n"
"{\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"
+ " float tw_factor = gl_MultiTexCoord3.y;\n"
+ " texcoord_r = apply_timewarp(gl_MultiTexCoord0.xy, tw_factor);\n"
+ " texcoord_g = apply_timewarp(gl_MultiTexCoord1.xy, tw_factor);\n"
+ " texcoord_b = apply_timewarp(gl_MultiTexCoord2.xy, tw_factor);\n"
" vignette = gl_MultiTexCoord3.x;\n"
"}\n";
void create_distortion_mesh(Msp::GL::Mesh &mesh, ovrHmd hmd, ovrEyeType eye, const ovrFovPort &fov)
{
ovrDistortionMesh ovr_mesh;
- ovrHmd_CreateDistortionMesh(hmd, eye, fov, ovrDistortionCap_Chromatic|ovrDistortionCap_Vignette, &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];
+ ovrHmd_CreateDistortionMesh(hmd, eye, fov, ovrDistortionCap_Chromatic|ovrDistortionCap_Vignette|ovrDistortionCap_TimeWarp, &ovr_mesh);
Msp::GL::MeshBuilder bld(mesh);
for(unsigned i=0; i<ovr_mesh.VertexCount; ++i)
{
ovrDistortionVertex &v = ovr_mesh.pVertexData[i];
- bld.multitexcoord(0, v.TanEyeAnglesR.x*scale.x+offset.x, 1.0f-(v.TanEyeAnglesR.y*scale.y+offset.y));
- bld.multitexcoord(1, v.TanEyeAnglesG.x*scale.x+offset.x, 1.0f-(v.TanEyeAnglesG.y*scale.y+offset.y));
- bld.multitexcoord(2, v.TanEyeAnglesB.x*scale.x+offset.x, 1.0f-(v.TanEyeAnglesB.y*scale.y+offset.y));
- bld.multitexcoord(3, v.VignetteFactor);
+ bld.multitexcoord(0, v.TanEyeAnglesR.x, v.TanEyeAnglesR.y);
+ bld.multitexcoord(1, v.TanEyeAnglesG.x, v.TanEyeAnglesG.y);
+ bld.multitexcoord(2, v.TanEyeAnglesB.x, v.TanEyeAnglesB.y);
+ bld.multitexcoord(3, v.VignetteFactor, v.TimeWarpFactor);
bld.vertex(v.ScreenPosNDC.x, v.ScreenPosNDC.y);
}
OculusRiftCombiner::OculusRiftCombiner(const OculusRiftDevice &d):
device(d),
- left_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2, GL::TEXCOORD1,3)),
- right_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2, GL::TEXCOORD1,3)),
+ left_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2, GL::TEXCOORD2,3)),
+ right_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2, GL::TEXCOORD2,3)),
shprog(vs_source, fs_source)
{
ovrHmd hmd = device.get_private().ovr_hmd;
float aspect = (inner+outer)/(vertical*2);
aspect_factor = aspect*hmd->Resolution.h/hmd->Resolution.w;
- shdata.uniform("texture", 0);
+ left_shdata.uniform("texture", 0);
+ right_shdata.uniform("texture", 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(left_fov, tex_size, view_rect, uv_scale_offset);
+ left_shdata.uniform("uv_scale", uv_scale_offset[0].x, -uv_scale_offset[0].y);
+ left_shdata.uniform("uv_offset", uv_scale_offset[1].x, 1-uv_scale_offset[1].y);
+ ovrHmd_GetRenderScaleAndOffset(right_fov, tex_size, view_rect, uv_scale_offset);
+ right_shdata.uniform("uv_scale", uv_scale_offset[0].x, -uv_scale_offset[0].y);
+ right_shdata.uniform("uv_offset", uv_scale_offset[1].x, 1-uv_scale_offset[1].y);
}
void OculusRiftCombiner::render(const GL::Texture2D &left, const GL::Texture2D &right) const
{
GL::Bind bind_shprog(shprog);
- shdata.apply();
+
+ ovrHmd hmd = device.get_private().ovr_hmd;
+
+ if(device.is_timing_active())
+ {
+ ovr_WaitTillTime(device.get_timewarp_time());
+ ovrTrackingState state = ovrHmd_GetTrackingState(hmd, device.get_tracking_time());
+
+ ovrMatrix4f matrices[2];
+ ovrHmd_GetEyeTimewarpMatrices(hmd, ovrEye_Left, state.HeadPose.ThePose, matrices);
+ left_shdata.uniform_matrix4_array("timewarp", 2, &matrices[0].M[0][0]);
+
+ ovrHmd_GetEyeTimewarpMatrices(hmd, ovrEye_Right, state.HeadPose.ThePose, matrices);
+ right_shdata.uniform_matrix4_array("timewarp", 2, &matrices[0].M[0][0]);
+ }
+ else
+ {
+ GL::Matrix matrices[2];
+ left_shdata.uniform_matrix4_array("timewarp", 2, matrices[0].data());
+ right_shdata.uniform_matrix4_array("timewarp", 2, matrices[0].data());
+ }
GL::Bind bind_tex(left);
+ left_shdata.apply();
left_mesh.draw();
right.bind();
+ right_shdata.apply();
right_mesh.draw();
}