cancel
Showing results for 
Search instead for 
Did you mean: 

Complete "Extended" Mode Modern OpenGL Example (SDK 0.4.3)

tmason101
Level 2
Hello,

Thanks to all of the help from the various posters (jherico and nuclear especially) here is a complete "Extended" mode example of using the latest version of the SDK (0.4.3) with Modern OpenGL.

Dependencies:



Tested on Windows but all dependencies and code is cross-platform as far as I can see.

I am sure experts on here can cut this code apart and make it far more efficient but I thought I would give back to those who need help getting started.

Hope someone can figure out why my code below doesn't work in "Direct" mode! But that is for other threads...


Main.h


#ifndef MAIN_H_
#define MAIN_H_

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include <array>

#ifndef OPENGL_INCLUDES_
#define OPENGL_INCLUDES_

#include "GL\glew.h"

#ifndef GLFW_INCLUDES_
#define GLFW_INCLUDES_

#if defined(_WIN32)
#include <Windows.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#define GLFW_EXPOSE_NATIVE_WGL
#elif defined(__linux__)
#include <X11/X.h>
#include <X11/extensions/Xrandr.h>
#define GLFW_EXPOSE_NATIVE_X11
#define GLFW_EXPOSE_NATIVE_GLX
#endif

#include "GLFW\glfw3.h"
#include "GLFW\glfw3native.h"

#endif

#ifndef GLM_INCLUDES_
#define GLM_INCLUDES_

#include <glm/glm.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>

#endif

#ifndef OCULUS_SDK_
#define OCULUS_SDK_

#define OVR_OS_WIN32

#include "OVR_CAPI_GL.h"
#include "Kernel\OVR_Math.h"

#endif

#endif

GLFWwindow* MainWindow;

#ifdef _WIN32

HWND MainWindowWin32Handle = NULL;

#endif

GLint WindowWidth = 1024;
GLint WindowHeight = 768;
GLfloat AspectRatio;

GLulong SizeDivizor = 1;

GLboolean RiftAvailable = false;
GLboolean DirectMode = false;
GLboolean RotateCubes = true;

GLfloat RotationSpeed = 0.001f;
GLfloat RotationDirection = 1.0f;

ovrHmd Main_HMD = NULL;
ovrEyeRenderDesc Main_EyeRenderDesc[2];
ovrRecti Main_EyeRenderViewport[2];
ovrGLConfig Main_HMD_Render_Config;
ovrGLTexture Main_EyeTexture[2];
OVR::Recti Main_HMD_Pos_Res;
ovrFovPort Main_HMD_eyeFov[2];

GLuint Main_HMD_FrameIndex;

OVR::Sizei recommenedLeftEyeSize;
OVR::Sizei recommenedRightEyeSize;
OVR::Sizei finalTextureSize;

GLuint OculusRiftFrameBufferID;
GLuint OculusRiftRenderBufferID;
GLuint OculusRiftDepthBufferID;
GLuint OculusRiftTextureID;

GLuint MainOpenGLShaderProgramID;
GLuint MatricesUniformBlockID;
GLuint MatricesUniformBufferID;

GLuint LightsUniformBlockID;
GLuint LightsUniformBufferID;

GLuint MaterialsUniformBlockID;
GLuint MaterialsUniformBufferID;

glm::mat4 CenterPositionMatrix;
glm::mat4 EyeOrientationMatrix;
glm::mat4 EyePositionMatrix;
glm::mat4 ViewMatrix;
glm::mat4 ViewModelMatrix;
glm::mat4 ProjectionMatrix;
glm::mat4 MVPMatrix;
glm::mat3 NormalMatrix;

class StandardCube;

std::vector<StandardCube> Cubes;

void (*DrawScene)();

int initializeOculusRift();

int initializeGLFWGLEW();

int prepareOpenGL();

int prepareFrameBuffer();

int prepareOculusRiftWindow();

int configureOculusRift();

int configureOculusRiftTracking();

int loadShaders();

int prepareShaderUniforms();

int loadCubes();

int prepareMatrices();

int SetDrawFunctionPointer();

void DrawWindowed();

void DrawOculusRift();

static void GLFWKeyCallback(GLFWwindow* p_Window, GLint p_Key, GLint p_Scancode, GLint p_Action, GLint p_Mods);

static void GLFWWindowResizeCallBack(GLFWwindow* p_Window, GLint width, GLint height);

static void GLFWMouseMovementCallBack(GLFWwindow* p_Window, GLdouble MouseX, GLdouble MouseY);

static void GLFWFramebufferSizeCallback(GLFWwindow* window, GLint width, GLint height);

static void GLFWErrorCallback(GLint error, const char* description);

int main(int argc, char** argv);

#endif



Main.cpp


#include "Main.h"

