]> git.tdb.fi Git - libs/vr.git/blob - source/libovr/libovrcombiner.cpp
Fix memory leaks
[libs/vr.git] / source / libovr / libovrcombiner.cpp
1 #include <msp/gl/meshbuilder.h>
2 #include <msp/gl/texture2d.h>
3 #include "libovrcombiner.h"
4 #include "libovrsystem.h"
5 #include "libovrsystem_private.h"
6
7 using namespace std;
8
9 namespace {
10
11 const char vs_source[] =
12         "uniform mat4 timewarp[2];\n"
13         "uniform vec2 uv_scale;\n"
14         "uniform vec2 uv_offset;\n"
15         "varying vec2 texcoord_r;\n"
16         "varying vec2 texcoord_g;\n"
17         "varying vec2 texcoord_b;\n"
18         "varying float vignette;\n"
19         "vec2 apply_timewarp(vec2 coords, float factor)\n"
20         "{\n"
21         "       vec4 coords4 = vec4(coords, 1.0, 1.0);\n"
22         "       vec4 warped = mix(timewarp[0]*coords4, timewarp[1]*coords4, factor);\n"
23         "       return (warped.xy/warped.z)*uv_scale+uv_offset;\n"
24         "}\n"
25         "void main()\n"
26         "{\n"
27         "       gl_Position = vec4(gl_Vertex.xy, 0.5, 1.0);\n"
28         "       float tw_factor = gl_MultiTexCoord3.y;\n"
29         "       texcoord_r = apply_timewarp(gl_MultiTexCoord0.xy, tw_factor);\n"
30         "       texcoord_g = apply_timewarp(gl_MultiTexCoord1.xy, tw_factor);\n"
31         "       texcoord_b = apply_timewarp(gl_MultiTexCoord2.xy, tw_factor);\n"
32         "       vignette = gl_MultiTexCoord3.x;\n"
33         "}\n";
34
35 const char fs_source[] =
36         "uniform sampler2D texture;\n"
37         "varying vec2 texcoord_r;\n"
38         "varying vec2 texcoord_g;\n"
39         "varying vec2 texcoord_b;\n"
40         "varying float vignette;\n"
41         "void main()\n"
42         "{\n"
43         "       float r = texture2D(texture, texcoord_r).r;\n"
44         "       float g = texture2D(texture, texcoord_g).g;\n"
45         "       float b = texture2D(texture, texcoord_b).b;\n"
46         "       gl_FragColor = vec4(vec3(r, g, b)*vignette, 1.0);\n"
47         "}\n";
48
49 void create_distortion_mesh(Msp::GL::Mesh &mesh, ovrHmd hmd, ovrEyeType eye, const ovrFovPort &fov)
50 {
51         ovrDistortionMesh ovr_mesh;
52         ovrHmd_CreateDistortionMesh(hmd, eye, fov, ovrDistortionCap_Vignette|ovrDistortionCap_TimeWarp, &ovr_mesh);
53
54         Msp::GL::MeshBuilder bld(mesh);
55         for(unsigned i=0; i<ovr_mesh.VertexCount; ++i)
56         {
57                 ovrDistortionVertex &v = ovr_mesh.pVertexData[i];
58                 bld.multitexcoord(0, v.TanEyeAnglesR.x, v.TanEyeAnglesR.y);
59                 bld.multitexcoord(1, v.TanEyeAnglesG.x, v.TanEyeAnglesG.y);
60                 bld.multitexcoord(2, v.TanEyeAnglesB.x, v.TanEyeAnglesB.y);
61                 bld.multitexcoord(3, v.VignetteFactor, v.TimeWarpFactor);
62                 bld.vertex(v.ScreenPosNDC.x, v.ScreenPosNDC.y);
63         }
64
65         Msp::GL::Batch batch(Msp::GL::TRIANGLES);
66         batch.append(vector<unsigned>(ovr_mesh.pIndexData, ovr_mesh.pIndexData+ovr_mesh.IndexCount));
67         mesh.add_batch(batch);
68
69         ovrHmd_DestroyDistortionMesh(&ovr_mesh);
70 }
71
72 }
73
74 namespace Msp {
75 namespace VR {
76
77 struct LibOVRCombiner::Frustum: StereoCombiner::Frustum
78 {
79         Frustum(const ovrFovPort &);
80 };
81
82
83 LibOVRCombiner::LibOVRCombiner(LibOVRSystem &d, GL::View &v):
84         system(d),
85         view(v),
86         left_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2, GL::TEXCOORD2,3)),
87         right_mesh((GL::VERTEX2, GL::TEXCOORD2,0, GL::TEXCOORD2,1, GL::TEXCOORD2,2, GL::TEXCOORD2,3)),
88         shprog(vs_source, fs_source)
89 {
90         ovrHmd hmd = system.get_private().ovr_hmd;
91
92         ovrFovPort left_fov = hmd->DefaultEyeFov[ovrEye_Left];
93         ovrFovPort right_fov = hmd->DefaultEyeFov[ovrEye_Right];
94         configure_eye_frustums(Frustum(left_fov), Frustum(right_fov));
95
96         left_fov.UpTan = left_fov.DownTan = tan(fov/2.0f);
97         left_fov.LeftTan = left_fov.UpTan*render_aspect*(1-frustum_skew);
98         left_fov.RightTan = left_fov.UpTan*render_aspect*(1+frustum_skew);
99         right_fov = left_fov;
100         swap(right_fov.LeftTan, right_fov.RightTan);
101
102         create_distortion_mesh(left_mesh, hmd, ovrEye_Left, left_fov);
103         create_distortion_mesh(right_mesh, hmd, ovrEye_Right, right_fov);
104
105         ovrSizei tex_size = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, left_fov, 1.0);
106         target_width = tex_size.w;
107         target_height = tex_size.h;
108
109         left_shdata.uniform("texture", 0);
110         right_shdata.uniform("texture", 0);
111
112         ovrRecti view_rect;
113         view_rect.Pos.x = 0;
114         view_rect.Pos.y = 0;
115         view_rect.Size = tex_size;
116         ovrVector2f uv_scale_offset[2];
117         ovrHmd_GetRenderScaleAndOffset(left_fov, tex_size, view_rect, uv_scale_offset);
118         left_shdata.uniform("uv_scale", uv_scale_offset[0].x, -uv_scale_offset[0].y);
119         left_shdata.uniform("uv_offset", uv_scale_offset[1].x, 1-uv_scale_offset[1].y);
120         ovrHmd_GetRenderScaleAndOffset(right_fov, tex_size, view_rect, uv_scale_offset);
121         right_shdata.uniform("uv_scale", uv_scale_offset[0].x, -uv_scale_offset[0].y);
122         right_shdata.uniform("uv_offset", uv_scale_offset[1].x, 1-uv_scale_offset[1].y);
123
124         system.configure_window(view.get_window());
125 }
126
127 void LibOVRCombiner::prepare() const
128 {
129         system.begin_frame();
130 }
131
132 void LibOVRCombiner::render(const GL::Texture2D &left, const GL::Texture2D &right) const
133 {
134         GL::Bind bind_shprog(shprog);
135
136         ovrHmd hmd = system.get_private().ovr_hmd;
137
138         if(system.is_timing_active())
139         {
140                 ovr_WaitTillTime(system.get_timewarp_time());
141                 ovrTrackingState state = ovrHmd_GetTrackingState(hmd, system.get_tracking_time());
142
143                 ovrMatrix4f matrices[2];
144                 ovrHmd_GetEyeTimewarpMatrices(hmd, ovrEye_Left, state.HeadPose.ThePose, matrices);
145                 left_shdata.uniform_matrix4_array("timewarp", 2, &matrices[0].M[0][0]);
146
147                 ovrHmd_GetEyeTimewarpMatrices(hmd, ovrEye_Right, state.HeadPose.ThePose, matrices);
148                 right_shdata.uniform_matrix4_array("timewarp", 2, &matrices[0].M[0][0]);
149         }
150         else
151         {
152                 GL::Matrix matrices[2];
153                 left_shdata.uniform_matrix4_array("timewarp", 2, matrices[0].data());
154                 right_shdata.uniform_matrix4_array("timewarp", 2, matrices[0].data());
155         }
156
157         GL::Bind bind_tex(left);
158         left_shdata.apply();
159         left_mesh.draw();
160
161         right.bind();
162         right_shdata.apply();
163         right_mesh.draw();
164
165         view.get_context().swap_buffers();
166         system.end_frame();
167 }
168
169
170 LibOVRCombiner::Frustum::Frustum(const ovrFovPort &fov):
171         StereoCombiner::Frustum(-fov.LeftTan, fov.RightTan, -fov.DownTan, fov.UpTan)
172 { }
173
174 } // namespace VR
175 } // namespace Msp