# HG changeset patch # User John Tsiombikas # Date 1380676177 -10800 # Node ID ef4c9d8eeca7c3d4852f8352d14068aa24edc79c # Parent ff3bfd4da86b761a37930a4208c34a0d8205a498 added shaderless distortion method diff -r ff3bfd4da86b -r ef4c9d8eeca7 oculus1.vcproj --- a/oculus1.vcproj Tue Oct 01 12:51:20 2013 +0300 +++ b/oculus1.vcproj Wed Oct 02 04:09:37 2013 +0300 @@ -553,6 +553,22 @@ + + + + + + + + diff -r ff3bfd4da86b -r ef4c9d8eeca7 src/main.cc --- a/src/main.cc Tue Oct 01 12:51:20 2013 +0300 +++ b/src/main.cc Wed Oct 02 04:09:37 2013 +0300 @@ -515,6 +515,13 @@ case 'f': toggle_fullscreen(); break; + + case '\\': + { + extern bool dbg_enable; + dbg_enable = !dbg_enable; + } + break; } keystate[key] = true; diff -r ff3bfd4da86b -r ef4c9d8eeca7 src/vr.cc --- a/src/vr.cc Tue Oct 01 12:51:20 2013 +0300 +++ b/src/vr.cc Wed Oct 02 04:09:37 2013 +0300 @@ -10,13 +10,40 @@ #include #endif +#define USUB 28 +#define VSUB 40 + +/* these are just used for the shaderless precomputed distortion method */ +struct Mesh { + int prim; + int num_verts, num_faces; + unsigned int vbo; + unsigned int ibo; +}; +struct Vertex { + float x, y, z; + float tx, ty; +}; + + static void init_ctx(); static bool init_ovr(); static bool init_sdr(); +static Mesh gen_view_mesh(int usub, int vsub, float aspect, float lens_center_offset, + float scale, const float *dist_factors, float tex_scale_x, float tex_scale_y); +static void distort_texcoords(float *tc, float aspect, float lens_center_offset, float scale, const float *dist_factors); +static float barrel_scale(float rad, const float *k); + VRContext vr_ctx; static unsigned int sdrprog; +static Mesh wrapmesh[2]; +static bool mesh_valid; + +bool dbg_enable; + + extern "C" int vr_init(enum vr_init_mode mode) { glewInit(); @@ -338,49 +365,204 @@ {-1, -1, 0, 1}, {0, -1, 1, 1} }; + static const float quad_trans[3] = {0, -1, 1}; + static const float quad_scale[3] = {1, 0.5, 0.5}; static const float offs_scale[3] = {0.0, -1.0, 1.0}; + static int prev_tex_scale_x, prev_tex_scale_y; glPushAttrib(GL_ENABLE_BIT); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); - glEnable(GL_TEXTURE_2D); + glDisable(GL_CULL_FACE); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); + if(!dbg_enable) { + glUseProgram(sdrprog); - glUseProgram(sdrprog); + if(sdrprog) { + int loc; + if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) { + float offset = vr_ctx.info.lens_center_offset * offs_scale[eye]; + glUniform1f(loc, offset); + } - if(sdrprog) { - int loc; - if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) { - float offset = vr_ctx.info.lens_center_offset * offs_scale[eye]; - glUniform1f(loc, offset); + if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) { + glUniform2f(loc, tex_scale_x, tex_scale_y); + } } - if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) { - glUniform2f(loc, tex_scale_x, tex_scale_y); + glBindTexture(GL_TEXTURE_2D, tex); + glBegin(GL_QUADS); + glColor4f(1, 1, 1, 1); + glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]); + glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]); + glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]); + glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]); + glEnd(); + + glUseProgram(0); + + } else { + + if(!mesh_valid || tex_scale_x != prev_tex_scale_x || tex_scale_y != prev_tex_scale_y) { + for(int i=0; i<2; i++) { + int eye = i + VR_EYE_LEFT; + + if(wrapmesh[i].vbo) { + glDeleteBuffers(1, &wrapmesh[i].vbo); + } + if(wrapmesh[i].ibo) { + glDeleteBuffers(1, &wrapmesh[i].ibo); + } + + float aspect = vr_ctx.info.aspect / 2.0; + float offset = vr_ctx.info.lens_center_offset * offs_scale[eye]; + wrapmesh[i] = gen_view_mesh(USUB, VSUB, aspect, offset, vr_ctx.info.scale, vr_ctx.info.distort, + tex_scale_x, tex_scale_y); + } + mesh_valid = true; + prev_tex_scale_x = tex_scale_x; + prev_tex_scale_y = tex_scale_y; } + + glScalef(quad_scale[eye], 1.0, 1.0); + glTranslatef(quad_trans[eye], 0, 0); + + glUseProgram(0); + glBindTexture(GL_TEXTURE_2D, tex); + glEnable(GL_TEXTURE_2D); + + glColor3f(1, 1, 1); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + int meshidx = eye - VR_EYE_LEFT; + glBindBuffer(GL_ARRAY_BUFFER, wrapmesh[meshidx].vbo); + glVertexPointer(3, GL_FLOAT, sizeof(Vertex), 0); + glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, tx)); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wrapmesh[meshidx].ibo); + glDrawElements(GL_TRIANGLES, wrapmesh[meshidx].num_faces * 3, GL_UNSIGNED_INT, 0); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); } - glBindTexture(GL_TEXTURE_2D, tex); - glBegin(GL_QUADS); - glColor4f(1, 1, 1, 1); - glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]); - glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]); - glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]); - glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]); - glEnd(); - - glUseProgram(0); - + glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glPopAttrib(); } + +static Mesh gen_view_mesh(int usub, int vsub, float aspect, float lens_center_offset, + float scale, const float *dist_factors, float tex_scale_x, float tex_scale_y) +{ + int uverts = usub + 1; + int vverts = vsub + 1; + + int num_verts = uverts * vverts; + int num_quads = usub * vsub; + int num_tris = num_quads * 2; + + Vertex *varr = new Vertex[num_verts]; + unsigned int *iarr = new unsigned int[num_tris * 3]; + + float du = 1.0 / (float)usub; + float dv = 1.0 / (float)vsub; + + Vertex *vptr = varr; + for(int i=0; ix = x; + vptr->y = y; + vptr->z = 0; + vptr->tx = tc[0] * tex_scale_x; + vptr->ty = tc[1] * tex_scale_y; + vptr++; + } + } + + unsigned int *iptr = iarr; + for(int i=0; i [-1, 1] + float ptx = tc[0] * 2.0 - 1.0; + float pty = tc[1] * 2.0 - 1.0; + + ptx += lens_center_offset * 2.0; + pty /= aspect; // correct for aspect ratio + + float rad = barrel_scale(ptx * ptx + pty * pty, dist_factors); + ptx *= rad; // scale the point by the computer distortion radius + pty *= rad; + + ptx /= scale; + pty /= scale; + + pty *= aspect; + ptx -= lens_center_offset * 2.0; + + // map back to range [0, 1] + tc[0] = ptx * 0.5 + 0.5; + tc[1] = pty * 0.5 + 0.5; +} + +static float barrel_scale(float rad, const float *k) +{ + float radsq = rad * rad; + float radquad = radsq * radsq; + return k[0] + k[1] * radsq + k[2] * radquad + k[3] * radquad * radsq; +}