class StandardCube {

private:

GLfloat* Vertices;
GLfloat* Normals;
GLuint* Indices;

GLuint VAO;

glm::mat4 ModelMatrix;

public:

void LoadIntoOpenGL() {

Vertices = new GLfloat[72]

{
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, -1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, -1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
1.0f, -1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
-1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, -1.0f
};

Normals = new GLfloat[72] {
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, 1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 0.0f, -1.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f,
-1.0f, 0.0f, 0.0f
};

Indices = new GLuint[36] {0, 1, 2, 2, 3, 0,
4, 5, 6, 6, 7, 4,
8, 9, 10, 10, 11, 8,
12, 13, 14, 14, 15, 12,
16, 17, 18, 18, 19, 16,
20, 21, 22, 22, 23, 20
};

glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);

GLuint MeshBufferID;
glGenBuffers(1, &MeshBufferID);
glBindBuffer(GL_ARRAY_BUFFER, MeshBufferID);

GLuint TotalBufferData = (sizeof(GLfloat) * 72) + (sizeof(GLfloat) * 72);

glBufferData(GL_ARRAY_BUFFER, TotalBufferData, NULL, GL_STATIC_DRAW);

glBufferSubData(GL_ARRAY_BUFFER, NULL, sizeof(GLfloat) * 72, Vertices);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);

glBufferSubData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 72, sizeof(GLfloat) * 72, Normals);

glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(sizeof(GLfloat) * 72));
glEnableVertexAttribArray(1);

GLuint IndexBufferID;
glGenBuffers(1, &IndexBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * 36, Indices, GL_STATIC_DRAW);

glBindVertexArray(NULL);

ModelMatrix = glm::mat4(1.0f);

}

void DrawMe() {

MVPMatrix = ProjectionMatrix * ViewMatrix * ModelMatrix;
ViewModelMatrix = ViewMatrix * ModelMatrix;
NormalMatrix = glm::transpose(glm::inverse(glm::mat3(MVPMatrix)));

glBindBuffer(GL_UNIFORM_BUFFER, MatricesUniformBufferID);

glBufferSubData(GL_UNIFORM_BUFFER, NULL, sizeof(glm::mat4), glm::value_ptr(MVPMatrix));
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(ViewModelMatrix));
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) + sizeof(glm::mat4), sizeof(glm::mat3), glm::value_ptr(NormalMatrix));

glBindBuffer(GL_UNIFORM_BUFFER, NULL);

glBindVertexArray(VAO);
glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_INT, NULL, 1);
glBindVertexArray(NULL);

}

void MoveMe(glm::vec3 NewPosition) {

ModelMatrix = glm::translate(ModelMatrix, NewPosition);

}

void RotateMe(GLfloat AmountToRotateBy) {

ModelMatrix = glm::rotate(ModelMatrix, AmountToRotateBy, glm::vec3(0.0f, 1.0f, 0.0f));

}

};

int initializeOculusRift() {

if (!ovr_Initialize()) {

return EXIT_FAILURE;

}

if (!Main_HMD) {

Main_HMD = ovrHmd_Create(0);

if (!Main_HMD)
{

fprintf(stderr, "Oculus Rift not detected.");
RiftAvailable = false;

}
else {

if (Main_HMD->ProductName[0] == '\0')
{

fprintf(stderr, "Rift detected, display not enabled.");
RiftAvailable = false;

}
else {

DirectMode = (Main_HMD->HmdCaps & ovrHmdCap_ExtendDesktop) ? false : true;

Main_HMD_Pos_Res = OVR::Recti(Main_HMD->WindowsPos, Main_HMD->Resolution);

if (DirectMode) {

SizeDivizor = 1;

}

WindowWidth = Main_HMD_Pos_Res.w / SizeDivizor;
WindowHeight = Main_HMD_Pos_Res.h / SizeDivizor;

RiftAvailable = true;

}

}

}

return EXIT_SUCCESS;

}

int initializeGLFWGLEW() {

MainWindow = NULL;

if (!glfwInit())
{

fprintf(stderr, "GLFW failed to initialize.");
glfwTerminate();
return EXIT_FAILURE;

}

/*

Customize this for the OpenGL version you have on your system.

*/

glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);

/*

End OpenGL context setup.

*/

glfwSetErrorCallback(GLFWErrorCallback);

if (DirectMode) {

MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Oculus Rift Direct Mode Example", NULL, NULL);

}
else {

if (!RiftAvailable) {

MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Simple OpenGL Example", NULL, NULL);

}
else {

GLint MonitorCount;
GLFWmonitor** GLFW_Monitors = glfwGetMonitors(&MonitorCount);
GLFWmonitor* MonitorToUse;

switch (MonitorCount)
{
case 0:
printf("No monitors found, exiting.\n");
return EXIT_FAILURE;
break;
case 1:
printf("Two monitors expected, found only one, using primary...\n");
MonitorToUse = glfwGetPrimaryMonitor();
break;
case 2:
printf("Two monitors found, using second monitor\n");
MonitorToUse = GLFW_Monitors[1];
break;
default:
printf("More than two monitors found, using second monitor\n");
MonitorToUse = GLFW_Monitors[1];
}

MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Oculus Rift Extended Mode Example", MonitorToUse, NULL);

}

}

