/* Header Inclusions */ #include #include #include // GLM Math Header inclusions #include #include #include using namespace std; // Standard namespace #define WINDOW_TITLE "Modern OpenGL" // Window title Macro /*Shader program Macro*/ #ifndef GLSL #define GLSL(Version, Source) "#version " #Version "\n" #Source #endif /*Variable declarations for shader, window size initialization, buffer and array objects*/ GLint shaderProgram, WindowWidth = 800, WindowHeight = 600; GLuint VBO, VAO, EBO, texture; /*Function prototypes*/ void UResizeWindow(int, int); void URenderGraphics(void); void UCreateShader(void); void UCreateBuffers(void); /* Vertex Shader Source Code */ const GLchar * vertexShaderSource = GLSL(330, layout (location = 0) in vec3 position; // Vertex data from Vertex Attrib Pointer 0 layout (location = 1) in vec3 color; // Color data from Vertex Attrib Pointer 1 out vec3 mobileColor; // variable to transfer color data to the fragment shader // Global variables for the transform matrices uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main(){ gl_Position = projection * view * model * vec4(position, 1.0f); // transforms vertices to clip coordinates mobileColor = color; // references incoming color data } ); /* Fragment Shader Source Code */ const GLchar * fragmentShaderSource = GLSL(330, in vec3 mobileColor; // Variable to hold incoming color data from vertex shader out vec4 gpuColor; // Variable to pass color data to the GPU void main(){ gpuColor = vec4(mobileColor, 1.0); // Sends color data to the GPU for rendering } ); /*Main Program*/ int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); glutInitWindowSize(WindowWidth, WindowHeight); glutCreateWindow(WINDOW_TITLE); glutReshapeFunc(UResizeWindow); glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK) { std::cout << "Failed to initialize GLEW" << std::endl; return -1; } UCreateShader(); UCreateBuffers(); // Use the Shader program glUseProgram(shaderProgram); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color // glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glutDisplayFunc(URenderGraphics); glutMainLoop(); // Destroys Buffer objects once used glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); return 0; } /* Resizes the window*/ void UResizeWindow(int w, int h) { WindowWidth = w; WindowHeight = h; glViewport(0, 0, WindowWidth, WindowHeight); } /* Renders graphics*/ void URenderGraphics(void) { glEnable(GL_DEPTH_TEST); // Enable z-depth glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clears the screen glBindVertexArray(VAO); // Activate the Vertex Array OBject before rendering and transforming the // Transform the object glm::mat4 model; model = glm::translate(model, glm::vec3(0.5, 0.0f, 0.0f)); // Place the object at the center of the viewport // Rotate the cube every second by 0.0005f degrees in XYZ model = glm::rotate(model, glutGet(GLUT_ELAPSED_TIME) * -0.0005f, glm::vec3(0.0, 1.0f, 0.0f)); // Rotate the object 45 degrees on the xyz model = glm::scale(model, glm::vec3(2.0f, 2.0f, 2.0f)); // Increase the object size by a scale of 2 // Transform the camera glm::mat4 view; view =glm::translate(view, glm::vec3(0.5f, 0.0f, -5.0f)); // Moves the world 0.5 units on X and -5 units in Z // Creates a perspective projection glm:: mat4 projection; projection = glm::perspective(45.0f, (GLfloat)WindowWidth / (GLfloat)WindowHeight, 0.1f, 100.0f); // Retrieves and passes transform matrices to the Shader program GLint modelLoc = glGetUniformLocation(shaderProgram, "model"); GLint viewLoc = glGetUniformLocation(shaderProgram, "view"); GLint projLoc = glGetUniformLocation(shaderProgram, "projection"); glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection)); glutPostRedisplay(); // Draws the triangles glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0); glBindVertexArray(0); // Deactivate the Vertex Array Object glutSwapBuffers(); // Flips the back buffer with the front buffer every frame. Similar to GL Flush } /*Creates the shader program*/ void UCreateShader() { // Vertex shader GLint vertexShader = glCreateShader(GL_VERTEX_SHADER); // Creates the Vertex shader glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); // Attaches the Vertex shader to the source code glCompileShader(vertexShader); // Compiles the Vertex shader // Fragment shader GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); // Creates the fragment shader glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); // Attaches the fragment shader to the source code glCompileShader(fragmentShader); // Compiles the Fragment shader // Shader program shaderProgram = glCreateProgram(); // Creates the Shader program and returns an id glAttachShader(shaderProgram, vertexShader); // Attach Vertex shader to the shader program glAttachShader(shaderProgram, fragmentShader); // Attach Fragment shader to the Shader program glLinkProgram(shaderProgram); // Link Vertex and Fragment shader's to Shader program // Delete the vertex and fragment shader once linked glDeleteShader(vertexShader); glDeleteShader(fragmentShader); } /*Creates the Buffer and Array Objects*/ void UCreateBuffers() { // Positions and Color data GLfloat verticies[] = { // Vertex Positions // Colors 0.0f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, // Top Right vertex 0 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, // Bottom Right vertex 1 -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, // Bottom Left Vertex 2 0.0f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f, // Top left Vertex 3 0.5f, -0.5f, -1.0f, 0.5f, 0.5f, 1.0f, // 4 br right 0.5f, 0.5f, -1.0f, 1.0f, 1.0f, 0.5f, // 5 tl right 0.0f, 0.5f, -0.5f, 0.2f, 0.2f, 0.5f, // 6 tl top -0.5f, -0.5f, -1.0f, 1.0f, 0.0f, 1.0f // 7 bl back }; // Index data to share position data GLuint indices[] = { 1, 2, 3, // Triangle 1 front 0, 1, 4, // Triangle 2 right 4, 6, 7, // Triangle 3 back 2, 6, 7, // Triangle 4 left 1, 4, 7, // Triangle 5 bottom back 1, 2, 7 // Triangle 6 bottom front }; //Generate buffer id's glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); // Activate the Vertex Array Object before binding and setting any VBOs and Vertex Attribute POinters. glBindVertexArray(VAO); // Activate the VBO glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(verticies), verticies, GL_STATIC_DRAW); // Copy vertices to VBO // Activate the Element Buffer Object / Indices glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // Copy indices to EBO // Set attribute pointer 0 to hold Position data glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); // Set attribute pointer 1 to hold Color data glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); // Enables vertex attribute glBindVertexArray(0); // Deactivates the VAO which is good practice }