diff --git a/assignment-2a/.gitignore b/assignment-2a/.gitignore index c286478..cf9b6f8 100644 --- a/assignment-2a/.gitignore +++ b/assignment-2a/.gitignore @@ -1,2 +1,3 @@ /build /result* +.cache diff --git a/assignment-2a/CMakeLists.txt b/assignment-2a/CMakeLists.txt index 86aad33..f94fa04 100755 --- a/assignment-2a/CMakeLists.txt +++ b/assignment-2a/CMakeLists.txt @@ -1,6 +1,14 @@ # Set the minimum required version of cmake for this project cmake_minimum_required (VERSION 3.1) +# Generate the `compile_commands.json` file. +set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") + +if(CMAKE_EXPORT_COMPILE_COMMANDS) + set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES + ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) +endif() + # Create a project called 'HW2a' project(HW2a) diff --git a/assignment-2a/compile_commands.json b/assignment-2a/compile_commands.json new file mode 120000 index 000000000..25eb4b2 --- /dev/null +++ b/assignment-2a/compile_commands.json @@ -0,0 +1 @@ +build/compile_commands.json \ No newline at end of file diff --git a/assignment-2a/src/HW2a.cpp b/assignment-2a/src/HW2a.cpp index 8dff223..9e1256a 100755 --- a/assignment-2a/src/HW2a.cpp +++ b/assignment-2a/src/HW2a.cpp @@ -1,29 +1,30 @@ // Skeleton code for hw2a -// Based on example code from: Interactive Computer Graphics: A Top-Down Approach with Shader-Based OpenGL (6th Edition), by Ed Angel +// Based on example code from: Interactive Computer Graphics: A Top-Down +// Approach with Shader-Based OpenGL (6th Edition), by Ed Angel - -#include "glad/glad.h" -#include "GLFW/glfw3.h" -#include -#include -#include #include +#include #include +#include +#include -#define DEBUG_ON 0 // repetitive of the debug flag in the shader loading code, included here for clarity only +#define DEBUG_ON \ + 0 // repetitive of the debug flag in the shader loading code, included here + // for clarity only -// This file contains the code that reads the shaders from their files and compiles them +// This file contains the code that reads the shaders from their files and +// compiles them #include "ShaderStuff.hpp" //---------------------------------------------------------------------------- // initialize some basic structure types typedef struct { - GLfloat x, y; + GLfloat x, y; } FloatType2D; typedef struct { - GLfloat r, g, b; + GLfloat r, g, b; } ColorType3D; GLfloat M[16]; // general transformation matrix @@ -33,201 +34,244 @@ GLint m_location; GLdouble mouse_x, mouse_y; GLint window_width = 500; GLint window_height = 500; -GLdouble pi = 4.0*atan(1.0); +GLdouble pi = 4.0 * atan(1.0); GLFWcursor *hand_cursor, *arrow_cursor; // some different cursors GLint NVERTICES = 9; // part of the hard-coded model - //---------------------------------------------------------------------------- // function that is called whenever an error occurs -static void -error_callback(int error, const char* description){ - fputs(description, stderr); // write the error description to stderr +static void error_callback(int error, const char *description) { + fputs(description, stderr); // write the error description to stderr } //---------------------------------------------------------------------------- -// function that is called whenever a keyboard event occurs; defines how keyboard input will be handled -static void -key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) // checks to see if the escape key was pressed - glfwSetWindowShouldClose(window, GL_TRUE); // closes the window +// function that is called whenever a keyboard event occurs; defines how +// keyboard input will be handled +static void key_callback(GLFWwindow *window, int key, int scancode, int action, + int mods) { + if (key == GLFW_KEY_ESCAPE && + action == GLFW_PRESS) // checks to see if the escape key was pressed + glfwSetWindowShouldClose(window, GL_TRUE); // closes the window } //---------------------------------------------------------------------------- -// function that is called whenever a mouse or trackpad button press event occurs -static void -mouse_button_callback(GLFWwindow* window, int button, int action, int mods) { - glfwGetCursorPos(window, &mouse_x, &mouse_y); - - // Check which mouse button triggered the event, e.g. GLFW_MOUSE_BUTTON_LEFT, etc. - // and what the button action was, e.g. GLFW_PRESS, GLFW_RELEASE, etc. - // (Note that ordinary trackpad click = mouse left button) - // Also check if any modifier keys were active at the time of the button press, e.g. GLFW_MOD_ALT, etc. - // Take the appropriate action, which could (optionally) also include changing the cursor's appearance +// function that is called whenever a mouse or trackpad button press event +// occurs +static void mouse_button_callback(GLFWwindow *window, int button, int action, + int mods) { + glfwGetCursorPos(window, &mouse_x, &mouse_y); + // Check which mouse button triggered the event, e.g. GLFW_MOUSE_BUTTON_LEFT, + // etc. and what the button action was, e.g. GLFW_PRESS, GLFW_RELEASE, etc. + // (Note that ordinary trackpad click = mouse left button) + // Also check if any modifier keys were active at the time of the button + // press, e.g. GLFW_MOD_ALT, etc. Take the appropriate action, which could + // (optionally) also include changing the cursor's appearance } //---------------------------------------------------------------------------- // function that is called whenever a cursor motion event occurs -static void -cursor_pos_callback(GLFWwindow* window, double xpos, double ypos) { - - // determine the direction of the mouse or cursor motion - // update the current mouse or cursor location - // (necessary to quantify the amount and direction of cursor motion) - // take the appropriate action - +static void cursor_pos_callback(GLFWwindow *window, double xpos, double ypos) { + + // determine the direction of the mouse or cursor motion + // update the current mouse or cursor location + // (necessary to quantify the amount and direction of cursor motion) + // take the appropriate action } //---------------------------------------------------------------------------- -void init( void ) -{ - ColorType3D colors[NVERTICES]; - FloatType2D vertices[NVERTICES]; - GLuint vao[1], buffer, program, location1, location2; - - // set up some hard-coded colors and geometry - // this part can be customized to read in an object description from a file - colors[0].r = 1; colors[0].g = 1; colors[0].b = 1; // white - colors[1].r = 1; colors[1].g = 0; colors[1].b = 0; // red - colors[2].r = 1; colors[2].g = 0; colors[2].b = 0; // red - colors[3].r = 1; colors[3].g = 1; colors[3].b = 1; // white - colors[4].r = 0; colors[4].g = 0; colors[4].b = 1; // blue - colors[5].r = 0; colors[5].g = 0; colors[5].b = 1; // blue - colors[6].r = 1; colors[6].g = 1; colors[6].b = 1; // white - colors[7].r = 0; colors[7].g = 1; colors[7].b = 1; // cyan - colors[8].r = 0; colors[8].g = 1; colors[8].b = 1; // cyan - - vertices[0].x = 0; vertices[0].y = 0.25; // center - vertices[1].x = 0.25; vertices[1].y = 0.5; // upper right - vertices[2].x = -0.25; vertices[2].y = 0.5; // upper left - vertices[3].x = 0; vertices[3].y = 0.25; // center (again) - vertices[4].x = 0.25; vertices[4].y = -0.5; // low-lower right - vertices[5].x = 0.5; vertices[5].y = -0.25; // mid-lower right - vertices[6].x = 0; vertices[6].y = 0.25; // center (again) - vertices[7].x = -0.5; vertices[7].y = -0.25; // low-lower left - vertices[8].x = -0.25; vertices[8].y = -0.5; // mid-lower left - - // Create and bind a vertex array object - glGenVertexArrays( 1, vao ); - glBindVertexArray( vao[0] ); +void init(void) { + ColorType3D colors[NVERTICES]; + FloatType2D vertices[NVERTICES]; + GLuint vao[1], buffer, program, location1, location2; - // Create and initialize a buffer object large enough to hold both vertex position and color data - glGenBuffers( 1, &buffer ); - glBindBuffer( GL_ARRAY_BUFFER, buffer ); - glBufferData( GL_ARRAY_BUFFER, sizeof(vertices)+sizeof(colors), vertices, GL_STATIC_DRAW ); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); - glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices), sizeof(colors), colors); - - // Define the names of the shader files - std::stringstream vshader, fshader; - vshader << SRC_DIR << "/vshader2a.glsl"; - fshader << SRC_DIR << "/fshader2a.glsl"; - - // Load the shaders and use the resulting shader program - program = InitShader( vshader.str().c_str(), fshader.str().c_str() ); - - // Determine locations of the necessary attributes and matrices used in the vertex shader - location1 = glGetAttribLocation( program, "vertex_position" ); - glEnableVertexAttribArray( location1 ); - glVertexAttribPointer( location1, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) ); - location2 = glGetAttribLocation( program, "vertex_color" ); - glEnableVertexAttribArray( location2 ); - glVertexAttribPointer( location2, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(vertices)) ); - m_location = glGetUniformLocation( program, "M"); - - // Define static OpenGL state variables - glClearColor( 1.0, 1.0, 1.0, 1.0 ); // white, opaque background - - // Define some GLFW cursors (in case you want to dynamically change the cursor's appearance) - // If you want, you can add more cursors, or even define your own cursor appearance - arrow_cursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); - hand_cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR); - + // set up some hard-coded colors and geometry + // this part can be customized to read in an object description from a file + colors[0].r = 1; + colors[0].g = 1; + colors[0].b = 1; // white + colors[1].r = 1; + colors[1].g = 0; + colors[1].b = 0; // red + colors[2].r = 1; + colors[2].g = 0; + colors[2].b = 0; // red + colors[3].r = 1; + colors[3].g = 1; + colors[3].b = 1; // white + colors[4].r = 0; + colors[4].g = 0; + colors[4].b = 1; // blue + colors[5].r = 0; + colors[5].g = 0; + colors[5].b = 1; // blue + colors[6].r = 1; + colors[6].g = 1; + colors[6].b = 1; // white + colors[7].r = 0; + colors[7].g = 1; + colors[7].b = 1; // cyan + colors[8].r = 0; + colors[8].g = 1; + colors[8].b = 1; // cyan + + vertices[0].x = 0; + vertices[0].y = 0.25; // center + vertices[1].x = 0.25; + vertices[1].y = 0.5; // upper right + vertices[2].x = -0.25; + vertices[2].y = 0.5; // upper left + vertices[3].x = 0; + vertices[3].y = 0.25; // center (again) + vertices[4].x = 0.25; + vertices[4].y = -0.5; // low-lower right + vertices[5].x = 0.5; + vertices[5].y = -0.25; // mid-lower right + vertices[6].x = 0; + vertices[6].y = 0.25; // center (again) + vertices[7].x = -0.5; + vertices[7].y = -0.25; // low-lower left + vertices[8].x = -0.25; + vertices[8].y = -0.5; // mid-lower left + + // Create and bind a vertex array object + glGenVertexArrays(1, vao); + glBindVertexArray(vao[0]); + + // Create and initialize a buffer object large enough to hold both vertex + // position and color data + glGenBuffers(1, &buffer); + glBindBuffer(GL_ARRAY_BUFFER, buffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) + sizeof(colors), vertices, + GL_STATIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); + glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices), sizeof(colors), colors); + + // Define the names of the shader files + std::stringstream vshader, fshader; + vshader << SRC_DIR << "/vshader2a.glsl"; + fshader << SRC_DIR << "/fshader2a.glsl"; + + // Load the shaders and use the resulting shader program + program = InitShader(vshader.str().c_str(), fshader.str().c_str()); + + // Determine locations of the necessary attributes and matrices used in the + // vertex shader + location1 = glGetAttribLocation(program, "vertex_position"); + glEnableVertexAttribArray(location1); + glVertexAttribPointer(location1, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); + location2 = glGetAttribLocation(program, "vertex_color"); + glEnableVertexAttribArray(location2); + glVertexAttribPointer(location2, 3, GL_FLOAT, GL_FALSE, 0, + BUFFER_OFFSET(sizeof(vertices))); + m_location = glGetUniformLocation(program, "M"); + + // Define static OpenGL state variables + glClearColor(1.0, 1.0, 1.0, 1.0); // white, opaque background + + // Define some GLFW cursors (in case you want to dynamically change the + // cursor's appearance) If you want, you can add more cursors, or even define + // your own cursor appearance + arrow_cursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + hand_cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR); } //---------------------------------------------------------------------------- -int main(int argc, char** argv) { +int main(int argc, char **argv) { - int i; - GLFWwindow* window; + int i; + GLFWwindow *window; - // Define the error callback function - glfwSetErrorCallback(error_callback); - - // Initialize GLFW (performs platform-specific initialization) - if (!glfwInit()) exit(EXIT_FAILURE); - - // Ask for OpenGL 3.2 - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + // Define the error callback function + glfwSetErrorCallback(error_callback); - // Use GLFW to open a window within which to display your graphics - window = glfwCreateWindow(window_width, window_height, "HW2a", NULL, NULL); - - // Verify that the window was successfully created; if not, print error message and terminate - if (!window) - { - printf("GLFW failed to create window; terminating\n"); - glfwTerminate(); - exit(EXIT_FAILURE); - } - - glfwMakeContextCurrent(window); // makes the newly-created context current - - // Load all OpenGL functions (needed if using Windows) - if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { - printf("gladLoadGLLoader failed; terminating\n"); - glfwTerminate(); - exit(EXIT_FAILURE); - } - - glfwSwapInterval(1); // tells the system to wait for the rendered frame to finish updating before swapping buffers; can help to avoid tearing + // Initialize GLFW (performs platform-specific initialization) + if (!glfwInit()) + exit(EXIT_FAILURE); - // Define the keyboard callback function - glfwSetKeyCallback(window, key_callback); - // Define the mouse button callback function - glfwSetMouseButtonCallback(window, mouse_button_callback); - // Define the mouse motion callback function - glfwSetCursorPosCallback(window, cursor_pos_callback); + // Ask for OpenGL 3.2 + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - // Create the shaders and perform other one-time initializations - init(); + // Use GLFW to open a window within which to display your graphics + window = glfwCreateWindow(window_width, window_height, "HW2a", NULL, NULL); - // event loop - while (!glfwWindowShouldClose(window)) { + // Verify that the window was successfully created; if not, print error + // message and terminate + if (!window) { + printf("GLFW failed to create window; terminating\n"); + glfwTerminate(); + exit(EXIT_FAILURE); + } - // fill/re-fill the window with the background color - glClear( GL_COLOR_BUFFER_BIT ); - - // define/re-define the modelview matrix. In this template, we define M to be the identity matrix; you will need define M according to the user's actions. - for (i=0; i<16; i++) { - M[i] = (i%5==0); - } - - // sanity check that your matrix contents are what you expect them to be - if (DEBUG_ON) printf("M = [%f %f %f %f\n %f %f %f %f\n %f %f %f %f\n %f %f %f %f]\n",M[0],M[4],M[8],M[12], M[1],M[5],M[9],M[13], M[2],M[6],M[10],M[14], M[3],M[7],M[11],M[15]); - - glUniformMatrix4fv( m_location, 1, GL_FALSE, M ); // send the updated model transformation matrix to the GPU - glDrawArrays( GL_TRIANGLES, 0, NVERTICES ); // draw a triangle between the first vertex and each successive vertex pair in the hard-coded model - glFlush(); // ensure that all OpenGL calls have executed before swapping buffers + glfwMakeContextCurrent(window); // makes the newly-created context current - glfwSwapBuffers(window); // swap buffers - glfwWaitEvents(); // wait for a new event before re-drawing + // Load all OpenGL functions (needed if using Windows) + if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { + printf("gladLoadGLLoader failed; terminating\n"); + glfwTerminate(); + exit(EXIT_FAILURE); + } - } // end graphics loop + glfwSwapInterval( + 1); // tells the system to wait for the rendered frame to finish updating + // before swapping buffers; can help to avoid tearing - // Clean up - glfwDestroyWindow(window); - glfwTerminate(); // destroys any remaining objects, frees resources allocated by GLFW - exit(EXIT_SUCCESS); + // Define the keyboard callback function + glfwSetKeyCallback(window, key_callback); + // Define the mouse button callback function + glfwSetMouseButtonCallback(window, mouse_button_callback); + // Define the mouse motion callback function + glfwSetCursorPosCallback(window, cursor_pos_callback); + + // Create the shaders and perform other one-time initializations + init(); + + // event loop + while (!glfwWindowShouldClose(window)) { + + // fill/re-fill the window with the background color + glClear(GL_COLOR_BUFFER_BIT); + + // define/re-define the modelview matrix. In this template, we define M to + // be the identity matrix; you will need define M according to the user's + // actions. + for (i = 0; i < 16; i++) { + M[i] = (i % 5 == 0); + } + + // sanity check that your matrix contents are what you expect them to be + if (DEBUG_ON) + printf("M = [%f %f %f %f\n %f %f %f %f\n %f %f %f %f\n %f %f " + "%f %f]\n", + M[0], M[4], M[8], M[12], M[1], M[5], M[9], M[13], M[2], M[6], + M[10], M[14], M[3], M[7], M[11], M[15]); + + glUniformMatrix4fv( + m_location, 1, GL_FALSE, + M); // send the updated model transformation matrix to the GPU + glDrawArrays( + GL_TRIANGLES, 0, + NVERTICES); // draw a triangle between the first vertex and each + // successive vertex pair in the hard-coded model + glFlush(); // ensure that all OpenGL calls have executed before swapping + // buffers + + glfwSwapBuffers(window); // swap buffers + glfwWaitEvents(); // wait for a new event before re-drawing + + } // end graphics loop + + // Clean up + glfwDestroyWindow(window); + glfwTerminate(); // destroys any remaining objects, frees resources allocated + // by GLFW + exit(EXIT_SUCCESS); } // end main - - diff --git a/assignment-2a/src/ShaderStuff.hpp b/assignment-2a/src/ShaderStuff.hpp index f2dd92a..898c9f1 100755 --- a/assignment-2a/src/ShaderStuff.hpp +++ b/assignment-2a/src/ShaderStuff.hpp @@ -1,141 +1,147 @@ +#include + +#include + +#include "glad/glad.h" +#include "GLFW/glfw3.h" + // Basic OpenGL program -// Based on example code from: Interactive Computer Graphics: A Top-Down Approach with Shader-Based OpenGL (6th Edition), by Ed Angel +// Based on example code from: Interactive Computer Graphics: A Top-Down +// Approach with Shader-Based OpenGL (6th Edition), by Ed Angel #ifndef SHADERSTUFF #define SHADERSTUFF 1 #define DEBUG_ON 0 -#define BUFFER_OFFSET(bytes) ((GLvoid*) (bytes)) +#define BUFFER_OFFSET(bytes) ((GLvoid *)(bytes)) // Create a NULL-terminated string by reading the provided file -static char* -readShaderSource(const char* shaderFile) -{ - FILE *fp; - long length, count; - char *buffer; - // struct stat fileinfo; - - // open the file containing the text of the shader code - fp = fopen(shaderFile, "rb"); - - // check for errors in opening the file - if ( fp == NULL ) { - printf("can't open shader source file %s\n", shaderFile); - return NULL; - } - - // determine the file size - fseek(fp, 0, SEEK_END); // move position indicator to the end of the file; - length = ftell(fp); // return the value of the current position - if (DEBUG_ON) fprintf(stdout, "length in bytes of shader file: %ld\n", length); - - // allocate a buffer with the indicated number of bytes, plus one - buffer = new char[length + 1]; - - // read the appropriate number of bytes from the file - fseek(fp, 0, SEEK_SET); // move position indicator to the start of the file - count = fread(buffer, 1, length, fp); // read all of the bytes - if (DEBUG_ON) fprintf(stdout, "count of bytes successfully read: %ld\n", count); +static char *readShaderSource(const char *shaderFile) { + FILE *fp; + long length, count; + char *buffer; + // struct stat fileinfo; - // append a NULL character to indicate the end of the string - buffer[count] = '\0'; //because on some systems, count != length - - // close the file - fclose(fp); - - // return the string - return buffer; + // open the file containing the text of the shader code + fp = fopen(shaderFile, "rb"); + + // check for errors in opening the file + if (fp == NULL) { + printf("can't open shader source file %s\n", shaderFile); + return NULL; + } + + // determine the file size + fseek(fp, 0, SEEK_END); // move position indicator to the end of the file; + length = ftell(fp); // return the value of the current position + if (DEBUG_ON) + fprintf(stdout, "length in bytes of shader file: %ld\n", length); + + // allocate a buffer with the indicated number of bytes, plus one + buffer = new char[length + 1]; + + // read the appropriate number of bytes from the file + fseek(fp, 0, SEEK_SET); // move position indicator to the start of the file + count = fread(buffer, 1, length, fp); // read all of the bytes + if (DEBUG_ON) + fprintf(stdout, "count of bytes successfully read: %ld\n", count); + + // append a NULL character to indicate the end of the string + buffer[count] = '\0'; // because on some systems, count != length + + // close the file + fclose(fp); + + // return the string + return buffer; } // Create a GLSL program object from vertex and fragment shader files -GLuint -InitShader(const char* vShaderFileName, const char* fShaderFileName) -{ - GLuint vertex_shader, fragment_shader; - GLuint program; - - // check GLSL version - if (DEBUG_ON) printf("GLSL version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); - - // Create shader handlers - vertex_shader = glCreateShader(GL_VERTEX_SHADER); - fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); - - // Read source code from file - std::string vs_text = readShaderSource(vShaderFileName); - std::string fs_text = readShaderSource(fShaderFileName); - - // error check - if ( vs_text == "" ) { - printf("Failed to read from vertex shader file %s\n", vShaderFileName); - exit( 1 ); - } else if (DEBUG_ON) { - printf("read shader code:\n%s\n", vs_text.c_str()); - } - if ( fs_text == "" ) { - printf("Failed to read from fragment shader file %s\n", fShaderFileName); - exit( 1 ); - } else if (DEBUG_ON) { - printf("read shader code:\n%s\n", fs_text.c_str()); - } - - // Set shader source - const char *vv = vs_text.c_str(); - const char *ff = fs_text.c_str(); - glShaderSource(vertex_shader, 1, &vv, NULL); - glShaderSource(fragment_shader, 1, &ff, NULL); - - // Compile shaders - glCompileShader(vertex_shader); - glCompileShader(fragment_shader); - - // Check for errors in compiling shaders - GLint compiled; - glGetShaderiv( vertex_shader, GL_COMPILE_STATUS, &compiled ); - if ( !compiled ) { - printf("vertex_shader failed to compile\n"); - if (DEBUG_ON) { - GLint logMaxSize, logLength; - glGetShaderiv( vertex_shader, GL_INFO_LOG_LENGTH, &logMaxSize ); - printf("printing error message of %d bytes\n", logMaxSize); - char* logMsg = new char[logMaxSize]; - glGetShaderInfoLog( vertex_shader, logMaxSize, &logLength, logMsg ); - printf("%d bytes retrieved\n", logLength); - printf("error message: %s\n", logMsg); - delete[] logMsg; - } - exit(1); - } - glGetShaderiv( fragment_shader, GL_COMPILE_STATUS, &compiled ); - if ( !compiled ) { - printf("fragment_shader failed to compile\n"); - if (DEBUG_ON) { - GLint logMaxSize, logLength; - glGetShaderiv( fragment_shader, GL_INFO_LOG_LENGTH, &logMaxSize ); - printf("printing error message of %d bytes\n", logMaxSize); - char* logMsg = new char[logMaxSize]; - glGetShaderInfoLog( fragment_shader, logMaxSize, &logLength, logMsg ); - printf("%d bytes retrieved\n", logLength); - printf("error message: %s\n", logMsg); - delete[] logMsg; - } - exit(1); - } - - // Create the program - program = glCreateProgram(); - - // Attach shaders to program - glAttachShader(program, vertex_shader); - glAttachShader(program, fragment_shader); - - // Link and set program to use - glLinkProgram(program); - glUseProgram(program); - - return program; +GLuint InitShader(const char *vShaderFileName, const char *fShaderFileName) { + GLuint vertex_shader, fragment_shader; + GLuint program; + + // check GLSL version + if (DEBUG_ON) + printf("GLSL version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); + + // Create shader handlers + vertex_shader = glCreateShader(GL_VERTEX_SHADER); + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + + // Read source code from file + std::string vs_text = readShaderSource(vShaderFileName); + std::string fs_text = readShaderSource(fShaderFileName); + + // error check + if (vs_text == "") { + printf("Failed to read from vertex shader file %s\n", vShaderFileName); + exit(1); + } else if (DEBUG_ON) { + printf("read shader code:\n%s\n", vs_text.c_str()); + } + if (fs_text == "") { + printf("Failed to read from fragment shader file %s\n", fShaderFileName); + exit(1); + } else if (DEBUG_ON) { + printf("read shader code:\n%s\n", fs_text.c_str()); + } + + // Set shader source + const char *vv = vs_text.c_str(); + const char *ff = fs_text.c_str(); + glShaderSource(vertex_shader, 1, &vv, NULL); + glShaderSource(fragment_shader, 1, &ff, NULL); + + // Compile shaders + glCompileShader(vertex_shader); + glCompileShader(fragment_shader); + + // Check for errors in compiling shaders + GLint compiled; + glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) { + printf("vertex_shader failed to compile\n"); + if (DEBUG_ON) { + GLint logMaxSize, logLength; + glGetShaderiv(vertex_shader, GL_INFO_LOG_LENGTH, &logMaxSize); + printf("printing error message of %d bytes\n", logMaxSize); + char *logMsg = new char[logMaxSize]; + glGetShaderInfoLog(vertex_shader, logMaxSize, &logLength, logMsg); + printf("%d bytes retrieved\n", logLength); + printf("error message: %s\n", logMsg); + delete[] logMsg; + } + exit(1); + } + glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &compiled); + if (!compiled) { + printf("fragment_shader failed to compile\n"); + if (DEBUG_ON) { + GLint logMaxSize, logLength; + glGetShaderiv(fragment_shader, GL_INFO_LOG_LENGTH, &logMaxSize); + printf("printing error message of %d bytes\n", logMaxSize); + char *logMsg = new char[logMaxSize]; + glGetShaderInfoLog(fragment_shader, logMaxSize, &logLength, logMsg); + printf("%d bytes retrieved\n", logLength); + printf("error message: %s\n", logMsg); + delete[] logMsg; + } + exit(1); + } + + // Create the program + program = glCreateProgram(); + + // Attach shaders to program + glAttachShader(program, vertex_shader); + glAttachShader(program, fragment_shader); + + // Link and set program to use + glLinkProgram(program); + glUseProgram(program); + + return program; } - #endif