if (!MainWindow)
{
fprintf(stderr, "Could not determine OpenGL version; exiting.");
glfwTerminate();
return EXIT_FAILURE;
}

glfwMakeContextCurrent(MainWindow);

glewExperimental = GL_TRUE;
GLenum err = glewInit();

if (GLEW_OK != err)
{
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
return EXIT_FAILURE;

}



glfwSetInputMode(MainWindow, GLFW_STICKY_KEYS, GL_TRUE);

glfwSetKeyCallback(MainWindow, GLFWKeyCallback);
glfwSetWindowSizeCallback(MainWindow, GLFWWindowResizeCallBack);
glfwSetCursorPosCallback(MainWindow, GLFWMouseMovementCallBack);
glfwSetFramebufferSizeCallback(MainWindow, GLFWFramebufferSizeCallback);

glfwSwapBuffers(MainWindow);

glfwPollEvents();

return EXIT_SUCCESS;

}

int prepareOpenGL() {

glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_MULTISAMPLE);

return EXIT_SUCCESS;

}

int prepareFrameBuffer() {

if (!RiftAvailable) {

//This process doesn't apply if an Oculus Rift isn't available.

return EXIT_SUCCESS;

}

recommenedLeftEyeSize = ovrHmd_GetFovTextureSize(Main_HMD, ovrEye_Left, Main_HMD->DefaultEyeFov[0], 1.0f);
recommenedRightEyeSize = ovrHmd_GetFovTextureSize(Main_HMD, ovrEye_Right, Main_HMD->DefaultEyeFov[1], 1.0f);

finalTextureSize.w = recommenedLeftEyeSize.w + recommenedRightEyeSize.w;
finalTextureSize.h = std::max(recommenedLeftEyeSize.h, recommenedRightEyeSize.h);

glGenFramebuffers(1, &OculusRiftFrameBufferID);
glBindFramebuffer(GL_FRAMEBUFFER, OculusRiftFrameBufferID);

// The texture we're going to render to...
glGenTextures(1, &OculusRiftTextureID);
// "Bind" the newly created texture : all future texture functions will modify this texture...
glBindTexture(GL_TEXTURE_2D, OculusRiftTextureID);

// Give an empty image to OpenGL (the last "0")
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, finalTextureSize.w, finalTextureSize.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
// Linear filtering...
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

// Create Depth Buffer...
glGenRenderbuffers(1, &OculusRiftDepthBufferID);
glBindRenderbuffer(GL_RENDERBUFFER, OculusRiftDepthBufferID);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, finalTextureSize.w, finalTextureSize.h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, OculusRiftDepthBufferID);

// Set the texture as our colour attachment #0...
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, OculusRiftTextureID, 0);

// Set the list of draw buffers...
GLenum l_GLDrawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
glDrawBuffers(1, l_GLDrawBuffers); // "1" is the size of DrawBuffers

// Check if everything is OK...
GLenum l_Check = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);

if (l_Check != GL_FRAMEBUFFER_COMPLETE)
{
printf("There is a problem with the FBO.\n");
return EXIT_FAILURE;
}

// Unbind...
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

return EXIT_SUCCESS;

}

int prepareFrameBuffer() {

if (!RiftAvailable) {



//This process doesn't apply if an Oculus Rift isn't available.



return EXIT_SUCCESS;

}

recommenedLeftEyeSize = ovrHmd_GetFovTextureSize(Main_HMD, ovrEye_Left, Main_HMD->DefaultEyeFov[0], 1.0f);
recommenedRightEyeSize = ovrHmd_GetFovTextureSize(Main_HMD, ovrEye_Right, Main_HMD->DefaultEyeFov[1], 1.0f);

finalTextureSize.w = recommenedLeftEyeSize.w + recommenedRightEyeSize.w;
finalTextureSize.h = std::max(recommenedLeftEyeSize.h, recommenedRightEyeSize.h);

glGenTextures(1, &OculusRiftTextureID);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, OculusRiftTextureID);

GLint MaximumSamples;
glGetIntegerv(GL_MAX_SAMPLES, &MaximumSamples);

glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, MaximumSamples,
GL_RGBA, finalTextureSize.w, finalTextureSize.h, false);

glGenFramebuffers(1, &OculusRiftFrameBufferID);
glBindFramebuffer(GL_FRAMEBUFFER, OculusRiftFrameBufferID);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, OculusRiftTextureID, 0);

glGenRenderbuffers(1, &OculusRiftRenderBufferID);
glBindRenderbuffer(GL_RENDERBUFFER, OculusRiftRenderBufferID);

