2019/11/26
1 #include <glad/glad.h> 2 #include <GLFW/glfw3.h> 3 4 #include <iostream> 5 6 void framebuffer_size_callback(GLFWwindow* window, int width, int height); 7 void processInput(GLFWwindow *window); 8 9 // settings 10 const unsigned int SCR_WIDTH = 800; 11 const unsigned int SCR_HEIGHT = 600; 12 13 const char *vertexShaderSource = "#version 330 core\n" 14 "layout (location = 0) in vec3 aPos;\n" 15 "void main()\n" 16 "{\n" 17 " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" 18 "}\0"; 19 const char *fragmentShaderSource = "#version 330 core\n" 20 "out vec4 FragColor;\n" 21 "void main()\n" 22 "{\n" 23 " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" 24 "}\n\0"; 25 26 int main() 27 { 28 // glfw: initialize and configure 29 // ------------------------------ 30 glfwInit(); 31 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 32 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 33 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 34 35 #ifdef __APPLE__ 36 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X 37 #endif 38 39 // glfw window creation 40 // -------------------- 41 GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); 42 if (window == NULL) 43 { 44 std::cout << "Failed to create GLFW window" << std::endl; 45 glfwTerminate(); 46 return -1; 47 } 48 glfwMakeContextCurrent(window); 49 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); 50 51 // glad: load all OpenGL function pointers 52 // --------------------------------------- 53 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) 54 { 55 std::cout << "Failed to initialize GLAD" << std::endl; 56 return -1; 57 } 58 59 60 // build and compile our shader program 61 // ------------------------------------ 62 // vertex shader 63 int vertexShader = glCreateShader(GL_VERTEX_SHADER); 64 glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); 65 glCompileShader(vertexShader); 66 // check for shader compile errors 67 int success; 68 char infoLog[512]; 69 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); 70 if (!success) 71 { 72 glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); 73 std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; 74 } 75 // fragment shader 76 int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 77 glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); 78 glCompileShader(fragmentShader); 79 // check for shader compile errors 80 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); 81 if (!success) 82 { 83 glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); 84 std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; 85 } 86 // link shaders 87 int shaderProgram = glCreateProgram(); 88 glAttachShader(shaderProgram, vertexShader); 89 glAttachShader(shaderProgram, fragmentShader); 90 glLinkProgram(shaderProgram); 91 // check for linking errors 92 glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); 93 if (!success) { 94 glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); 95 std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; 96 } 97 glDeleteShader(vertexShader); 98 glDeleteShader(fragmentShader); 99 100 // set up vertex data (and buffer(s)) and configure vertex attributes 101 // ------------------------------------------------------------------ 102 // add a new set of vertices to form a second triangle (a total of 6 vertices); the vertex attribute configuration remains the same (still one 3-float position vector per vertex) 103 float vertices[] = { 104 // first triangle 105 -0.9f, -0.5f, 0.0f, // left 106 -0.0f, -0.5f, 0.0f, // right 107 -0.45f, 0.5f, 0.0f, // top 108 // second triangle 109 0.0f, -0.5f, 0.0f, // left 110 0.9f, -0.5f, 0.0f, // right 111 0.45f, 0.5f, 0.0f // top 112 }; 113 114 unsigned int VBO, VAO; 115 glGenVertexArrays(1, &VAO); 116 glGenBuffers(1, &VBO); 117 // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). 118 glBindVertexArray(VAO); 119 120 glBindBuffer(GL_ARRAY_BUFFER, VBO); 121 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 122 123 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); 124 glEnableVertexAttribArray(0); 125 126 // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind 127 glBindBuffer(GL_ARRAY_BUFFER, 0); 128 129 // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other 130 // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. 131 glBindVertexArray(0); 132 133 134 // uncomment this call to draw in wireframe polygons. 135 //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 136 137 // render loop 138 // ----------- 139 while (!glfwWindowShouldClose(window)) 140 { 141 // input 142 // ----- 143 processInput(window); 144 145 // render 146 // ------ 147 glClearColor(0.2f, 0.3f, 0.3f, 1.0f); 148 glClear(GL_COLOR_BUFFER_BIT); 149 150 // draw our first triangle 151 glUseProgram(shaderProgram); 152 glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized 153 glDrawArrays(GL_TRIANGLES, 0, 6); // set the count to 6 since we're drawing 6 vertices now (2 triangles); not 3! 154 // glBindVertexArray(0); // no need to unbind it every time 155 156 // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) 157 // ------------------------------------------------------------------------------- 158 glfwSwapBuffers(window); 159 glfwPollEvents(); 160 } 161 162 // optional: de-allocate all resources once they've outlived their purpose: 163 // ------------------------------------------------------------------------ 164 glDeleteVertexArrays(1, &VAO); 165 glDeleteBuffers(1, &VBO); 166 167 // glfw: terminate, clearing all previously allocated GLFW resources. 168 // ------------------------------------------------------------------ 169 glfwTerminate(); 170 return 0; 171 } 172 173 // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly 174 // --------------------------------------------------------------------------------------------------------- 175 void processInput(GLFWwindow *window) 176 { 177 if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) 178 glfwSetWindowShouldClose(window, true); 179 } 180 181 // glfw: whenever the window size changed (by OS or user resize) this callback function executes 182 // --------------------------------------------------------------------------------------------- 183 void framebuffer_size_callback(GLFWwindow* window, int width, int height) 184 { 185 // make sure the viewport matches the new window dimensions; note that width and 186 // height will be significantly larger than specified on retina displays. 187 glViewport(0, 0, width, height); 188 }