diff --git a/assignment-2a/.DS_Store b/assignment-2a/.DS_Store deleted file mode 100644 index 5dcc6a5..000000000 Binary files a/assignment-2a/.DS_Store and /dev/null differ diff --git a/assignment-2a/.clang-format b/assignment-2a/.clang-format new file mode 100644 index 000000000..f6b8fdf --- /dev/null +++ b/assignment-2a/.clang-format @@ -0,0 +1,2 @@ +--- +BasedOnStyle: LLVM diff --git a/assignment-2a/CMakeLists.txt b/assignment-2a/CMakeLists.txt index f94fa04..e115069 100755 --- a/assignment-2a/CMakeLists.txt +++ b/assignment-2a/CMakeLists.txt @@ -1,81 +1,84 @@ -# 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) - -# Define in the C++ code what the variable "SRC_DIR" should be equal to the current_path/src -add_definitions( -DSRC_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src" ) - - -# Find OpenGL, and set link library names and include paths -find_package(OpenGL REQUIRED) -set(OPENGL_LIBRARIES ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}) -set(OPENGL_INCLUDE_DIRS ${OPENGL_INCLUDE_DIR}) -include_directories(${OPENGL_INCLUDE_DIRS}) - -# Also disable building some of the extra things GLFW has (examples, tests, docs) -set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL " " FORCE) -set(GLFW_BUILD_TESTS OFF CACHE BOOL " " FORCE) -set(GLFW_BUILD_DOCS OFF CACHE BOOL " " FORCE) - -# Now actually run cmake on the CMakeLists.txt file found inside of the GLFW directory -add_subdirectory(ext/glfw) - -# Make a list of all the source files -set( - SOURCES - src/HW2a.cpp - - ext/glad/src/glad.c -) - -# Make a list of all the header files (optional-- only necessary to make them appear in IDE) -set( - INCLUDES - src/ShaderStuff.hpp -) - -# Make a list of all of the directories to look in when doing #include "whatever.h" -set( - INCLUDE_DIRS - ext/ - ext/glfw/include - ext/glad/include -) - -set( - LIBS - glfw - ${OPENGL_LIBRARIES} -) - -# Define what we are trying to produce here (an executable), as -# well as what items are needed to create it (the header and source files) -add_executable(${PROJECT_NAME} ${SOURCES} ${INCLUDES}) - -# Tell cmake which directories to look in when you #include a file -# Equivalent to the "-I" option for g++ -include_directories(${INCLUDE_DIRS}) - -# Tell cmake which libraries to link to -# Equivalent to the "-l" option for g++ -target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBS}) - -install(TARGETS ${PROJECT_NAME} DESTINATION bin) - -# For Visual Studio only -if (MSVC) - # Do a parallel compilation of this project - target_compile_options(${PROJECT_NAME} PRIVATE "/MP") - # Have this project be the default startup project (the one to build/run when hitting F5) - set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME}) -endif() +# Set the minimum required version of cmake for this project +cmake_minimum_required (VERSION 3.1) +set(CMAKE_CXX_STANDARD 17) + +# 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) + +# Define in the C++ code what the variable "SRC_DIR" should be equal to the current_path/src +add_definitions( -DSRC_DIR="${CMAKE_CURRENT_SOURCE_DIR}/src" ) + +find_package(spdlog REQUIRED) + +# Find OpenGL, and set link library names and include paths +find_package(OpenGL REQUIRED) +set(OPENGL_LIBRARIES ${OPENGL_gl_LIBRARY} ${OPENGL_glu_LIBRARY}) +set(OPENGL_INCLUDE_DIRS ${OPENGL_INCLUDE_DIR}) +include_directories(${OPENGL_INCLUDE_DIRS}) + +# Also disable building some of the extra things GLFW has (examples, tests, docs) +set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL " " FORCE) +set(GLFW_BUILD_TESTS OFF CACHE BOOL " " FORCE) +set(GLFW_BUILD_DOCS OFF CACHE BOOL " " FORCE) + +# Now actually run cmake on the CMakeLists.txt file found inside of the GLFW directory +add_subdirectory(ext/glfw) + +# Make a list of all the source files +set( + SOURCES + src/main.cpp + src/controls.cpp + src/util.cpp + ext/glad/src/glad.c +) + +# Make a list of all the header files (optional-- only necessary to make them appear in IDE) +set( + INCLUDES +) + +# Make a list of all of the directories to look in when doing #include "whatever.h" +set( + INCLUDE_DIRS + ext/ + ext/glfw/include + ext/glad/include +) + +set( + LIBS + glfw + spdlog::spdlog + ${OPENGL_LIBRARIES} +) + +# Define what we are trying to produce here (an executable), as +# well as what items are needed to create it (the header and source files) +add_executable(${PROJECT_NAME} ${SOURCES} ${INCLUDES}) + +# Tell cmake which directories to look in when you #include a file +# Equivalent to the "-I" option for g++ +include_directories(${INCLUDE_DIRS}) + +# Tell cmake which libraries to link to +# Equivalent to the "-l" option for g++ +target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBS}) + +install(TARGETS ${PROJECT_NAME} DESTINATION bin) + +# For Visual Studio only +if (MSVC) + # Do a parallel compilation of this project + target_compile_options(${PROJECT_NAME} PRIVATE "/MP") + # Have this project be the default startup project (the one to build/run when hitting F5) + set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${PROJECT_NAME}) +endif() diff --git a/assignment-2a/default.nix b/assignment-2a/default.nix index fbacd1a..563ce07 100644 --- a/assignment-2a/default.nix +++ b/assignment-2a/default.nix @@ -1,4 +1,4 @@ -{ stdenv, cmake, ninja, libglvnd, libGLU, xorg }: +{ stdenv, cmake, ninja, libglvnd, libGLU, xorg, spdlog }: stdenv.mkDerivation { name = "assignment-2a"; @@ -15,6 +15,7 @@ stdenv.mkDerivation { xorg.libXinerama xorg.libXrandr xorg.libXrender + spdlog ]; preBuild = '' diff --git a/assignment-2a/src/controls.cpp b/assignment-2a/src/controls.cpp new file mode 100644 index 000000000..1664fae --- /dev/null +++ b/assignment-2a/src/controls.cpp @@ -0,0 +1,60 @@ +#include "controls.h" +#include "GLFW/glfw3.h" +#include + +void key_callback(GLFWwindow *window, int key, int scancode, int action, + int mods) { + int state = glfwGetKey(window, GLFW_KEY_E); + + // checks to see if the escape or q key was pressed + if ((key == GLFW_KEY_ESCAPE || key == GLFW_KEY_Q) && action == GLFW_PRESS) + glfwSetWindowShouldClose(window, GL_TRUE); + + if ((mods & GLFW_MOD_CONTROL) > 0) { + if (action == GLFW_PRESS) { + ctrl_pressed = true; + spdlog::debug("Press ctrl"); + } else if (action == GLFW_RELEASE) { + ctrl_pressed = false; + spdlog::debug("Release ctrl"); + } + + } else { + } +} + +void mouse_button_callback(GLFWwindow *window, int button, int action, + int mods) { + glfwGetCursorPos(window, &mouse_x, &mouse_y); + if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) { + } + + // Pressed the left mouse button, starting drag + if (ctrl_pressed && button == GLFW_MOUSE_BUTTON_LEFT && + action == GLFW_PRESS) { + is_dragging = true; + drag_start_x = mouse_x; + drag_start_y = mouse_y; + spdlog::debug("Start drag at ({}, {})!", drag_start_x, drag_start_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 +} + +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 + mouse_x = xpos; + mouse_y = ypos; + + // (necessary to quantify the amount and direction of cursor motion) + // take the appropriate action + + if (is_dragging) { + } +} diff --git a/assignment-2a/src/controls.h b/assignment-2a/src/controls.h new file mode 100644 index 000000000..a995917 --- /dev/null +++ b/assignment-2a/src/controls.h @@ -0,0 +1,25 @@ +#ifndef PERIPHERALS_H_ +#define PERIPHERALS_H_ + +#include "GLFW/glfw3.h" + +extern GLdouble mouse_x, mouse_y; +extern GLfloat M[16]; + +extern bool is_dragging, ctrl_pressed; +extern GLdouble drag_start_x, drag_start_y; + +// function that is called whenever a keyboard event occurs; defines how +// keyboard input will be handled +void key_callback(GLFWwindow *window, int key, int scancode, int action, + int mods); + +// function that is called whenever a mouse or trackpad button press event +// occurs +void mouse_button_callback(GLFWwindow *window, int button, int action, + int mods); + +// function that is called whenever a cursor motion event occurs +void cursor_pos_callback(GLFWwindow *window, double xpos, double ypos); + +#endif diff --git a/assignment-2a/src/fshader2a.glsl b/assignment-2a/src/fshader2a.glsl index 6cb93cb..75e4086 100755 --- a/assignment-2a/src/fshader2a.glsl +++ b/assignment-2a/src/fshader2a.glsl @@ -1,9 +1,9 @@ // fragment shader template -#version 150 -in vec4 vcolor; -out vec4 color; -void main() -{ - color = vcolor; // set output color to interpolated color from vshader -} \ No newline at end of file +#version 150 +in vec4 vcolor; +out vec4 color; + +void main() { + color = vcolor; // set output color to interpolated color from vshader +} diff --git a/assignment-2a/src/HW2a.cpp b/assignment-2a/src/main.cpp similarity index 65% rename from assignment-2a/src/HW2a.cpp rename to assignment-2a/src/main.cpp index 9e1256a..a8ef78f 100755 --- a/assignment-2a/src/HW2a.cpp +++ b/assignment-2a/src/main.cpp @@ -1,277 +1,248 @@ -// 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 - -#include -#include -#include -#include -#include - -#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 -#include "ShaderStuff.hpp" - -//---------------------------------------------------------------------------- - -// initialize some basic structure types -typedef struct { - GLfloat x, y; -} FloatType2D; - -typedef struct { - GLfloat r, g, b; -} ColorType3D; - -GLfloat M[16]; // general transformation matrix - -// define some assorted global variables, to make life easier -GLint m_location; -GLdouble mouse_x, mouse_y; -GLint window_width = 500; -GLint window_height = 500; -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 -} - -//---------------------------------------------------------------------------- -// 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 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 -} - -//---------------------------------------------------------------------------- - -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]); - - // 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 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); - - // 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 - - // 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 +// 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 + +#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 + +#include "shaders.h" + +#include "controls.h" +#include "util.h" + +//---------------------------------------------------------------------------- + +// initialize some basic structure types +typedef struct { + GLfloat x, y; +} FloatType2D; + +typedef struct { + GLfloat r, g, b; +} ColorType3D; + +GLfloat M[16]; // general transformation matrix + +// define some assorted global variables, to make life easier +GLint m_location; +GLdouble mouse_x, mouse_y; +GLint window_width = 500; +GLint window_height = 500; +GLdouble pi = 4.0 * atan(1.0); + +bool is_dragging = false; +bool ctrl_pressed = false; +GLdouble drag_start_x, drag_start_y; + +double figure_x, figure_y, figure_z; + +GLFWcursor *hand_cursor, *arrow_cursor; // some different cursors + +GLint NVERTICES = 9; // part of the hard-coded model + +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]); + + // 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 + string shader_dir = env("SHADER_DIR").value_or(SRC_DIR); + string vshader = fmt::format("{}/vshader2a.glsl", shader_dir); + string fshader = fmt::format("{}/fshader2a.glsl", shader_dir); + spdlog::info("Shaders from: {}", shader_dir); + + // Load the shaders and use the resulting shader program + program = InitShader(vshader.c_str(), fshader.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) { + spdlog::set_level(spdlog::level::debug); + + 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); + + // 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); + } + + // tells the system to wait for the rendered frame to finish updating + // before swapping buffers; can help to avoid tearing + glfwSwapInterval(1); + + // 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 + spdlog::info("Initializing..."); + 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 + spdlog::debug( + "M = [{} {} {} {}\n {} {} {} {}\n {} {} {} {}\n {} {} " + "{} {}]\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]); + + // send the updated model transformation matrix to the GPU + glUniformMatrix4fv(m_location, 1, GL_FALSE, M); + + // draw a triangle between the first vertex and each + // successive vertex pair in the hard-coded model + glDrawArrays(GL_TRIANGLES, 0, NVERTICES); + + // ensure that all OpenGL calls have executed before swapping + // buffers + glFlush(); + + 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/shaders.h similarity index 95% rename from assignment-2a/src/ShaderStuff.hpp rename to assignment-2a/src/shaders.h index 898c9f1..78fffb0 100755 --- a/assignment-2a/src/ShaderStuff.hpp +++ b/assignment-2a/src/shaders.h @@ -1,147 +1,149 @@ -#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 - -#ifndef SHADERSTUFF -#define SHADERSTUFF 1 - -#define DEBUG_ON 0 -#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); - - // 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; -} - -#endif +#include +#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 + +#ifndef SHADERSTUFF +#define SHADERSTUFF 1 + +#define DEBUG_ON 0 +#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) { + spdlog::info(":skull: can't open shader source file {}", 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; +} + +#endif diff --git a/assignment-2a/src/util.cpp b/assignment-2a/src/util.cpp new file mode 100644 index 000000000..82b6d06 --- /dev/null +++ b/assignment-2a/src/util.cpp @@ -0,0 +1,13 @@ +#include "util.h" +#include + +optional env(string ident) { + char *result = getenv(ident.c_str()); + if (!result) + return {}; + return string(result); +} + +void error_callback(int error, const char *description) { + spdlog::error("{}", description); +} diff --git a/assignment-2a/src/util.h b/assignment-2a/src/util.h new file mode 100644 index 000000000..d017102 --- /dev/null +++ b/assignment-2a/src/util.h @@ -0,0 +1,12 @@ +#ifndef UTIL_H_ +#define UTIL_H_ + +#include +#include + +using namespace std; + +optional env(string ident); +void error_callback(int error, const char *description); + +#endif diff --git a/assignment-2a/src/vshader2a.glsl b/assignment-2a/src/vshader2a.glsl index 77b270c..ee0ebc3 100755 --- a/assignment-2a/src/vshader2a.glsl +++ b/assignment-2a/src/vshader2a.glsl @@ -1,12 +1,12 @@ // vertex shader template - -#version 150 -in vec4 vertex_position; -in vec4 vertex_color; -out vec4 vcolor; -uniform mat4 M; - -void main() { - gl_Position = M*vertex_position; // update vertex position using M - vcolor = vertex_color; // pass vertex color to fragment shader -} \ No newline at end of file + +#version 150 +in vec4 vertex_position; +in vec4 vertex_color; +out vec4 vcolor; +uniform mat4 M; + +void main() { + gl_Position = M * vertex_position; // update vertex position using M + vcolor = vertex_color; // pass vertex color to fragment shader +} diff --git a/flake.nix b/flake.nix index e569f9d..47dd35f 100644 --- a/flake.nix +++ b/flake.nix @@ -31,12 +31,13 @@ cargo-watch clang-tools cmake + dos2unix imagemagick linuxPackages_latest.perf + ninja pandoc poppler_utils texlive.combined.scheme-full - ninja unzip zip @@ -62,6 +63,7 @@ xorg.libXinerama xorg.libXrandr xorg.libXrender + spdlog ]); }; });