glRenderbufferStorageMultisample(GL_RENDERBUFFER, MaximumSamples,
GL_RGBA, finalTextureSize.w, finalTextureSize.h);

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, OculusRiftRenderBufferID);

glGenRenderbuffers(1, &OculusRiftDepthBufferID);
glBindRenderbuffer(GL_RENDERBUFFER, OculusRiftDepthBufferID);

glRenderbufferStorageMultisample(GL_RENDERBUFFER, MaximumSamples,
GL_DEPTH24_STENCIL8, finalTextureSize.w, finalTextureSize.h);

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, OculusRiftDepthBufferID);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, OculusRiftDepthBufferID);

GLenum DrawBufferStatusCheck_ENUM = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);

if (DrawBufferStatusCheck_ENUM != GL_FRAMEBUFFER_COMPLETE) {
switch (DrawBufferStatusCheck_ENUM)
{
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
break;
case GL_FRAMEBUFFER_UNSUPPORTED:
break;
default:
break;
}

glBindRenderbuffer(GL_RENDERBUFFER, NULL);
glBindTexture(GL_TEXTURE_2D, NULL);
glBindFramebuffer(GL_FRAMEBUFFER, NULL);
return EXIT_FAILURE;

}
else {

glBindRenderbuffer(GL_RENDERBUFFER, NULL);
glBindTexture(GL_TEXTURE_2D, NULL);
glBindFramebuffer(GL_FRAMEBUFFER, NULL);
return EXIT_SUCCESS;

}

}

*/

int prepareOculusRiftWindow() {

if (!RiftAvailable) {

//This process doesn't apply if an Oculus Rift isn't available.

return EXIT_SUCCESS;

}

#ifdef _WIN32

if (RiftAvailable) {

MainWindowWin32Handle = glfwGetWin32Window(MainWindow);

if (DirectMode) {

ovrHmd_AttachToWindow(Main_HMD, MainWindowWin32Handle, NULL, NULL);

}

return EXIT_SUCCESS;

}
else {

return EXIT_FAILURE;

}

#endif

}

int configureOculusRift() {

if (!RiftAvailable) {

return EXIT_SUCCESS;

}

Main_HMD_eyeFov[ovrEye_Left] = Main_HMD->DefaultEyeFov[ovrEye_Left];
Main_HMD_eyeFov[ovrEye_Right] = Main_HMD->DefaultEyeFov[ovrEye_Right];

Main_HMD_Render_Config.OGL.Window = MainWindowWin32Handle;

HDC MainHDC = GetDC(Main_HMD_Render_Config.OGL.Window);
Main_HMD_Render_Config.OGL.DC = MainHDC;
Main_HMD_Render_Config.OGL.Header.API = ovrRenderAPI_OpenGL;
Main_HMD_Render_Config.OGL.Header.Multisample = 1;
Main_HMD_Render_Config.OGL.Header.RTSize = OVR::Sizei(Main_HMD->Resolution.w, Main_HMD->Resolution.h);

Main_EyeRenderViewport[ovrEye_Left].Pos = OVR::Vector2i(0, 0);
Main_EyeRenderViewport[ovrEye_Left].Size = OVR::Sizei(finalTextureSize.w / 2, finalTextureSize.h);
Main_EyeRenderViewport[ovrEye_Right].Pos = OVR::Vector2i((finalTextureSize.w + 1) / 2, 0);
Main_EyeRenderViewport[ovrEye_Right].Size = Main_EyeRenderViewport[ovrEye_Left].Size;

Main_EyeTexture[ovrEye_Left].OGL.Header.API = ovrRenderAPI_OpenGL;
Main_EyeTexture[ovrEye_Left].OGL.Header.RenderViewport = Main_EyeRenderViewport[ovrEye_Left];
Main_EyeTexture[ovrEye_Left].OGL.Header.TextureSize = finalTextureSize;
Main_EyeTexture[ovrEye_Left].OGL.TexId = OculusRiftTextureID;
Main_EyeTexture[ovrEye_Left].Texture.Header.API = ovrRenderAPI_OpenGL;
Main_EyeTexture[ovrEye_Left].Texture.Header.RenderViewport = Main_EyeRenderViewport[ovrEye_Left];
Main_EyeTexture[ovrEye_Left].Texture.Header.TextureSize = finalTextureSize;

Main_EyeTexture[ovrEye_Right] = Main_EyeTexture[ovrEye_Left];
Main_EyeTexture[ovrEye_Right].OGL.Header.RenderViewport = Main_EyeRenderViewport[ovrEye_Right];
Main_EyeTexture[ovrEye_Right].Texture.Header.RenderViewport = Main_EyeRenderViewport[ovrEye_Right];

if (!ovrHmd_ConfigureRendering(Main_HMD, &Main_HMD_Render_Config.Config,
ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette |
ovrDistortionCap_TimeWarp | ovrDistortionCap_Overdrive,
Main_HMD_eyeFov,
Main_EyeRenderDesc)) {

return EXIT_FAILURE;

}

ovrHmd_SetEnabledCaps(Main_HMD, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction);

return EXIT_SUCCESS;

}

