main.c (7264B)
1 #include <math.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 #include <glad/glad.h> 7 #include <GLFW/glfw3.h> 8 9 #include "main.h" 10 #include "glm.h" 11 #include "err.h" 12 #define STB_IMAGE_IMPLEMENTATION 13 #define STBI_NO_SIMD // TODO: confirm this workaround. 14 #include "stb_image.h" 15 16 int rotating = 0; 17 float alpha = 0.2; 18 19 void 20 framebuffer_size_callback(GLFWwindow *window, int width, int height) 21 { 22 glViewport(0, 0, width, height); 23 } 24 25 void 26 processInput(GLFWwindow *window) 27 { 28 static int spacePressing = 0; 29 if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) 30 glfwSetWindowShouldClose(window, 1); 31 else if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS) { 32 if (!spacePressing) { 33 spacePressing = 1; 34 rotating = !rotating; 35 } 36 } else if (glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_RELEASE && 37 spacePressing == 1) { 38 spacePressing = 0; 39 } else if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) { 40 alpha += 0.01; 41 if (alpha > 1.0) 42 alpha = 1.0; 43 } else if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) { 44 alpha -= 0.01; 45 if (alpha < 0) 46 alpha = 0; 47 } 48 } 49 50 int 51 main(void) 52 { 53 int width = 600; 54 int height = 600; 55 56 float vertices[] = { 57 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 58 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 59 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 60 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 61 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 62 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 63 64 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 65 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 66 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 67 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 68 -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 69 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 70 71 -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 72 -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 73 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 74 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 75 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 76 -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 77 78 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 79 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 80 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 81 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 82 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 83 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 84 85 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 86 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 87 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 88 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 89 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 90 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 91 92 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 93 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 94 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 95 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 96 -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 97 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f 98 }; 99 100 int numCube = 3; 101 vec *cubePositions[numCube]; 102 cubePositions[0] = vecMake((float []){-2.0, 0.0, -2.0}, 3); 103 cubePositions[1] = vecMake((float []){0.0, 0.0, 0.0}, 3); 104 cubePositions[2] = vecMake((float []){1.0, 1.0, -1.0}, 3); 105 mat *modelMat[numCube]; 106 for (int i = 0; i < numCube; i++) { 107 modelMat[i] = scale(matMakeIdent(4), 0.1); 108 translate(modelMat[i], cubePositions[i]); 109 } 110 mat *projMat = matMakePers((float)M_PI/4, (float)width/(float)height, 111 0.1, 100.0); 112 vec *cameraPos = vecMake((float[]){4.0, 1.0, 4.0}, 3); 113 vec *cameraTarget = vecMake((float[]){0.0, 0.0, 0.0}, 3); 114 vec *cameraUp = vecMake((float[]){0.0, 1.0, 0.0}, 3); 115 mat *viewMat = matMakeLookAt(cameraPos, cameraTarget, cameraUp); 116 vec *axis0 = vecMake((float[]){1.41421356/2, 1.41421356/2, 0.0}, 3); 117 vec *axis1 = vecMake((float[]){0.0, 1.0, 0.0}, 3); 118 119 // initialize glfw 120 glfwInit(); 121 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 122 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 123 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 124 125 // create glfw window 126 GLFWwindow *window = glfwCreateWindow(width, height, "opengl", 127 NULL, NULL); 128 if (window == NULL) { 129 fprintf(stderr, "main: failed to open window\n"); 130 glfwTerminate(); 131 exit(1); 132 } 133 glfwMakeContextCurrent(window); 134 135 // load function pointers 136 if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { 137 fprintf(stderr, "main: failed to initialize glad\n"); 138 exit(1); 139 } 140 141 // register callback functions 142 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); 143 144 // setup shaders 145 Shader *shader = ShaderInit("shaders/vertex.sl", "shaders/fragment.sl"); 146 if (shader == NULL) { 147 fprintf(stderr, "init shader: %s\n", errstr); 148 exit(1); 149 } 150 ShaderUse(shader); 151 152 // setup vbo 153 unsigned int VAO, VBO; 154 glGenVertexArrays(1, &VAO); 155 glGenBuffers(1, &VBO); 156 glBindVertexArray(VAO); 157 glBindBuffer(GL_ARRAY_BUFFER, VBO); 158 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 159 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), 160 (void *)0); 161 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), 162 (void *)(3*sizeof(float))); 163 glEnableVertexAttribArray(0); 164 glEnableVertexAttribArray(1); 165 166 // setup texture 167 int nTex = 2; 168 unsigned int textures[nTex]; 169 char *texfiles[nTex]; 170 texfiles[0] = "img/wall.jpg"; 171 texfiles[1] = "img/awesomeface.jpg"; 172 glGenTextures(nTex, textures); 173 for (int i = 0; i < nTex; i++) { 174 glActiveTexture(GL_TEXTURE0 + i); 175 glBindTexture(GL_TEXTURE_2D, textures[i]); 176 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 177 GL_REPEAT); 178 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 179 GL_REPEAT); 180 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 181 GL_LINEAR_MIPMAP_LINEAR); 182 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 183 int width, height; 184 unsigned char *data = stbi_load(texfiles[i], &width, &height, 185 NULL, 0); 186 if (data == NULL) { 187 fprintf(stderr, "can't load texture: %s\n", texfiles[i]); 188 exit(1); 189 } 190 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, 191 GL_UNSIGNED_BYTE, data); 192 glGenerateMipmap(GL_TEXTURE_2D); 193 stbi_image_free(data); 194 } 195 196 glEnable(GL_DEPTH_TEST); 197 198 float lastTime = (float) glfwGetTime(); 199 float rotation = 0; 200 201 while (!glfwWindowShouldClose(window)) { 202 processInput(window); 203 204 glClearColor(1.0, 1.0, 0.8, 1.0); 205 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 206 207 ShaderSetFloat(shader, "alpha", alpha); 208 glUniform1i(glGetUniformLocation(shader->ID, "texture0"), 0); 209 glUniform1i(glGetUniformLocation(shader->ID, "texture1"), 1); 210 unsigned int tloc = glGetUniformLocation(shader->ID, "transform"); 211 float now = (float) glfwGetTime(); 212 if (rotating) { 213 rotation += now-lastTime; 214 } 215 mat *view = matCopy(viewMat); 216 rotate(view, rotation, axis1); 217 for (int i = 0; i < numCube; i++) { 218 mat *transform = matCopy(modelMat[i]); 219 rotate(transform, rotation, axis0); 220 ShaderSetMat4(shader, "model", matDataPtr(transform)); 221 ShaderSetMat4(shader, "view", matDataPtr(view)); 222 ShaderSetMat4(shader, "proj", matDataPtr(projMat)); 223 glDrawArrays(GL_TRIANGLES, 0, 36); 224 matFree(transform); 225 } 226 matFree(view); 227 228 lastTime = now; 229 230 glfwPollEvents(); 231 glfwSwapBuffers(window); 232 } 233 234 235 vecFree(cameraPos); 236 vecFree(cameraTarget); 237 vecFree(cameraUp); 238 239 vecFree(axis0); 240 vecFree(axis1); 241 for (int i = 0; i < sizeof(cubePositions)/sizeof(cubePositions[0]); i++) { 242 vecFree(cubePositions[i]); 243 matFree(modelMat[i]); 244 } 245 matFree(viewMat); 246 matFree(projMat); 247 248 glDeleteVertexArrays(1, &VAO); 249 glDeleteBuffers(1, &VBO); 250 ShaderDelete(shader); 251 glfwTerminate(); 252 253 if (matCount() != 0) { 254 fprintf(stderr, "%d mats not freed\n", matCount()); 255 assert(0); 256 } 257 if (vecCount() != 0) { 258 fprintf(stderr, "%d vecs not freed\n", vecCount()); 259 assert(0); 260 } 261 return 0; 262 }