#include "frame.h" #include "lvrc_internal.h" #include "instance.h" #include #include #define USE_ES_SHADERS 0 static const GLfloat textureVertices[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f }; static GLuint shader = 0; static float left_lens_center[2]; static float right_lens_center[2]; // ------------------------------------------------------------------- // from OpenHMD static void compile_shader_src(GLuint shader, const char* src) { glShaderSource(shader, 1, &src, NULL); glCompileShader(shader); GLint status; GLint length; char log[4096] = {0}; glGetShaderiv(shader, GL_COMPILE_STATUS, &status); glGetShaderInfoLog(shader, 4096, &length, log); if(status == GL_FALSE){ printf("compile failed %s\n", log); } } static GLuint compile_shader(const char* vertex, const char* fragment) { // Create the handels GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); GLuint programShader = glCreateProgram(); // Attach the shaders to a program handel. glAttachShader(programShader, vertexShader); glAttachShader(programShader, fragmentShader); // Load and compile the Vertex Shader compile_shader_src(vertexShader, vertex); // Load and compile the Fragment Shader compile_shader_src(fragmentShader, fragment); // The shader objects are not needed any more, // the programShader is the complete shader to be used. glDeleteShader(vertexShader); glDeleteShader(fragmentShader); glLinkProgram(programShader); GLint status; GLint length; char log[4096] = {0}; glGetProgramiv(programShader, GL_LINK_STATUS, &status); glGetProgramInfoLog(programShader, 4096, &length, log); if(status == GL_FALSE){ printf("link failed %s\n", log); } return programShader; } // ------------------------------------------------------------------- bool lvrcInitFrameResources(struct lvrcInstance * instance) { Instance * internalState = (Instance*)instance; if (!internalState->swapChain) { return false; } ohmd_device * hmd = internalState->device; float viewport_scale[2]; float distortion_coeffs[4]; float aberr_scale[3]; float sep; //viewport is half the screen ohmd_device_getf(hmd, OHMD_SCREEN_HORIZONTAL_SIZE, &(viewport_scale[0])); viewport_scale[0] /= 2.0f; ohmd_device_getf(hmd, OHMD_SCREEN_VERTICAL_SIZE, &(viewport_scale[1])); //distortion coefficients ohmd_device_getf(hmd, OHMD_UNIVERSAL_DISTORTION_K, &(distortion_coeffs[0])); ohmd_device_getf(hmd, OHMD_UNIVERSAL_ABERRATION_K, &(aberr_scale[0])); //calculate lens centers (assuming the eye separation is the distance between the lens centers) ohmd_device_getf(hmd, OHMD_LENS_HORIZONTAL_SEPARATION, &sep); ohmd_device_getf(hmd, OHMD_LENS_VERTICAL_POSITION, &(left_lens_center[1])); ohmd_device_getf(hmd, OHMD_LENS_VERTICAL_POSITION, &(right_lens_center[1])); left_lens_center[0] = viewport_scale[0] - sep/2.0f; right_lens_center[0] = sep/2.0f; //assume calibration was for lens view to which ever edge of screen is further away from lens center float warp_scale = (left_lens_center[0] > right_lens_center[0]) ? left_lens_center[0] : right_lens_center[0]; //float warp_scale = 0.305f; // test float warp_adj = 1.0f; #if USE_ES_SHADERS const char* vertex; ohmd_gets(OHMD_GLSL_ES_DISTORTION_VERT_SRC, &vertex); const char* fragment; ohmd_gets(OHMD_GLSL_ES_DISTORTION_FRAG_SRC, &fragment); #else const char* vertex; ohmd_gets(OHMD_GLSL_DISTORTION_VERT_SRC, &vertex); const char* fragment; ohmd_gets(OHMD_GLSL_DISTORTION_FRAG_SRC, &fragment); #endif // shader = compile_shader(vertex, fragment); assert(GL_NO_ERROR == glGetError()); glUseProgram(shader); assert(GL_NO_ERROR == glGetError()); glUniform1i(glGetUniformLocation(shader, "warpTexture"), 0); assert(GL_NO_ERROR == glGetError()); glUniform2fv(glGetUniformLocation(shader, "ViewportScale"), 1, viewport_scale); assert(GL_NO_ERROR == glGetError()); glUniform3fv(glGetUniformLocation(shader, "aberr"), 1, aberr_scale); assert(GL_NO_ERROR == glGetError()); glUniform1f(glGetUniformLocation(shader, "WarpScale"), warp_scale*warp_adj); assert(GL_NO_ERROR == glGetError()); glUniform4fv(glGetUniformLocation(shader, "HmdWarpParam"), 1, distortion_coeffs); assert(GL_NO_ERROR == glGetError()); float mvp [16] = { 2.0f, 0.0f, 0.0f, -1.0f, /* | */ 0.0f, 2.0f, 0.0f, -1.0f, /* | */ 0.0f, 0.0f, 1.0f, 0.0f, /* | */ 0.0f, 0.0f, 0.0f, 1.0f }; glUniformMatrix4fv(glGetUniformLocation(shader, "mvp"), 1, GL_TRUE, mvp); assert(GL_NO_ERROR == glGetError()); glUseProgram(0); return true; } bool lvrcReleaseFrameResources(struct lvrcInstance * state) { // TODO return true; } bool lvrcBeginFrame(struct lvrcInstance * state) { return true; // nothing yet } static void prepare(GLuint texture) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); assert(GL_NO_ERROR == glGetError()); glUseProgram(shader); } static void draw() { #if USE_ES_SHADERS glVertexAttribPointer(glGetAttribLocation(shader, "coords"), 2, GL_FLOAT, 0, 0, textureVertices); glEnableVertexAttribArray(glGetAttribLocation(shader, "coords")); assert(GL_NO_ERROR == glGetError()); #endif // USE_ES_SHADERS glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); assert(GL_NO_ERROR == glGetError()); } bool lvrcSubmitFrameLeft(struct lvrcInstance * instance, GLuint texture) { Instance * internalInstance = (Instance*)instance; if (!internalInstance->swapChain) { return false; } unsigned int hmd_w = internalInstance->swapChain->mode->hdisplay; unsigned int hmd_h = internalInstance->swapChain->mode->vdisplay; prepare(texture); glViewport(0, 0, hmd_w/2, hmd_h); glUniform2fv(glGetUniformLocation(shader, "LensCenter"), 1, left_lens_center); assert(GL_NO_ERROR == glGetError()); draw(); return true; } bool lvrcSubmitFrameRight(struct lvrcInstance * instance, GLuint texture) { Instance * internalInstance = (Instance*)instance; if (!internalInstance->swapChain) { return false; } unsigned int hmd_w = internalInstance->swapChain->mode->hdisplay; unsigned int hmd_h = internalInstance->swapChain->mode->vdisplay; prepare(texture); glViewport(hmd_w/2, 0, hmd_w/2, hmd_h); glUniform2fv(glGetUniformLocation(shader, "LensCenter"), 1, right_lens_center); assert(GL_NO_ERROR == glGetError()); draw(); return true; } bool lvrcEndFrame(struct lvrcInstance * instance) { Instance * internalInstance = (Instance*)instance; if (!internalInstance->swapChain) { return false; } SwapBuffers(internalInstance->swapChain); return true; }