int configureOculusRiftTracking() {

if (!RiftAvailable) {

return EXIT_SUCCESS;

}

if (!ovrHmd_ConfigureTracking(Main_HMD, ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, NULL)) {

return EXIT_FAILURE;

}

return EXIT_SUCCESS;

}

int loadShaders() {

// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

// Compile Vertex Shader
printf("Compiling Vertext Shader.\n\n");
char const * VertexSource = "#version 330 \n\n\
layout(std140) uniform Matrices{\n\
mat4 m_pvm;\n\
mat4 m_viewModel;\n\
mat3 m_normal;\n\
};\n\
layout(std140) uniform Lights{\n\
vec3 l_dir; \n\
};\n\
layout (location=0) in vec4 position;\n\
layout (location=1) in vec3 normal;\n\
\n\
\n\
out Data{\n\
vec3 normal;\n\
vec4 eye;\n\
} DataOut;\n\
\n\
void main() {\n\
\n\
DataOut.normal = normalize(m_normal * normal);\n\
DataOut.eye = -(m_viewModel * position);\n\
\n\
gl_Position = m_pvm * position;\n\
}\n\
\n";

glShaderSource(VertexShaderID, 1, &VertexSource, NULL);
glCompileShader(VertexShaderID);

// Check Vertex Shader

GLint Result = GL_FALSE;
int InfoLogLength;

glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);

if (InfoLogLength > 0){

std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
std::string ErrorMessage = std::string(&VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);

}

printf("Compiling Fragment Shader.\n\n");
char const * FragmentSource = "#version 330\n\
\
layout(std140) uniform Matrices{\n\
mat4 m_pvm;\n\
mat4 m_viewModel;\n\
mat3 m_normal;\n\
};\n\
\
layout(std140) uniform Materials{\n\
vec4 diffuse;\n\
vec4 ambient;\n\
vec4 specular;\n\
vec4 emissive;\n\
float shininess;\n\
int texCount;\n\
};\
\n\
layout(std140) uniform Lights{\n\
vec3 l_dir; \n\
};\
\n\
in Data{\n\
vec3 normal;\n\
vec4 eye;\n\
} DataIn;\n\
\n\
out vec4 colorOut;\
\n\
void main() {\n\
\n\
vec4 spec = vec4(0.0);\n\
\n\
vec3 n = normalize(DataIn.normal);\n\
vec3 e = normalize(vec3(DataIn.eye));\n\
\n\
float intensity = max(dot(n, l_dir), 0.0);\n\
\n\
if (intensity > 0.0) {\n\
vec3 h = normalize(l_dir + e);\n\
\n\
float intSpec = max(dot(h, n), 0.0);\n\
spec = specular * pow(intSpec, shininess);\n\
}\n\
\n\
colorOut = max(intensity * diffuse + spec, ambient);\n\
}";

glShaderSource(FragmentShaderID, 1, &FragmentSource, NULL);
glCompileShader(FragmentShaderID);

// Check Fragment Shader
glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0){

std::vector<char> FragmentShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
std::string ErrorMessage = std::string(&FragmentShaderErrorMessage[0]);
printf("%s\n", &FragmentShaderErrorMessage[0]);

}

// Link the program
printf("Linking shader program.\n\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);

// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0){

std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
std::string ErrorMessage = std::string(&ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);

}

glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);

MainOpenGLShaderProgramID = ProgramID;

return EXIT_SUCCESS;

}

