1 #include <GL/glew.h> 2 #include <GL/glut.h> 3 #include <GLFW/glfw3.h> 4 5 #include <stdio.h> 6 #include <math.h> 7 8 #define WIN_TITLE "OpenGL Test Window" 9 #define WIN_WIDTH 800 10 #define WIN_HEIGHT 600 11 12 #define FRAGMENT_SHADER_FILE_NAME "main.frag" 13 #define VERTEX_SHADER_FILE_NAME "main.vert" 14 15 double time = 0.0; 16 17 float map(float x, float in_min, float in_max, float out_min, float out_max) { 18 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; 19 } 20 21 void glfwPrintError(int e, const char *s) { 22 fprintf(stderr, "%s\n", s); 23 } 24 25 void framebufferSizeCallback(GLFWwindow* win, int width, int height) { 26 glViewport(0, 0, width, height); 27 } 28 29 char *loadShaderFromFile(const char *filename) { 30 char *buffer; 31 long len; 32 FILE *f = fopen(filename, "rb"); 33 34 if(f) { 35 fseek(f, 0, SEEK_END); 36 len = ftell(f); 37 fseek(f, 0, SEEK_SET); 38 buffer = (char *)malloc(len + 1); 39 buffer[len] = '\0'; 40 41 if(buffer) 42 fread (buffer, 1, len, f); 43 44 fclose (f); 45 } else return NULL; 46 47 return buffer; 48 } 49 50 int main (void) { 51 GLenum err; 52 GLFWwindow *win; 53 unsigned int VBO, VAO; /* Vertex Buffer Objects, Vertex Array Objects */ 54 char *vertexShaderSource, *fragmentShaderSource; 55 unsigned int vertexShader, fragmentShader, shaderProgram; 56 int success; 57 char infoLog[512]; 58 59 if(!glfwInit()) { 60 fprintf(stderr, "GLFW: failed to initialize\n"); 61 return 1; 62 } 63 64 if(!(win = glfwCreateWindow(WIN_WIDTH, WIN_HEIGHT, WIN_TITLE, NULL, NULL))) 65 glfwTerminate(); 66 67 glfwSetErrorCallback(&glfwPrintError); 68 glfwSetFramebufferSizeCallback(win, framebufferSizeCallback); 69 glfwMakeContextCurrent(win); 70 71 if((err = glewInit())) { 72 fprintf(stderr, "GLEW: %s\n", glewGetErrorString(err)); 73 return 2; 74 } 75 76 /* Vertex Input (or Vertex Data) */ 77 float vertices[] = { 78 -1.0f, -1.0f, 79 1.0f, -1.0f, 80 0.0f, 1.0f, 81 }; 82 83 /* Generate an unique ID to VBO */ 84 glGenBuffers(1, &VBO); 85 86 /* Bind VBO to a Vertex Buffer type */ 87 glBindBuffer(GL_ARRAY_BUFFER, VBO); 88 89 /* Copy the previously defined Vertex Data (vertices) into the buffer's 90 * memory. 91 * The fourth parameter specifies how we want the GPU to manage the given 92 * data: 93 * - GL_STREAM_DRAW: the data is set only once and used by the GPU. 94 * - GL_STATIC_DRAW: the data is set only once and used many times. 95 * - GL_DYNAMIC_DRAW: the data is changed a lot and used many times. */ 96 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 97 98 /* Vertex Shader */ 99 if(!(vertexShaderSource = loadShaderFromFile(VERTEX_SHADER_FILE_NAME))) { 100 fprintf(stderr, "could not load shader from file \"%s\n\"", 101 VERTEX_SHADER_FILE_NAME); 102 return 1; 103 } 104 105 vertexShader = glCreateShader(GL_VERTEX_SHADER); 106 glShaderSource(vertexShader, 1, (char const* const*)&vertexShaderSource, NULL); 107 glCompileShader(vertexShader); 108 109 /* Check if the Vertex Shader compiled succesfully */ 110 glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); 111 if(!success) { 112 glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); 113 fprintf(stderr, "OpenGL: Vertex Shader Compilation failed\n%s\n", 114 infoLog); 115 } 116 117 /* Fragment Shader */ 118 if(!(fragmentShaderSource = loadShaderFromFile(FRAGMENT_SHADER_FILE_NAME))) { 119 fprintf(stderr, "could not load shader from file \"%s\n\"", 120 FRAGMENT_SHADER_FILE_NAME); 121 return 1; 122 } 123 124 fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); 125 glShaderSource(fragmentShader, 1, (char const* const*)&fragmentShaderSource, NULL); 126 glCompileShader(fragmentShader); 127 128 /* Check if the Fragment Shader compiled succesfully */ 129 glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); 130 if(!success) { 131 glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); 132 fprintf(stderr, "OpenGL: Fragment Shader Compilation failed\n%s\n", 133 infoLog); 134 } 135 136 /* Shader Program */ 137 shaderProgram = glCreateProgram(); 138 glAttachShader(shaderProgram, vertexShader); 139 glAttachShader(shaderProgram, fragmentShader); 140 glLinkProgram(shaderProgram); 141 142 /* Check if linking program failed */ 143 glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); 144 if(!success) { 145 glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); 146 fprintf(stderr, "OpenGL: Linking Program with Shaders failed\n%s\n", 147 infoLog); 148 } 149 150 unsigned int gScaleLocation = glGetUniformLocation(shaderProgram, "scale"); 151 152 /* Free memory */ 153 free(vertexShaderSource); 154 free(fragmentShaderSource); 155 glDeleteShader(vertexShader); 156 glDeleteShader(fragmentShader); 157 158 glGenVertexArrays(1, &VAO); 159 glBindVertexArray(VAO); 160 161 /* Linking Vertex attributes */ 162 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 163 2 * sizeof(float), (void *)0); 164 165 glEnableVertexAttribArray(0); 166 glUseProgram(shaderProgram); 167 glBindVertexArray(VAO); 168 169 /* main loop */ 170 time = glfwGetTime(); 171 double prev_time = 0.0; 172 double delta_time = 0.0f; 173 174 static float ds = 0.0025f; 175 static float scale = 0.5f; 176 while (!glfwWindowShouldClose(win)) { 177 glClear(GL_COLOR_BUFFER_BIT); 178 179 scale += ds; 180 if((scale >= 0.75f) || (scale <= 0.5f)) 181 ds *= -1.0f; 182 183 glUniform1f(gScaleLocation, scale); 184 185 glDrawArrays(GL_TRIANGLES, 0, 3); 186 glfwSwapBuffers(win); 187 glfwPollEvents(); 188 189 double cur_time = glfwGetTime(); 190 delta_time = cur_time - prev_time; 191 time += delta_time; 192 prev_time = cur_time; 193 } 194 195 glDeleteVertexArrays(1, &VAO); 196 glDeleteBuffers(1, &VBO); 197 glDeleteProgram(shaderProgram); 198 199 glfwDestroyWindow(win); 200 glfwTerminate(); 201 return 0; 202 }