#include // GLEW #define GLEW_STATIC #include // GLFW #include #if defined(__linux__) #define LINUX #elif defined(_WIN32) #define WINDOWS #elif defined(__APPLE__) #define MAC #endif #define FULLSCREEN false using namespace std; void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode); GLint compileVertexShader(const GLchar**); GLint compileFragmentShader(const GLchar**); GLint linkShaderProgram(initializer_list); const GLuint WIDTH = 800, HEIGHT = 600; // Shaders const GLchar* vertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 position;\n" "void main()\n" "{\n" "gl_Position = vec4(position.x, position.y, position.z, 1.0);\n" "}\0"; const GLchar* fragmentShaderSource = "#version 330 core\n" "out vec4 color;\n" "void main()\n" "{\n" "color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" "}\n\0"; int main(int argc, char* argv[]) { cout << "Starting OpenGL game..." << endl; cout << "Starting GLFW context, OpenGL 3.3" << endl; // Init GLFW glfwInit(); // Set all the required options for GLFW glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); #ifdef MAC // required in OSX glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif // Create a GLFWwindow object that we can use for GLFW's functions GLFWmonitor* monitor = FULLSCREEN ? glfwGetPrimaryMonitor() : nullptr; GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", monitor, nullptr); glfwMakeContextCurrent(window); if (window == NULL) { cout << "Failed to create GLFW window" << endl; glfwTerminate(); return EXIT_FAILURE; } // Set the required callback functions glfwSetKeyCallback(window, key_callback); // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions glewExperimental = GL_TRUE; // Initialize GLEW to setup the OpenGL Function pointers if (glewInit() != GLEW_OK) { cout << "Failed to initialize GLEW" << endl; return EXIT_FAILURE; } // Define the viewport dimensions int width, height; glfwGetFramebufferSize(window, &width, &height); glViewport(0, 0, width, height); GLint vertexShader = compileVertexShader(&vertexShaderSource); GLint fragmentShader = compileFragmentShader(&fragmentShaderSource); GLint shaderProgram = linkShaderProgram({vertexShader, fragmentShader}); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); // Set up vertex data (and buffer(s)) and attribute pointers //GLfloat vertices[] = { // // First triangle // 0.5f, 0.5f, // Top Right // 0.5f, -0.5f, // Bottom Right // -0.5f, 0.5f, // Top Left // // Second triangle // 0.5f, -0.5f, // Bottom Right // -0.5f, -0.5f, // Bottom Left // -0.5f, 0.5f // Top Left //}; GLfloat vertices[] = { 0.5f, 0.5f, 0.0f, // Top Right 0.5f, -0.5f, 0.0f, // Bottom Right -0.5f, 0.5f, 0.0f, // Top Left 0.5f, -0.5f, 0.0f, // Bottom Right -0.5f, -0.5f, 0.0f, // Bottom Left -0.5f, 0.5f, 0.0f // Top Left }; GLuint indices[] = { // Note that we start from 0! 0, 1, 3, // First Triangle 1, 2, 3 // Second Triangle }; GLuint VBO, VAO, EBO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); //glGenBuffers(1, &EBO); // Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s). glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); //glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); // Note that this is allowed, the call to glVertexAttribPointer registered VBO as the currently bound vertex buffer object so afterwards we can safely unbind glBindVertexArray(0); // Unbind VAO (it's always a good thing to unbind any buffer/array to prevent strange bugs), remember: do NOT unbind the EBO, keep it bound to this VAO // Uncommenting this call will result in wireframe polygons. //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Game loop while (!glfwWindowShouldClose(window)) { // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions glfwPollEvents(); // Render // Clear the colorbuffer glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // Draw our first triangle glUseProgram(shaderProgram); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 6); //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glBindVertexArray(0); // Swap the screen buffers glfwSwapBuffers(window); } // Properly de-allocate all resources once they've outlived their purpose glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); //glDeleteBuffers(1, &EBO); glfwTerminate(); return EXIT_SUCCESS; } // Is called whenever a key is pressed/released via GLFW void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { std::cout << key << std::endl; if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); } GLint compileVertexShader(const GLchar** shaderSource) { GLint vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, shaderSource, NULL); glCompileShader(vertexShader); // Check for compile time errors GLint success; GLchar infoLog[512]; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED" << endl << infoLog << endl; } return vertexShader; } GLint compileFragmentShader(const GLchar** shaderSource) { GLint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, shaderSource, NULL); glCompileShader(fragmentShader); // Check for compile time errors GLint success; GLchar infoLog[512]; glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << endl; } return fragmentShader; } GLint linkShaderProgram(initializer_list shaders) { GLint shaderProgram = glCreateProgram(); for (auto shader : shaders) { glAttachShader(shaderProgram, shader); } glLinkProgram(shaderProgram); // Check for linking errors GLint success; GLchar infoLog[512]; glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << endl; } return shaderProgram; }