int prepareShaderUniforms() {

glUseProgram(MainOpenGLShaderProgramID);

MatricesUniformBlockID = glGetUniformBlockIndex(MainOpenGLShaderProgramID, "Matrices");
glUniformBlockBinding(MainOpenGLShaderProgramID, MatricesUniformBlockID, 1);
glGenBuffers(1, &MatricesUniformBufferID);
glBindBuffer(GL_UNIFORM_BUFFER, MatricesUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, MatricesUniformBufferID);
GLsizeiptr TotalBufferSize = sizeof(glm::mat4) + sizeof(glm::mat4);
TotalBufferSize += sizeof(glm::mat3);

glBufferData(GL_UNIFORM_BUFFER, TotalBufferSize, NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);

LightsUniformBlockID = glGetUniformBlockIndex(MainOpenGLShaderProgramID, "Lights");
glUniformBlockBinding(MainOpenGLShaderProgramID, LightsUniformBlockID, 2);
glGenBuffers(1, &LightsUniformBufferID);
glBindBuffer(GL_UNIFORM_BUFFER, LightsUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 2, LightsUniformBufferID);

GLfloat LightDirection[3] = {-4.0f, -3.0f, -3.0f};

glBufferData(GL_UNIFORM_BUFFER, sizeof(LightDirection), &LightDirection, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);

MaterialsUniformBlockID = glGetUniformBlockIndex(MainOpenGLShaderProgramID, "Materials");
glUniformBlockBinding(MainOpenGLShaderProgramID, MaterialsUniformBlockID, 3);
glGenBuffers(1, &MaterialsUniformBufferID);
glBindBuffer(GL_UNIFORM_BUFFER, MaterialsUniformBufferID);
glBindBufferBase(GL_UNIFORM_BUFFER, 3, MaterialsUniformBufferID);

GLfloat Material[18];

//Diffuse
Material[0] = 0.5f;
Material[1] = 0.0f;
Material[2] = 0.0f;
Material[3] = 1.0f;

//Ambient
Material[4] = 0.2f;
Material[5] = 0.2f;
Material[6] = 0.2f;
Material[7] = 1.0f;

//Specular
Material[8] = 1.0f;
Material[9] = 1.0f;
Material[10] = 1.0f;
Material[11] = 1.0f;

//Emissive
Material[12] = 0.0f;
Material[13] = 0.0f;
Material[14] = 0.0f;
Material[15] = 1.0f;

//Shininess
Material[16] = 5.0f;

//Texture Count
Material[17] = 0.0f;

glBufferData(GL_UNIFORM_BUFFER, sizeof(Material), &Material, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, NULL);

return EXIT_SUCCESS;

}

int loadCubes() {

StandardCube FrontCube;

FrontCube.LoadIntoOpenGL();

FrontCube.MoveMe(glm::vec3(0.0f, -1.0f, -2.0f));

Cubes.push_back(FrontCube);

return EXIT_SUCCESS;

}

int prepareMatricies() {

AspectRatio = (GLfloat)(WindowWidth) / (GLfloat)(WindowHeight);

ProjectionMatrix = glm::perspective(45.0f, AspectRatio, 1.0f, 1000.0f);

ViewMatrix = glm::lookAt(
glm::vec3(0.0f, 6.0f, 6.0f), // camera is at (4,3,3), in world space - Where the camera is inside world.
glm::vec3(0.0f, 0.0f, -3.0f), // and looks at the origin - What point the camera is looking at inside world.
glm::vec3(0.0f, 1.0f, 0.0f) // head is up(set to 0,1,0) - the direction of up for camera.
);

glViewport(0, 0, WindowWidth, WindowHeight);

return EXIT_SUCCESS;

}

int SetDrawFunctionPointer() {

if (!RiftAvailable) {

DrawScene = DrawWindowed;

}
else {

DrawScene = DrawOculusRift;

}

return EXIT_SUCCESS;

}

void DrawWindowed() {

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

for (auto & C : Cubes) {

if (RotateCubes) {

C.RotateMe(RotationSpeed * RotationDirection);

}

C.DrawMe();

}

glfwSwapBuffers(MainWindow);

glfwPollEvents();

}

void DrawOculusRift() {

ovrFrameTiming Current_Frame = ovrHmd_BeginFrame(Main_HMD, Main_HMD_FrameIndex);

static ovrPosef Main_HMD_eyeRenderPose[2];
static ovrMatrix4f OculusRiftProjection[2];
static ovrMatrix4f OculusRiftView[2];
static OVR::Vector3f Main_HMD_HeadPos(0.0f, 1.6f, -5.0f);
static ovrTrackingState HmdState;

ovrVector3f hmdToEyeViewOffset[2] = { Main_EyeRenderDesc[0].HmdToEyeViewOffset, Main_EyeRenderDesc[1].HmdToEyeViewOffset };
ovrHmd_GetEyePoses(Main_HMD, Main_HMD_FrameIndex, hmdToEyeViewOffset, Main_HMD_eyeRenderPose, &HmdState);

Main_HMD_HeadPos.y = ovrHmd_GetFloat(Main_HMD, OVR_KEY_EYE_HEIGHT, Main_HMD_HeadPos.y);

if (RotateCubes) {

for (auto & C : Cubes) {

C.RotateMe(RotationSpeed * RotationDirection);

}

}

glBindFramebuffer(GL_FRAMEBUFFER, OculusRiftFrameBufferID);

glUseProgram(MainOpenGLShaderProgramID);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

for (GLint CurrentEyeIndex = 0; CurrentEyeIndex < ovrEye_Count; ++CurrentEyeIndex)
{

ovrEyeType CurrentEye = Main_HMD->EyeRenderOrder[CurrentEyeIndex];

glViewport(
Main_EyeTexture[CurrentEyeIndex].Texture.Header.RenderViewport.Pos.x,
Main_EyeTexture[CurrentEyeIndex].Texture.Header.RenderViewport.Pos.y,
Main_EyeTexture[CurrentEyeIndex].Texture.Header.RenderViewport.Size.w,
Main_EyeTexture[CurrentEyeIndex].Texture.Header.RenderViewport.Size.h
);

OculusRiftProjection[CurrentEyeIndex] = ovrMatrix4f_Projection(Main_EyeRenderDesc[CurrentEyeIndex].Fov,
0.1f, 1000.0f, true);

for (int o = 0; o < 4; o++) {
for (int i = 0; i < 4; i++) {
ProjectionMatrix[o][i] = OculusRiftProjection[CurrentEyeIndex].M[o][i];
}
}

ProjectionMatrix = glm::transpose(ProjectionMatrix);

CenterPositionMatrix = glm::translate(glm::mat4(1.0f),
-glm::vec3(Main_HMD_eyeRenderPose[CurrentEyeIndex].Position.x,
Main_HMD_eyeRenderPose[CurrentEyeIndex].Position.y,
Main_HMD_eyeRenderPose[CurrentEyeIndex].Position.z));

EyeOrientationMatrix = glm::toMat4(glm::quat(
Main_HMD_eyeRenderPose[CurrentEyeIndex].Orientation.w,
-Main_HMD_eyeRenderPose[CurrentEyeIndex].Orientation.x,
-Main_HMD_eyeRenderPose[CurrentEyeIndex].Orientation.y,
-Main_HMD_eyeRenderPose[CurrentEyeIndex].Orientation.z
));

EyePositionMatrix = glm::translate(glm::mat4(1.0f),
glm::vec3(
Main_EyeRenderDesc[CurrentEyeIndex].HmdToEyeViewOffset.x,
Main_EyeRenderDesc[CurrentEyeIndex].HmdToEyeViewOffset.y,
Main_EyeRenderDesc[CurrentEyeIndex].HmdToEyeViewOffset.z
));

ViewMatrix = EyePositionMatrix * EyeOrientationMatrix * CenterPositionMatrix;

for (auto & C : Cubes) {

C.DrawMe();

}

}

ovrHmd_EndFrame(Main_HMD, Main_HMD_eyeRenderPose, &Main_EyeTexture[0].Texture);

Main_HMD_FrameIndex += 1;

glfwPollEvents();

}

