mirror of https://github.com/bjornbytes/lovr.git
Basic VR rendering;
This commit is contained in:
parent
4cd0bf06c8
commit
98994d52fb
18
src/glfw.c
18
src/glfw.c
|
@ -14,22 +14,9 @@ void initGlfw(GLFWerrorfun onError, GLFWwindowclosefun onClose) {
|
|||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
glfwWindowHint(GLFW_SAMPLES, 4);
|
||||
//glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
|
||||
int count;
|
||||
GLFWmonitor** monitors = glfwGetMonitors(&count);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
const GLFWvidmode* mode = glfwGetVideoMode(monitors[i]);
|
||||
if (mode->refreshRate == 90) {
|
||||
glfwWindowHint(GLFW_RED_BITS, mode->redBits);
|
||||
glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
|
||||
glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
|
||||
glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
|
||||
window = glfwCreateWindow(mode->width, mode->height, "Window", monitors[i], NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
window = glfwCreateWindow(800, 600, "Window", NULL, NULL);
|
||||
|
||||
if (!window) {
|
||||
glfwTerminate();
|
||||
|
@ -50,6 +37,7 @@ void initGlfw(GLFWerrorfun onError, GLFWwindowclosefun onClose) {
|
|||
#endif
|
||||
|
||||
glfwSetTime(0);
|
||||
glfwSwapInterval(0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,13 @@
|
|||
#include <assimp/cimport.h>
|
||||
#include <assimp/scene.h>
|
||||
#include <assimp/postprocess.h>
|
||||
#include "../headset/headset.h"
|
||||
|
||||
typedef struct {
|
||||
Shader* activeShader;
|
||||
} GraphicsState;
|
||||
|
||||
static GraphicsState graphicsState;
|
||||
|
||||
void lovrGraphicsInit() {
|
||||
map_init(&BufferDrawModes);
|
||||
|
@ -38,8 +45,13 @@ void lovrGraphicsSetClearColor(float r, float g, float b, float a) {
|
|||
glClearColor(r / 255, g / 255, b / 255, a / 255);
|
||||
}
|
||||
|
||||
Shader* lovrGraphicsGetShader() {
|
||||
return graphicsState.activeShader;
|
||||
}
|
||||
|
||||
// TODO default shader
|
||||
void lovrGraphicsSetShader(Shader* shader) {
|
||||
graphicsState.activeShader = shader;
|
||||
glUseProgram(shader->id);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ void lovrGraphicsClear();
|
|||
void lovrGraphicsPresent();
|
||||
void lovrGraphicsGetClearColor(float* r, float* g, float* b, float* a);
|
||||
void lovrGraphicsSetClearColor(float r, float g, float b, float a);
|
||||
Shader* lovrGraphicsGetShader();
|
||||
void lovrGraphicsSetShader(Shader* shader);
|
||||
Buffer* lovrGraphicsNewBuffer(int size);
|
||||
Model* lovrGraphicsNewModel(const char* path);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
const char* lovrShaderVertexPrefix = ""
|
||||
"#version 150 \n"
|
||||
"uniform mat4 lovrTransform;"
|
||||
"in vec3 position;"
|
||||
"";
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "headset.h"
|
||||
#include "../util.h"
|
||||
#include "../glfw.h"
|
||||
#include "../graphics/graphics.h"
|
||||
typedef char bool;
|
||||
#include <openvr_capi.h>
|
||||
#include <stdio.h>
|
||||
|
@ -11,11 +12,18 @@ extern __declspec(dllimport) intptr_t VR_InitInternal(EVRInitError *peError, EVR
|
|||
extern __declspec(dllimport) bool VR_IsInterfaceVersionValid(const char *pchInterfaceVersion);
|
||||
extern __declspec(dllimport) intptr_t VR_GetGenericInterface(const char *pchInterfaceVersion, EVRInitError *peError);
|
||||
|
||||
#define DEVICE_COUNT 16
|
||||
|
||||
typedef struct {
|
||||
struct VR_IVRSystem_FnTable* vrSystem;
|
||||
GLuint framebuffers[2];
|
||||
GLuint renderbuffers[2];
|
||||
GLuint textures[2];
|
||||
struct VR_IVRCompositor_FnTable* vrCompositor;
|
||||
|
||||
GLuint framebuffer;
|
||||
GLuint depthbuffer;
|
||||
GLuint colorTexture;
|
||||
|
||||
uint32_t renderWidth;
|
||||
uint32_t renderHeight;
|
||||
} HeadsetState;
|
||||
|
||||
static HeadsetState headsetState;
|
||||
|
@ -41,29 +49,51 @@ void lovrHeadsetInit() {
|
|||
}
|
||||
|
||||
char fnTableName[128];
|
||||
|
||||
sprintf(fnTableName, "FnTable:%s", IVRSystem_Version);
|
||||
headsetState.vrSystem = (struct VR_IVRSystem_FnTable*) VR_GetGenericInterface(fnTableName, &vrError);
|
||||
if (vrError != EVRInitError_VRInitError_None || headsetState.vrSystem == NULL) {
|
||||
error("Problem initializing OpenVR");
|
||||
error("Problem initializing VRSystem");
|
||||
return;
|
||||
}
|
||||
|
||||
glGenFramebuffers(2, headsetState.framebuffers);
|
||||
glGenRenderbuffers(2, headsetState.renderbuffers);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, headsetState.framebuffers[i]);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, headsetState.framebuffers[i]);
|
||||
sprintf(fnTableName, "FnTable:%s", IVRCompositor_Version);
|
||||
headsetState.vrCompositor = (struct VR_IVRCompositor_FnTable*) VR_GetGenericInterface(fnTableName, &vrError);
|
||||
if (vrError != EVRInitError_VRInitError_None || headsetState.vrCompositor == NULL) {
|
||||
error("Problem initializing VRCompositor");
|
||||
return;
|
||||
}
|
||||
|
||||
headsetState.vrSystem->GetRecommendedRenderTargetSize(&headsetState.renderWidth, &headsetState.renderHeight);
|
||||
|
||||
glGenTextures(1, &headsetState.colorTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, headsetState.colorTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, headsetState.renderWidth, headsetState.renderHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
glGenFramebuffers(1, &headsetState.framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, headsetState.framebuffer);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, headsetState.colorTexture, 0);
|
||||
|
||||
glGenRenderbuffers(1, &headsetState.depthbuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, headsetState.depthbuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, headsetState.renderWidth, headsetState.renderHeight);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, headsetState.depthbuffer);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||
error("Framebuffer not complete");
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
}
|
||||
|
||||
void lovrHeadsetGetPosition(float* x, float* y, float* z) {
|
||||
TrackedDevicePose_t poses[16];
|
||||
headsetState.vrSystem->GetDeviceToAbsoluteTrackingPose(ETrackingUniverseOrigin_TrackingUniverseStanding, 0.f, poses, 16);
|
||||
/*TrackedDevicePose_t poses[DEVICE_COUNT];
|
||||
headsetState.vrSystem->GetDeviceToAbsoluteTrackingPose(ETrackingUniverseOrigin_TrackingUniverseStanding, 0.f, poses, DEVICE_COUNT);
|
||||
TrackedDevicePose_t hmdPose = poses[k_unTrackedDeviceIndex_Hmd];
|
||||
*x = hmdPose.mDeviceToAbsoluteTracking.m[2][0];
|
||||
*y = hmdPose.mDeviceToAbsoluteTracking.m[2][1];
|
||||
*z = hmdPose.mDeviceToAbsoluteTracking.m[2][2];
|
||||
*z = hmdPose.mDeviceToAbsoluteTracking.m[2][2];*/
|
||||
}
|
||||
|
||||
void lovrHeadsetGetOrientation(float* w, float* x, float* y, float* z) {
|
||||
|
@ -75,4 +105,67 @@ int lovrHeadsetIsPresent() {
|
|||
}
|
||||
|
||||
void lovrHeadsetRenderTo(headsetRenderCallback callback, void* userdata) {
|
||||
/*float (*m)[4];
|
||||
TrackedDevicePose_t pose;
|
||||
headsetState.vrCompositor->WaitGetPoses(&pose, 1, NULL, 0);
|
||||
|
||||
m = pose.mDeviceToAbsoluteTracking.m;
|
||||
float hmdMatrix[16] = {
|
||||
m[0][0], m[1][0], m[2][0], 0.0,
|
||||
m[0][1], m[1][1], m[2][1], 0.0,
|
||||
m[0][2], m[1][2], m[2][2], 0.0,
|
||||
m[0][3], m[1][3], m[2][3], 1.0
|
||||
};*/
|
||||
|
||||
TrackedDevicePose_t pose;
|
||||
headsetState.vrCompositor->WaitGetPoses(&pose, 1, NULL, 0);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
EVREye eye = (i == 0) ? EVREye_Eye_Left : EVREye_Eye_Right;
|
||||
|
||||
/*m = headsetState.vrSystem->GetEyeToHeadTransform(eye).m;
|
||||
float eyeMatrix[16] = {
|
||||
m[0][0], m[1][0], m[2][0], 0.0,
|
||||
m[0][1], m[1][1], m[2][1], 0.0,
|
||||
m[0][2], m[1][2], m[2][2], 0.0,
|
||||
m[0][3], m[1][3], m[2][3], 1.0
|
||||
};
|
||||
|
||||
m = headsetState.vrSystem->GetProjectionMatrix(eye, 0.1f, 30.0f, EGraphicsAPIConvention_API_OpenGL).m;
|
||||
float lovrTransform[16] = {
|
||||
m[0][0], m[1][0], m[2][0], m[3][0],
|
||||
m[0][1], m[1][1], m[2][1], m[3][1],
|
||||
m[0][2], m[1][2], m[2][2], m[3][2],
|
||||
m[0][3], m[1][3], m[2][3], m[3][3]
|
||||
};
|
||||
|
||||
matrixMultiply(matrixMultiply(lovrTransform, eyeMatrix), hmdMatrix);
|
||||
|
||||
Shader* shader = lovrGraphicsGetShader();
|
||||
int id = lovrShaderGetUniformId(shader, "lovrTransform");
|
||||
lovrShaderSendFloatMat4(shader, id, lovrTransform);
|
||||
glClearColor(0.5f, 0.0f, 0.5f, 1.0f);
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, headsetState.framebuffers[i]);
|
||||
glViewport(0, 0, headsetState.renderWidth, headsetState.renderHeight);
|
||||
lovrGraphicsClear();
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
callback(i, userdata);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glDisable(GL_MULTISAMPLE);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, headsetState.framebuffers[i]);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, headsetState.resolveFramebuffers[i]);
|
||||
glBlitFramebuffer(0, 0, headsetState.renderWidth, headsetState.renderHeight, 0, 0, headsetState.renderWidth, headsetState.renderHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);*/
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, headsetState.framebuffer);
|
||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
Texture_t eyeTexture = { (void*) headsetState.framebuffer, EGraphicsAPIConvention_API_OpenGL, EColorSpace_ColorSpace_Gamma };
|
||||
EVRSubmitFlags flags = EVRSubmitFlags_Submit_Default;
|
||||
headsetState.vrCompositor->Submit(eye, &eyeTexture, NULL, flags);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,4 +6,4 @@ void lovrHeadsetInit();
|
|||
void lovrHeadsetGetPosition(float* x, float* y, float* z);
|
||||
void lovrHeadsetGetOrientation(float* w, float* x, float* y, float* z);
|
||||
int lovrHeadsetIsPresent();
|
||||
void lovrHeadsetRenderTo(headsetRenderCallback callback, void* userdata);
|
||||
void lovrHeadsetRenderTo(headsetRenderCallback callback, void* userdata);
|
||||
|
|
|
@ -59,6 +59,11 @@ int l_lovrGraphicsSetClearColor(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrGraphicsGetShader(lua_State* L) {
|
||||
luax_pushshader(L, lovrGraphicsGetShader());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrGraphicsSetShader(lua_State* L) {
|
||||
Shader* shader = luax_checkshader(L, 1);
|
||||
lovrGraphicsSetShader(shader);
|
||||
|
|
|
@ -8,6 +8,7 @@ int l_lovrGraphicsClear(lua_State* L);
|
|||
int l_lovrGraphicsPresent(lua_State* L);
|
||||
int l_lovrGraphicsGetClearColor(lua_State* L);
|
||||
int l_lovrGraphicsSetClearColor(lua_State* L);
|
||||
int l_lovrGraphicsGetShader(lua_State* L);
|
||||
int l_lovrGraphicsSetShader(lua_State* L);
|
||||
int l_lovrGraphicsNewBuffer(lua_State* L);
|
||||
int l_lovrGraphicsNewModel(lua_State* L);
|
||||
|
|
31
src/util.c
31
src/util.c
|
@ -100,3 +100,34 @@ void luaRegisterType(lua_State* L, const char* name, const luaL_Reg* functions,
|
|||
// Pop metatable
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
float* matrixMultiply(float* a, float* b) {
|
||||
float a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
|
||||
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
|
||||
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
|
||||
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15],
|
||||
|
||||
b00 = b[0], b01 = b[1], b02 = b[2], b03 = b[3],
|
||||
b10 = b[4], b11 = b[5], b12 = b[6], b13 = b[7],
|
||||
b20 = b[8], b21 = b[9], b22 = b[10], b23 = b[11],
|
||||
b30 = b[12], b31 = b[13], b32 = b[14], b33 = b[15];
|
||||
|
||||
a[0] = b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30;
|
||||
a[1] = b00 * a01 + b01 * a11 + b02 * a21 + b03 * a31;
|
||||
a[2] = b00 * a02 + b01 * a12 + b02 * a22 + b03 * a32;
|
||||
a[3] = b00 * a03 + b01 * a13 + b02 * a23 + b03 * a33;
|
||||
a[4] = b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30;
|
||||
a[5] = b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31;
|
||||
a[6] = b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32;
|
||||
a[7] = b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33;
|
||||
a[8] = b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30;
|
||||
a[9] = b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31;
|
||||
a[10] = b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32;
|
||||
a[11] = b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33;
|
||||
a[12] = b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30;
|
||||
a[13] = b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31;
|
||||
a[14] = b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32;
|
||||
a[15] = b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -8,3 +8,4 @@ char* loadFile(char* filename);
|
|||
void luaRegisterModule(lua_State* L, const char* name, const luaL_Reg* module);
|
||||
void luaRegisterType(lua_State* L, const char* name, const luaL_Reg* functions, lua_CFunction gc);
|
||||
int luaPreloadModule(lua_State* L, const char* key, lua_CFunction f);
|
||||
float* matrixMultiply(float* a, float* b);
|
||||
|
|
Loading…
Reference in New Issue