# HG changeset patch # User John Tsiombikas # Date 1379661269 -10800 # Node ID d797639e0234368668f9db6dc8febecbf4b2756c # Parent 39ec672a51583c40d85dc2e7a371c6f480fcaadb moving on to the distortion... not correct yet diff -r 39ec672a5158 -r d797639e0234 src/main.cc --- a/src/main.cc Fri Sep 20 07:00:18 2013 +0300 +++ b/src/main.cc Fri Sep 20 10:14:29 2013 +0300 @@ -10,6 +10,8 @@ static void cleanup(); static void disp(); static void draw_scene(); +static void draw_teapot(); +static void draw_grid(float size, float spacing); static void idle(); static void reshape(int x, int y); static void keyb(unsigned char key, int x, int y); @@ -27,6 +29,9 @@ static bool keystate[256]; +static int rtarg_width, rtarg_height; +static unsigned int fbo, tex[2], zbuf; + int main(int argc, char **argv) { @@ -37,8 +42,11 @@ return 1; } - glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE); - glutCreateWindow("oculus test 01"); + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); + glutCreateWindow("oculus vr test 01"); + + width = glutGet(GLUT_WINDOW_WIDTH); + height = glutGet(GLUT_WINDOW_HEIGHT); glutDisplayFunc(disp); glutIdleFunc(idle); @@ -62,10 +70,6 @@ { glewInit(); // this must be first - if(GLEW_ARB_multisample) { - glEnable(GL_MULTISAMPLE); - } - glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_CULL_FACE); @@ -76,14 +80,59 @@ // y = height of neck cam.input_move(0, 1.65, 0); - if(vr_init(VR_INIT_OCULUS) == -1) { - return false; + if(use_vr) { + if(vr_init(VR_INIT_OCULUS) == -1) { + return false; + } + + // reshape to the size of the VR display + int xsz = vr_get_width(); + int ysz = vr_get_height(); + + glutReshapeWindow(xsz, ysz); + + rtarg_width = (xsz + xsz / 2) / 2; + rtarg_height = ysz + ysz / 2; + } else { + rtarg_width = width; + rtarg_height = height; } + + // create render targets for each eye + GLenum wrap_mode = GL_CLAMP_TO_EDGE; + if(!GLEW_SGIS_texture_edge_clamp) { + wrap_mode = GL_CLAMP; + } + + glGenTextures(2, tex); + for(int i=0; i<2; i++) { + glBindTexture(GL_TEXTURE_2D, tex[i]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, rtarg_width, rtarg_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0); + } + + // create the depth render buffer + glGenRenderbuffers(1, &zbuf); + glBindRenderbuffer(GL_RENDERBUFFER, zbuf); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, rtarg_width, rtarg_height); + + // create the FBO + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, zbuf); + return true; } static void cleanup() { + glDeleteTextures(2, tex); + glDeleteRenderbuffers(1, &zbuf); + glDeleteFramebuffers(1, &fbo); vr_shutdown(); } @@ -91,24 +140,75 @@ { unsigned int msec = glutGet(GLUT_ELAPSED_TIME); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + cam.track_vr(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - gluPerspective(45.0, (float)width / (float)height, 0.5, 500.0); + gluPerspective(RAD_TO_DEG(vr_get_fov()), (float)rtarg_width / (float)rtarg_height, 0.5, 500.0); + + glViewport(0, 0, rtarg_width, rtarg_height); + + glClearColor(0.1, 0.1, 0.1, 1.0); + + // draw left view + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[0], 0); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); + cam.use_inverse(); + glTranslatef(0.32, 0, 0); + draw_scene(); - cam.track_vr(); + + // draw right view + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex[1], 0); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); cam.use_inverse(); + glTranslatef(-0.32, 0, 0); + draw_scene(); - draw_scene(); + // return to the regular window framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, width, height); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + + vr_draw_eye(tex[0], VR_EYE_LEFT); + vr_draw_eye(tex[1], VR_EYE_RIGHT); glutSwapBuffers(); assert(glGetError() == GL_NO_ERROR); } + +static void draw_scene() +{ + float lpos[] = {0, 60, 0, 1}; + glLightfv(GL_LIGHT0, GL_POSITION, lpos); + + static Vector2 teapos[] = { + Vector2(-8, 8), Vector2(8, 8), Vector2(8, -8), Vector2(-8, -8) + }; + + for(int i=0; i<4; i++) { + glPushMatrix(); + glTranslatef(teapos[i].x, 0, teapos[i].y); + draw_teapot(); + glPopMatrix(); + } + + draw_grid(100.0, 2.5); +} + static void draw_teapot() { static int tealist; @@ -125,7 +225,7 @@ glFrontFace(GL_CCW); } -void draw_grid(float size, float spacing) +static void draw_grid(float size, float spacing) { int num_lines = size / spacing; float dist = size / 2.0; @@ -164,26 +264,6 @@ glPopAttrib(); } - -static void draw_scene() -{ - float lpos[] = {0, 60, 0, 1}; - glLightfv(GL_LIGHT0, GL_POSITION, lpos); - - static Vector2 teapos[] = { - Vector2(-8, 8), Vector2(8, 8), Vector2(8, -8), Vector2(-8, -8) - }; - - for(int i=0; i<4; i++) { - glPushMatrix(); - glTranslatef(teapos[i].x, 0, teapos[i].y); - draw_teapot(); - glPopMatrix(); - } - - draw_grid(100.0, 2.5); -} - static void idle() { glutPostRedisplay(); @@ -194,6 +274,11 @@ { width = x; height = y; + + if(!use_vr) { + rtarg_width = width; + rtarg_height = height; + } } static void keyb(unsigned char key, int x, int y) @@ -213,6 +298,24 @@ glutSetCursor(GLUT_CURSOR_INHERIT); } break; + + case 'f': + { + static bool fullscreen; + static int prev_xsz, prev_ysz; + + fullscreen = !fullscreen; + + if(fullscreen) { + prev_xsz = width; + prev_ysz = height; + glutFullScreen(); + } else { + glutReshapeWindow(prev_xsz, prev_ysz); + } + glutPostRedisplay(); + } + break; } keystate[key] = true; diff -r 39ec672a5158 -r d797639e0234 src/vr.cc --- a/src/vr.cc Fri Sep 20 07:00:18 2013 +0300 +++ b/src/vr.cc Fri Sep 20 10:14:29 2013 +0300 @@ -1,16 +1,51 @@ #include +#include #include "vr.h" #include "vr_impl.h" +static const char *sdr_src = + "uniform sampler2D tex;\n" + "uniform vec2 lens_center;\n" + "uniform vec2 scr_center;\n" + "uniform vec2 scale;\n" + "uniform vec2 scale_in;\n" + "uniform vec4 warp_param;\n" + "\n" + "vec2 warp(in vec2 pt)\n" + "{\n" + " vec2 theta = (pt - lens_center) * scale_in;\n" + " float rsq = length(theta);\n" + " vec2 rvec = theta * (warp_param.x + warp_param.y * rsq +\n" + " warp_param.z * rsq * rsq +\n" + " warp_param.w * rsq * rsq * rsq);\n" + " return lens_center + scale * rvec;\n" + "}\n" + "\n" + "void main()\n" + "{\n" + " vec2 tc = warp(gl_TexCoord[0].xy);\n" + " gl_FragColor.rgb = texture2D(tex, tc).rgb;\n" + " gl_FragColor.a = 1.0;\n" + "}\n"; + static bool init_ovr(); +static bool init_sdr(); VRContext vr_ctx; +static unsigned int sdrprog; extern "C" int vr_init(enum vr_init_mode mode) { + glewInit(); + if(!init_ovr()) { return -1; } + + if(!init_sdr()) { + return -1; + } + return 0; } @@ -70,6 +105,8 @@ for(int i=0; i<4; i++) { vr_ctx.info.distort[i] = info.DistortionK[i]; } + + vr_ctx.info.lens_center = info.LensSeparationDistance / info.HScreenSize; } // get the sensor device @@ -95,6 +132,55 @@ return true; } +static bool init_sdr() +{ + int status; + + unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(sdr, 1, &sdr_src, 0); + glCompileShader(sdr); + glGetShaderiv(sdr, GL_COMPILE_STATUS, &status); + if(!status) { + fprintf(stderr, "failed to compile distortion shader\n"); + return false; + } + + sdrprog = glCreateProgram(); + glAttachShader(sdrprog, sdr); + glLinkProgram(sdrprog); + if(!status) { + fprintf(stderr, "failed to link distortion shader program\n"); + glDeleteShader(sdr); + return false; + } + + int loc; + + glUseProgram(sdrprog); + + if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) { + glUniform1i(loc, 0); + } + if((loc = glGetUniformLocation(sdrprog, "lens_center")) != -1) { + glUniform2f(loc, 0.5, 0.5); + } + if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) { + glUniform2f(loc, 0, 0); + } + if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) { + glUniform2f(loc, 1, 1); + } + if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) { + glUniform2f(loc, 1, 1); + } + if((loc = glGetUniformLocation(sdrprog, "warp_param")) != -1) { + glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1], + vr_ctx.info.distort[2], vr_ctx.info.distort[3]); + } + + return true; +} + extern "C" int vr_get_width(void) { return vr_ctx.info.width; @@ -165,3 +251,52 @@ Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation(); oq.GetEulerAngles(euler + 1, euler, euler + 2); } + +extern "C" void vr_draw_eye(unsigned int tex, int eye) +{ + static const float rects[3][4] = { + {-1, -1, 1, 1}, + {-1, -1, 0, 1}, + {0, -1, 1, 1} + }; + static const float offs_scale[3] = {0.0, -1.0, 1.0}; + + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glEnable(GL_TEXTURE_2D); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glUseProgram(sdrprog); + + int loc; + if((loc = glGetUniformLocation(sdrprog, "lens_center")) != -1) { + float lens_center = 0.5 - vr_ctx.info.lens_center * offs_scale[eye]; + glUniform2f(loc, lens_center, 0.5); + printf("lens_center = %f\n", lens_center); + } + + 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); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glPopAttrib(); +} diff -r 39ec672a5158 -r d797639e0234 src/vr.h --- a/src/vr.h Fri Sep 20 07:00:18 2013 +0300 +++ b/src/vr.h Fri Sep 20 10:14:29 2013 +0300 @@ -22,6 +22,9 @@ int vr_init(enum vr_init_mode mode); void vr_shutdown(void); +int vr_get_width(void); +int vr_get_height(void); + float vr_get_fov(void); float vr_get_aspect(void); diff -r 39ec672a5158 -r d797639e0234 src/vr_impl.h --- a/src/vr_impl.h Fri Sep 20 07:00:18 2013 +0300 +++ b/src/vr_impl.h Fri Sep 20 10:14:29 2013 +0300 @@ -19,9 +19,13 @@ float aspect; float ipd; float distort[4]; + // the right lens center offset (negate for left) + float lens_center; } info; }; extern VRContext vr_ctx; +bool vr_gl_init(); + #endif // VR_IMPL_H_