First development release - WIP
This commit is contained in:
243
src/frame.c
Normal file
243
src/frame.c
Normal file
@@ -0,0 +1,243 @@
|
||||
#include "frame.h"
|
||||
|
||||
#include "lvrc_internal.h"
|
||||
#include "instance.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
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 0
|
||||
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()
|
||||
{
|
||||
glVertexAttribPointer(glGetAttribLocation(shader, "coords"), 2, GL_FLOAT, 0, 0, textureVertices);
|
||||
glEnableVertexAttribArray(glGetAttribLocation(shader, "coords"));
|
||||
assert(GL_NO_ERROR == glGetError());
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user