static void GLFWKeyCallback(GLFWwindow* p_Window, GLint p_Key, GLint p_Scancode, GLint p_Action, GLint p_Mods) {

if (RiftAvailable) {

ovrHSWDisplayState l_HasWarningState;

ovrHmd_GetHSWDisplayState(Main_HMD, &l_HasWarningState);

if (l_HasWarningState.Displayed) {

ovrHmd_DismissHSWDisplay(Main_HMD);

}

}

if (p_Key == GLFW_KEY_ESCAPE && p_Action == GLFW_PRESS) {

glfwSetWindowShouldClose(p_Window, GL_TRUE);
}

if (p_Key == GLFW_KEY_O && p_Action == GLFW_PRESS) {

glClearColor(0.2f, 0.1f, 0.3f, 1.0f);

}

if (p_Key == GLFW_KEY_I && p_Action == GLFW_PRESS) {

glClearColor(1.0f, 0.5f, 0.5f, 1.0f);

}

if (p_Key == GLFW_KEY_R && p_Action == GLFW_PRESS) {

RotateCubes = !RotateCubes;

}

if (p_Key == GLFW_KEY_PAGE_UP && (p_Action == GLFW_PRESS || p_Action == GLFW_REPEAT)) {

RotationSpeed += 0.001f;

}

if (p_Key == GLFW_KEY_PAGE_DOWN && (p_Action == GLFW_PRESS || p_Action == GLFW_REPEAT)) {

RotationSpeed -= 0.001f;

if (RotationSpeed < 0.001f) {

RotationSpeed = 0.001f;

}

}

if (p_Key == GLFW_KEY_SPACE && p_Action == GLFW_PRESS) {

RotationDirection *= -1.0f;

}

}

static void GLFWWindowResizeCallBack(GLFWwindow* p_Window, GLint width, GLint height) {

//CurrentGLFWApplication->WindowResizeCallBack(p_Window, width, height);

}

static void GLFWMouseMovementCallBack(GLFWwindow* p_Window, GLdouble MouseX, GLdouble MouseY) {

//CurrentGLFWApplication->MouseMovementCallBack(p_Window, MouseX, MouseY);

}

static void GLFWFramebufferSizeCallback(GLFWwindow* window, GLint width, GLint height)
{
AspectRatio = (GLfloat)(width) / (GLfloat)(height);

ProjectionMatrix = glm::perspective(45.0f, AspectRatio, 0.1f, 1000.0f);

glViewport(0, 0, width, height);

}

static void GLFWErrorCallback(GLint error, const char* description)
{

fputs(description, stderr);

}

