PDA

View Full Version : Simple Cube not Showing up with simple Example ...



tmason
10-26-2014, 06:25 AM
Hello,

I am trying to draw a simple cube for a homework assignment for a class but for some reason it isn't showing up.

I am using uniform blocks and modern OpenGL. I am sure I am not doing something correctly.

My complete code is below. The below example depends on GLEW + GLFW + GLM.

Any ideas?

Thank you:



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

#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

#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

GLFWwindow* MainWindow;

#ifdef _WIN32

HWND MainWindowWin32Handle;

#endif

GLint WindowWidth = 1024;
GLint WindowHeight = 768;

GLulong SizeDivizor = 1;

GLboolean RiftAvailable = false;
GLboolean UseApplicationWindowFrame = false;

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;

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

}

};

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

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)
{

glViewport(0, 0, width, height);

}

int initializeGLFWGLEW() {

MainWindow = NULL;

if (!glfwInit())
{

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

}

glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);

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 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\
in vec4 position;\n\
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 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, 0, MatricesUniformBufferID);
GLsizeiptr TotalBufferSize = sizeof(glm::mat4) + sizeof(glm::mat4);
TotalBufferSize += sizeof(glm::mat3);
glBufferData(GL_ARRAY_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, 0, LightsUniformBufferID);

GLfloat LightDirection[3] = { 1.0f, 1.0f, 0.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, 0, 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] = 0.0f;
Material[9] = 0.0f;
Material[10] = 0.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] = 2.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();

Cubes.push_back(NewCube);

return EXIT_SUCCESS;

}

int prepareMatricies() {

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

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

ViewMatrix = glm::lookAt(
glm::vec3(4.0f, 3.0f, 3.0f), // camera is at (4,3,3), in world space - Where the camera is inside world.
glm::vec3(0.0f, 0.0f, 0.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 main(int argc, char** argv) {

if (initializeGLFWGLEW() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}

if (prepareOpenGL() == 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);

}

while (!glfwWindowShouldClose(MainWindow))

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

for (auto & C : Cubes) {

C.DrawMe();

}

glfwSwapBuffers(MainWindow);

glfwPollEvents();

}

exit(EXIT_SUCCESS);

}

tmason
10-26-2014, 11:42 PM
Update:

What I found interesting is that for my light and material uniform blocks I get the uniform block index but the uniform block for my MVP matrix I don't get the index.

I also have updated code at the very bottom of this post.

Any ideas?

Here is the relavent vertex and fragment shaders isolated out:

Vertex Shader

#version 330

layout(std140) uniform MatrixInformation {
mat4 m_pvm;
mat4 m_viewModel;
mat3 m_normal;
};

layout(std140) uniform Lights {
vec3 l_dir;
};
in vec4 position;
in vec3 normal;

out Data{
vec3 normal;
vec4 eye;
} DataOut;

void main() {

DataOut.normal = normalize(m_normal * normal);
DataOut.eye = -(m_viewModel * position);

gl_Position = m_pvm * position;
}




Fragment Shader

#version 330
layout(std140) uniform Materials {
vec4 diffuse;
vec4 ambient;
vec4 specular;
vec4 emissive;
float shininess;
int texCount;
};
layout(std140) uniform Lights {
vec3 l_dir;
};
in Data{
vec3 normal;
vec4 eye;
} DataIn;

out vec4 colorOut;
void main() {

vec4 spec = vec4(0.0);

vec3 n = normalize(DataIn.normal);
vec3 e = normalize(vec3(DataIn.eye));

float intensity = max(dot(n, l_dir), 0.0);

if (intensity > 0.0) {
vec3 h = normalize(l_dir + e);

float intSpec = max(dot(h, n), 0.0);
spec = specular * pow(intSpec, shininess);
}

colorOut = max(intensity * diffuse + spec, ambient);
}


Complete code:

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

#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

#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

GLFWwindow* MainWindow;

#ifdef _WIN32

HWND MainWindowWin32Handle;

#endif

GLint WindowWidth = 1024;
GLint WindowHeight = 768;

GLulong SizeDivizor = 1;

GLboolean RiftAvailable = false;
GLboolean UseApplicationWindowFrame = false;

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;

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

}

};

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

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)
{

glViewport(0, 0, width, height);

}

int initializeGLFWGLEW() {

MainWindow = NULL;

if (!glfwInit())
{

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

}

glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);

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 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 MatrixInformation {\n\
mat4 m_pvm;\n\
mat4 m_viewModel;\n\
mat3 m_normal;\n\
};\n\
layout(std140) uniform Lights {\n\
vec3 l_dir; \n\
};\n\
in vec4 position;\n\
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 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);

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] = { 1.0f, 1.0f, 0.0f };

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

MatricesUniformBlockID = glGetUniformBlockIndex(MainOpenGLShaderProgramID, "MatrixInformation");
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_ARRAY_BUFFER, TotalBufferSize, NULL, 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] = 0.0f;
Material[9] = 0.0f;
Material[10] = 0.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] = 2.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();

Cubes.push_back(NewCube);

return EXIT_SUCCESS;

}

int prepareMatricies() {

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

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

ViewMatrix = glm::lookAt(
glm::vec3(4.0f, 3.0f, 3.0f), // camera is at (4,3,3), in world space - Where the camera is inside world.
glm::vec3(0.0f, 0.0f, 0.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 main(int argc, char** argv) {

if (initializeGLFWGLEW() == EXIT_FAILURE) {

exit(EXIT_FAILURE);

}

if (prepareOpenGL() == 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);

}

while (!glfwWindowShouldClose(MainWindow))

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

for (auto & C : Cubes) {

C.DrawMe();

}

glfwSwapBuffers(MainWindow);

glfwPollEvents();

}

exit(EXIT_SUCCESS);

}