248 lines
6.4 KiB
C
248 lines
6.4 KiB
C
#include "frame.h"
|
|
|
|
#include "lvrc_internal.h"
|
|
#include "instance.h"
|
|
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
|
|
#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;
|
|
}
|