Almost working GLFW+OpenGL+SDK 0.4.3 Example ...
Hello,
So, as the title suggests, I am trying to create a simple GLFW+OpenGL+SDK0.4.3 example to model my larger project out of but I am running into trouble.
I can't figure out what is wrong with the below code so I am hoping someone can help out.
Of course, if we can get this working the community can use the example I am posting as a template for their projects.
Thank you for your time.
The code below has the following dependencies:
Header File "Main.H":
Code File Main.CPP:
So, as the title suggests, I am trying to create a simple GLFW+OpenGL+SDK0.4.3 example to model my larger project out of but I am running into trouble.
I can't figure out what is wrong with the below code so I am hoping someone can help out.
Of course, if we can get this working the community can use the example I am posting as a template for their projects.
Thank you for your time.
The code below has the following dependencies:
- GLEW
- GLFW
- GLM
- Oculus Rift SDK 0.4.3
Header File "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 UseApplicationWindowFrame = false;
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 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);
Code File 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 {
UseApplicationWindowFrame = (Main_HMD->HmdCaps & ovrHmdCap_ExtendDesktop) ? false : true;
Main_HMD_Pos_Res = OVR::Recti(Main_HMD->WindowsPos, Main_HMD->Resolution);
if (UseApplicationWindowFrame) {
SizeDivizor = 2;
}
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;
}
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
glfwSetErrorCallback(GLFWErrorCallback);
if (UseApplicationWindowFrame) {
MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Basic Oculus Rift Example", NULL, NULL);
}
else {
if (!RiftAvailable) {
MainWindow = glfwCreateWindow(WindowWidth, WindowHeight, "Basic Oculus Rift 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, "Basic Oculus Rift 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_TEXTURE_2D);
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 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 (UseApplicationWindowFrame) {
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.Config.Header.API = ovrRenderAPI_OpenGL;
Main_HMD_Render_Config.Config.Header.Multisample = 1;
Main_HMD_Render_Config.Config.Header.RTSize = OVR::Sizei(Main_HMD->Resolution.w, Main_HMD->Resolution.h);
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_HMD_Render_Config.Config.Header.API = ovrRenderAPI_OpenGL;
Main_HMD_Render_Config.Config.Header.Multisample = 1;
Main_HMD_Render_Config.Config.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 NewCube;
NewCube.LoadIntoOpenGL();
NewCube.MoveMe(glm::vec3(0.0f, 0.0f, -3.0f));
Cubes.push_back(NewCube);
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) {
C.RotateMe(0.001f);
C.DrawMe();
}
glfwSwapBuffers(MainWindow);
glfwPollEvents();
}
void DrawOculusRift() {
static 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);
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,
1.0f, 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);
ViewMatrix = 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
));
for (auto & C : Cubes) {
C.RotateMe(0.001f);
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);
}
}
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, 1.0f, 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);
}
