#include #include #include #include "vertexShader.c" #include "fragmentShader.c" #include #include #include #define RESTART 345678 typedef struct { GLfloat x; GLfloat y; GLfloat z; GLfloat value; } Point; GLuint program; GLuint vao; GLuint indicesBufferObject; GLfloat aspectRatio = 1.0f; GLfloat step = 0.0f; GLfloat corners[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 0.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 0.0f }; GLuint indices[] = { 0, 1, 0, 2, 0, 4, 1, 3, 1, 5, 2, 3, 2, 6, 3, 7, 4, 5, 4, 6, 5, 7, 6, 7 }; // CREATE 4x4 IDENTITY MATRIX void identity(GLfloat* out) { for (int i = 0; i < 16; i++) { out[i] = (i % 4 == i / 4); } } // CREATE 4x4 TRANSLATION MATRIX void translation(GLfloat* out, GLfloat* v) { identity(out); for (int i = 0; i < 3; i++) { out[3 * 4 + i] = v[i]; } } // CREATE 4x4 SCALING MATRIX void scaling(GLfloat* out, GLfloat* v) { identity(out); for (int i = 0; i < 3; i++) { out[i * 5] = v[i]; } } // CREATE 4x4 ROTATION MATRIX AROUND Z AXIS /* cos a -sin a 0 0 * sin a cos a 0 0 * 0 0 1 0 * 0 0 0 1 */ void rotationZ(GLfloat* out, GLfloat angle) { identity(out); out[0] = cos(angle); out[1] = sin(angle); out[4] = -sin(angle); out[5] = cos(angle); } void rotationY(GLfloat* out, GLfloat angle) { identity(out); out[0] = cos(angle); out[2] = -sin(angle); out[8] = sin(angle); out[10] = cos(angle); } void rotationX(GLfloat* out, GLfloat angle) { identity(out); out[5] = cos(angle); out[6] = sin(angle); out[9] = -sin(angle); out[10] = cos(angle); } // MULTIPLY ANY TO MATRICES void multiplyAny(GLfloat* A, GLfloat* B, GLfloat* out, int wA, int hA, int wB) { int sizeOut = hA * wB; GLfloat* result = (GLfloat*) malloc(sizeOut * sizeof(GLfloat)); for (int i = 0; i < sizeOut; i++) { result[i] = 0; // printf("%d: ", i); for (int j = 0; j < wA; j++) { // printf("%d : %f ", j * hA + i % hA, A[j * hA + i % hA]); result[i] += A[j * hA + i % hA] * B[j + i / hA * wB]; } // printf("\n"); } memcpy(out, result, sizeOut * sizeof(GLfloat)); free(result); } // MULTIPLY TWO 4x4 MATRICES void multiply(GLfloat* A, GLfloat* B, GLfloat* out) { multiplyAny(A, B, out, 4, 4, 4); } // MULTIPLY 4x4 MATRIX WITH VEC4 void multiplyV(GLfloat* M, GLfloat* v, GLfloat* out) { multiplyAny(M, v, out, 4, 4, 1); } // MULTIPLY in WITH TRANSLATION MATRIX OF v void translate(GLfloat* out, GLfloat* in, GLfloat* v) { GLfloat translationMatrix[16]; translation(translationMatrix, v); multiply(translationMatrix, in, out); } // MULTIPLY in WITH SCALING MATRIX OF v void scale(GLfloat* out, GLfloat* in, GLfloat* v) { GLfloat scalingMatrix[16]; scaling(scalingMatrix, v); multiply(scalingMatrix, in, out); } // MULTIPLY in WITH ROTATION MATRIX OF a AROUND Z AXIS void rotateZ(GLfloat* out, GLfloat* in, GLfloat angle) { GLfloat rotationMatrix[16]; rotationZ(rotationMatrix, angle); multiply(rotationMatrix, in, out); } // MULTIPLY in WITH ROTATION MATRIX OF a AROUND Y AXIS void rotateY(GLfloat* out, GLfloat* in, GLfloat angle) { GLfloat rotationMatrix[16]; rotationY(rotationMatrix, angle); multiply(rotationMatrix, in, out); } // MULTIPLY in WITH ROTATION MATRIX OF a AROUND X AXIS void rotateX(GLfloat* out, GLfloat* in, GLfloat angle) { GLfloat rotationMatrix[16]; rotationX(rotationMatrix, angle); multiply(rotationMatrix, in, out); } void init(void) { // create and compile vertex shader GLchar *vertexText = malloc(vertexShader_glsl_len); memcpy(vertexText, vertexShader_glsl, vertexShader_glsl_len); const GLchar *vertexTextConst = vertexText; GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexTextConst, &vertexShader_glsl_len); glCompileShader(vertexShader); GLint status; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status); if (!status) { printf("Error compiling vertex shader: "); GLchar infoLog[1024]; glGetShaderInfoLog(vertexShader, 1024, NULL, infoLog); printf("%s",infoLog); } free(vertexText); vertexText = NULL; vertexTextConst = NULL; // create and compile fragment shader GLchar *fragmentText = malloc(fragmentShader_glsl_len); memcpy(fragmentText, fragmentShader_glsl, fragmentShader_glsl_len); const GLchar *fragmentTextConst = fragmentText; GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentTextConst, &fragmentShader_glsl_len); glCompileShader(fragmentShader); glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status); if (!status) { printf("Error compiling fragment shader: "); GLchar infoLog[1024]; glGetShaderInfoLog(fragmentShader, 1024, NULL, infoLog); printf("%s",infoLog); } free(fragmentText); fragmentText = NULL; fragmentTextConst = NULL; // create and link shader program program = glCreateProgram(); glAttachShader(program, vertexShader); glAttachShader(program, fragmentShader); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &status); if (!status) { printf("Error linking program: "); GLchar infoLog[1024]; glGetProgramInfoLog(program, 1024, NULL, infoLog); printf("%s",infoLog); } glValidateProgram(program); glGetProgramiv(program, GL_VALIDATE_STATUS, &status); if (!status) { printf("Error validating program: "); GLchar infoLog[1024]; glGetProgramInfoLog(program, 1024, NULL, infoLog); printf("%s",infoLog); } GLuint triangleVertexBufferObject; glGenBuffers(1, &triangleVertexBufferObject); glBindBuffer(GL_ARRAY_BUFFER, triangleVertexBufferObject); glBufferData(GL_ARRAY_BUFFER, sizeof(corners), corners, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); // create vertex array object glGenVertexArrays(1, &vao); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, triangleVertexBufferObject); glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, sizeof(Point), 0 ); glEnableVertexAttribArray(0); glVertexAttribPointer( 1, 1, GL_FLOAT, GL_FALSE, sizeof(Point), (GLvoid*)(3 * sizeof(GLfloat)) ); glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); // ENABLE BACKFACE CULLING glFrontFace(GL_CW); glEnable(GL_CULL_FACE); glEnable(GL_PRIMITIVE_RESTART); glPrimitiveRestartIndex(RESTART); // DEFINE INDEX ARRAY FOR ELEMENT DRAWING glGenBuffers(1, &indicesBufferObject); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesBufferObject); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); } void draw(void) { glClear(GL_COLOR_BUFFER_BIT); glUseProgram(program); glBindVertexArray(vao); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indicesBufferObject); step += 0.001f; if (step > 1.0f) step -= 1.0f; GLfloat M[16]; GLfloat scaleFactor = sin(step * 3.14159f * 2) * 0.1f + 0.2f; // GLfloat scaleFactor = 0.2f; GLfloat scaleBy[3] = {scaleFactor / aspectRatio, scaleFactor, scaleFactor}; GLfloat translateBy[3] = {sin(step * 3.14159f * 4.0f), 0.0f, 0.0f}; identity(M); rotateY(M, M, step * 3.14159f * 2); rotateZ(M, M, step * 3.14159f * 2 + 0.5f); rotateX(M, M, step * 3.14159f * 2 + 1.0f); scale(M, M, scaleBy); // translate(M, M, translateBy); glUniformMatrix4fv(glGetUniformLocation(program, "transformation"), 1, GL_FALSE, M); glDrawElements(GL_LINES, sizeof(indices) / sizeof(GLuint), GL_UNSIGNED_INT, NULL); } void framebuffer_size_callback(GLFWwindow *window, int width, int height) { glViewport(0, 0, width, height); aspectRatio = (float)width / height; } int main(void) { // GLfloat A[16]; // GLfloat B[16]; // GLfloat v[] = {1.0f, 2.0f, 3.0f}; // GLfloat angle = 1.5f; // identity(A); // identity(B); // multiplyAny(A, B, A, 4, 4, 4); // translate(A, A, v); // scale(A, A, v); // rotateZ(A, A, angle); // // DEBUG // // PRINT COLUMN MAJOR MATRIX // for (int i = 0; i < 16; i++) { // if (i != 0 && i % 4 == 0) printf("\n"); // // cursed stuff to print column major form // printf("%.2f ", A[i % 4 * 4 + i / 4]); // } // printf("\n"); // // ------ // return 0; glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); GLFWwindow *window = glfwCreateWindow(600, 600, "Computergrafik 1", NULL, NULL); if (!window) { printf("Failed to create window\n"); glfwTerminate(); return -1; } glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwMakeContextCurrent(window); glewInit(); printf("OpenGL version supported by this platform (%s):\n", glGetString(GL_VERSION)); init(); while (!glfwWindowShouldClose(window)) { draw(); glfwSwapBuffers(window); glfwPollEvents(); } glfwTerminate(); return 0; }