#include #include #include #include "shaders.h" #define GLEW_STATIC #include #include #include #include // For exit, EXIT_FAILURE #include // For stderr #include // For reading files #include #include #include void error_callback(int error, const char* description); static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods); std::string loadFile(const std::string& filename); void printArray(float a[]); int main() { using namespace std; // --- GLFW --- glfwSetErrorCallback(error_callback); if (!glfwInit()) exit(EXIT_FAILURE); // Set hints 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 window and context GLFWwindow* window = glfwCreateWindow(638, 499, "program", NULL, NULL); if (!window) { glfwTerminate(); exit(EXIT_FAILURE); } glfwMakeContextCurrent(window); glfwSetKeyCallback(window, key_callback); // GLEW stuff glewExperimental = GL_TRUE; glewInit(); // --------------- // VAO - Vertex Array Objects GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); // When we now call glVertexAttribPointer: the info is stored in the VAO // // Define vertices float vertices[] = { // Position Color Texcoords -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top-left 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Top-right 0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, // Bottom-right -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f // Bottom-left }; GLuint elements[] = { 0, 1, 2, 0, 2, 3 }; GLuint ebo; glGenBuffers(1, &ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW); // GLuint vertexBuffer; glGenBuffers(1, &vertexBuffer); // Using vertexBuffer: glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); // Copy vertex data to buffer. Say that is STATIC: uploaded once! glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // COMPILING VERTEX SHADER GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &shaders::vert, NULL); glCompileShader(vertexShader); // Checking if it compiled: GLint status; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status); assert(status == GL_TRUE); // COMPILING FRAGMENT SHADER GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &shaders::frag, NULL); glCompileShader(fragmentShader); // Checking glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status); assert(status == GL_TRUE); // LINKING / MAKING THE PROGRAM GLuint shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); // Can also link more shaders // (possibly specify which output -> which buffer) // └──▶ glBindFragDataLocation(shaderProgram, 0, "outColor"); glLinkProgram(shaderProgram); glUseProgram(shaderProgram); // MAKING A LINK BETWEEN VERTEX DATA AND ATTRIBUTES // variable, , , , , GLint posAttrib = glGetAttribLocation(shaderProgram, "position"); GLint colAttrib = glGetAttribLocation(shaderProgram, "color"); GLint texcoorAttrib = glGetAttribLocation(shaderProgram, "texcoord"); glEnableVertexAttribArray(posAttrib); glEnableVertexAttribArray(colAttrib); glEnableVertexAttribArray(texcoorAttrib); glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 7*sizeof(float), 0); glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE, 7*sizeof(float), (void*)(2*sizeof(float))); glVertexAttribPointer(texcoorAttrib, 2, GL_FLOAT, GL_FALSE, 7*sizeof(float), (void*)(5*sizeof(float))); // TEXTURES GLuint tex; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); // SOIL - LOAD IMAGE int width, height; unsigned char* image = SOIL_load_image("data/img.png", &width, &height, 0, SOIL_LOAD_RGB); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); SOIL_free_image_data(image); glUniform1i(glGetUniformLocation(shaderProgram, "texKitten"), 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Loop while (!glfwWindowShouldClose(window)) { float timer = (float)glfwGetTime() /2; float ratio; int width, height; glfwGetFramebufferSize(window, &width, &height); ratio = width / (float) height; //glViewport(0, 0, width, height); //glOrtho(-ratio, ratio, -1.f, 1.f, 1.f, -1.f); // CLEAR glClear(GL_COLOR_BUFFER_BIT); // Using Projection matrix //glMatrixMode(GL_PROJECTION); // Reset matrix to identity //glLoadIdentity(); // Switch go Model matrix //glMatrixMode(GL_MODELVIEW); // Reset matrix to identity //glLoadIdentity(); // GL //glDrawArrays(GL_TRIANGLES, 0, 4); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // gl done glfwSwapBuffers(window); glfwPollEvents(); } glDeleteProgram(shaderProgram); glDeleteShader(fragmentShader); glDeleteShader(vertexShader); glDeleteBuffers(1, &vertexBuffer); glDeleteVertexArrays(1, &vao); // TERMINATE glfwDestroyWindow(window); glfwTerminate(); exit(EXIT_SUCCESS); } void printArray(float a[]) { using namespace std; for (int i = 0; i < sizeof(a); i ++) { cout << "Entry " << i << ":" << a[i] << endl; } } std::string loadFile(const std::string& filename) { using namespace std; std::string str; std::ifstream t(filename.c_str()); assert(t); t.seekg(0, std::ios::end); streampos endPos = t.tellg(); assert(endPos >= 0); str.reserve(endPos); t.seekg(0, std::ios::beg); str.assign((std::istreambuf_iterator(t)), std::istreambuf_iterator()); return str; } static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { using namespace std; if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); switch(action) { case GLFW_PRESS: cout << "Press " << key << endl; break; case GLFW_RELEASE: cout << "Release " << key << endl; break; case GLFW_REPEAT: cout << "Repeat " << key << endl; break; default: break; } } void error_callback(int error, const char* description) { fputs(description, stderr); }