Files
Linux-VR-Compositor-Dev/src/frame.c
2018-09-18 20:41:33 +02:00

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;
}