int main(int argc, char** argv) {

if (initializeOculusRift() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}

if (initializeGLFWGLEW() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}

if (prepareOpenGL() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}

if (prepareFrameBuffer() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}

if (prepareOculusRiftWindow() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}

if (configureOculusRift() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}



if (configureOculusRiftTracking() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}

if (loadShaders() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}

if (prepareShaderUniforms() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}

if (loadCubes() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}

if (prepareMatricies() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}

if (SetDrawFunctionPointer() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}

while (!glfwWindowShouldClose(MainWindow))

{

DrawScene();

}

exit(EXIT_SUCCESS);

}
29 REPLIES 29

Afuerg
Level 2
"tmason101" wrote:

Hope someone can figure out why my code below doesn't work in "Direct" mode! But that is for other threads...

The combination of direct mode and OpenGL has been buggy/non functional since they introduced direct mode. I'm not entirely up to date if someone managed to get it reliably working with 0.4.3.

tmason101
Level 2
"Afuerg" wrote:
"tmason101" wrote:

Hope someone can figure out why my code below doesn't work in "Direct" mode! But that is for other threads...

The combination of direct mode and OpenGL has been buggy/non functional since they introduced direct mode. I'm not entirely up to date if someone managed to get it reliably working with 0.4.3.


Thanks; looking forward to a response on this front; my example works 100% otherwise 😄 😄 😄

ockiller
Level 3
I'm using SDL2 instead of GLFW, and direct-HMD works fine since SDK 0.4.2 (not tested before). Win 7 64, 64 bits builds, Geforce 9800 GTX (340.52 driver).

Have you tried different initialization orders ? I follow this one :
- ovr_Initialize
- ovrHmd_Create
- ovrHmd_SetEnabledCaps
- ovrHmd_ConfigureTracking
- SDL Init, window creation, GL context creation, GLEW Init
- ovrHmd_AttachToWindow
- Eye textures/FBOs creation
- ovrHmd_ConfigureRendering

Everything else come later. Also, I think you also noticed it but apparently you should not have any GL error pending when calling ovrHmd_EndFrame.

tmason101
Level 2
Worth a shot; I'll try this later today.

tmason101
Level 2
"ockiller" wrote:
I'm using SDL2 instead of GLFW, and direct-HMD works fine since SDK 0.4.2 (not tested before). Win 7 64, 64 bits builds, Geforce 9800 GTX (340.52 driver).

Have you tried different initialization orders ? I follow this one :
- ovr_Initialize
- ovrHmd_Create
- ovrHmd_SetEnabledCaps
- ovrHmd_ConfigureTracking
- SDL Init, window creation, GL context creation, GLEW Init
- ovrHmd_AttachToWindow
- Eye textures/FBOs creation
- ovrHmd_ConfigureRendering

Everything else come later. Also, I think you also noticed it but apparently you should not have any GL error pending when calling ovrHmd_EndFrame.


OK, so I tried your steps and my application fully recognizes the Rift in "Direct" Mode, the camera is turned on, and the orientation works as I can see the output being rendered into the smaller window my app creates.

HOWEVER, with "Direct" mode the Rift itself never activates. As mentioned, the tracking and orientation works but the light stays orange on the Rift.

Any ideas?

Thanks.

EDIT: And I have no pending errors. I used this to check right before ovrHmd_EndFrame():


GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
err = err;
}

jherico
Level 5
"Afuerg" wrote:
"tmason101" wrote:

Hope someone can figure out why my code below doesn't work in "Direct" mode! But that is for other threads...

The combination of direct mode and OpenGL has been buggy/non functional since they introduced direct mode. I'm not entirely up to date if someone managed to get it reliably working with 0.4.3.


Direct Mode with OpenGL works fine for me in 0.4.3.
Brad Davis - Developer for High Fidelity Co-author of Oculus Rift in Action

nuclear
Level 3
"tmason101" wrote:


GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
err = err;
}


OpenGL errors do not accumulate. It's just a single global error variable, which gets cleared by glGetError(). You don't have to call it in a loop. Also err = err; is a no-op 🙂

Just call glGetError() once if you wish to clear the last error.
John Tsiombikas webpage - blog - youtube channel

tmason101
Level 2
"nuclear" wrote:
"tmason101" wrote:


GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
err = err;
}


OpenGL errors do not accumulate. It's just a single global error variable, which gets cleared by glGetError(). You don't have to call it in a loop. Also err = err; is a no-op 🙂

Just call glGetError() once if you wish to clear the last error.


Thanks; I just wanted to see the error in the debugger, hence the no-operation.

But I wasn't getting an error so at least in the above code everything is solid from what I can see.

tmason101
Level 2
"jherico" wrote:
"Afuerg" wrote:
"tmason101" wrote:

Hope someone can figure out why my code below doesn't work in "Direct" mode! But that is for other threads...

The combination of direct mode and OpenGL has been buggy/non functional since they introduced direct mode. I'm not entirely up to date if someone managed to get it reliably working with 0.4.3.


Direct Mode with OpenGL works fine for me in 0.4.3.


Did you use the above code or your personal mix?

Anything that stands out to you in the OP that can prevent or cause "Direct" mode to fail?

Thank you for your time..