#include #include #include #include #include #include #include #include #include "vertexShader.c" #include "fragmentShader.c" #include "skyboxVertexShader.c" #include "skyboxFragmentShader.c" #include "objectHandler.h" #include "matrixMath.h" #include "transformation.h" #include "wavefrontobj.h" #include "sceneGraph.h" #include "shader.h" #include "inputHandler.c" GLuint program; GLuint skyboxProgram; ObjectData* skyboxObject; GLuint skyboxTexture; #define NUM_TEXTURES 5 #define DAY 0 #define NIGHT 1 #define CLOUDS 2 #define OCEAN 3 #define NORMAL 4 int flipFlag = 1; bool exitRequested = false; GLFWwindow* window; GLfloat aspectRatio = 1.0f; double timeBetweenUpdates = 0.2f; double timeSinceUpdate = 0.0f; int framesSinceUpdate = 0; GLfloat step = 0.0f; const GLfloat pi = 3.14159f; vec3 origin = {0.0f, 0.0f, 0.0f}; vec3 cameraPosition = {0.0f, 2.0f, 1.0f}; vec3 objectPosition = {0.0f, 0.0f, 0.0f}; vec3 cameraTravelPosition = {0.3f, 0.3f, 0.3f}; bool cameraTraveling = false; GLfloat radius = 1.0f; mat4 viewingTransformation; mat4 projection; // Define a global scene graph root node SceneNode* rootNode; void renderNode(SceneNode* node) { assert(node != NULL); if (!node->model) return; mat4 modelView; identity(&modelView); multiply(&modelView, &node->worldTransformation, &modelView); multiply(&modelView, &viewingTransformation, &modelView); // calculate matrix for normals mat3 normalModelView; mat3From4(&normalModelView, &modelView); mat3Inverse(&normalModelView, &normalModelView); mat3Transpose(&normalModelView, &normalModelView); // send transformation matrix to shader glUniformMatrix4fv(glGetUniformLocation(program, "modelView"), 1, GL_FALSE, (GLfloat*)&modelView); glUniformMatrix3fv(glGetUniformLocation(program, "normalModelView"), 1, GL_FALSE, (GLfloat*)&normalModelView); // SET MATERIAL DATA glUniform1f(glGetUniformLocation(program, "shininess"), node->model->shininess * 4.0f); // BIND TEXTURES GLuint textureLocation; textureLocation = glGetUniformLocation(program, "textureSampler"); glUniform1i(textureLocation, 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, node->model->texture); if (node->model->secondaryTexture != -1) { glUniform1i(glGetUniformLocation(program, "useSecondaryTexture"), 1); glUniform1i(glGetUniformLocation(program, "secondaryTexture"), 1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, node->model->secondaryTexture); } else { glUniform1i(glGetUniformLocation(program, "useSecondaryTexture"), 0); } if (node->model->normalMap != -1) { glUniform1i(glGetUniformLocation(program, "useNormalMap"), 1); glUniform1i(glGetUniformLocation(program, "normalMap"), 2); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, node->model->normalMap); } else { glUniform1i(glGetUniformLocation(program, "useNormalMap"), 0); } draw_object(node->model->objectData); } void linkAndValidateProgram(GLuint prog) { GLuint status; glLinkProgram(prog); glGetProgramiv(prog, GL_LINK_STATUS, &status); if (!status) { printf("Error linking program: "); GLchar infoLog[1024]; glGetProgramInfoLog(prog, 1024, NULL, infoLog); printf("%d - %s\n",status, infoLog); exit(1); } glValidateProgram(prog); glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); if (!status) { printf("Error validating program: "); GLchar infoLog[1024]; glGetProgramInfoLog(prog, 1024, NULL, infoLog); printf("%d - %s\n",status, infoLog); exit(1); } } void init(void) { //IDEE: shader in array speichern und dann so kompilieren etc Shader shaders[4] = { {GL_VERTEX_SHADER, 0}, {GL_FRAGMENT_SHADER, 0}, {GL_VERTEX_SHADER, 0}, {GL_FRAGMENT_SHADER, 0} }; const GLchar* shaderSources[4] = { vertexShader_glsl, fragmentShader_glsl, skyboxVertexShader_glsl, skyboxFragmentShader_glsl, }; int numShaders = sizeof(shaders) / sizeof(Shader); compileShaders(shaders, shaderSources, 4); program = glCreateProgram(); // das müsste evtl noch angepasst werden glAttachShader(program, shaders[0].id); glAttachShader(program, shaders[1].id); linkAndValidateProgram(program); printf("Default Program OK\n"); ///// SKYBOX PROGRAM skyboxProgram = glCreateProgram(); glAttachShader(skyboxProgram, shaders[2].id); glAttachShader(skyboxProgram, shaders[3].id); linkAndValidateProgram(skyboxProgram); printf("Skybox Program OK\n"); skyboxObject = readSingleObjFile("../obj/cube/cube.obj"); skyboxTexture = loadCubemap(); // --------------- READ SCENE GRAPH setFlipBit(1); setNodeRenderFunction(&renderNode); // read scene graph rootNode = loadSceneGraphFromFile("../scene-graph.scg"); // ENABLE BACKFACE CULLING glFrontFace(GL_CCW); glEnable(GL_CULL_FACE); // ENABLE DEPTH BUFFER glEnable(GL_DEPTH_TEST); glClearColor(0.1f, 0.1f, 0.1f, 1.0f); } void updateStats() { printf("\rFPS: %.1f", framesSinceUpdate / timeSinceUpdate); printf(" - Camera Position: [%f, %f, %f] - Traveling: %s ", cameraPosition.x, cameraPosition.y, cameraPosition.z, cameraTraveling ? "true" : "false"); fflush(stdout); } void drawSkybox(void) { glUseProgram(skyboxProgram); glDepthMask(GL_FALSE); glDisable(GL_CULL_FACE); mat4 view = viewingTransformation; view.m30 = 0; view.m31 = 0; view.m32 = 0; view.m33 = 1; view.m23 = 0; view.m13 = 0; view.m03 = 0; glUniformMatrix4fv(glGetUniformLocation(skyboxProgram, "view"), 1, GL_FALSE, (GLfloat*)&view); glUniformMatrix4fv(glGetUniformLocation(skyboxProgram, "projection"), 1, GL_FALSE, (GLfloat*)&projection); glBindVertexArray(skyboxObject->vao); glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxTexture); draw_object(skyboxObject); glDepthMask(GL_TRUE); } /** * Main draw function. */ void draw(void) { handleCameraTravel(); // FPS Counter framesSinceUpdate++; double deltaTime = glfwGetTime(); timeSinceUpdate += deltaTime; glfwSetTime(0.0f); if (timeSinceUpdate >= timeBetweenUpdates) { updateStats(); timeSinceUpdate = 0.0f; framesSinceUpdate = 0; } // camera movement handleInputs(deltaTime); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // step for rotations // counts up to 1.0 and then resets back to 0.0 forever step += deltaTime / 15; if (step > 1.0f) step -= 1.0f; if (step < 0.0f) step += 1.0f; //SceneNode* box3 = findNodeByName("box3", rootNode); //rotateY(&box3->transformation, &box3->transformation, 0.001); //updateSceneNode(rootNode, NULL); // step multiplied by pi * 2 for use in rotation and trig functions GLfloat stepi = step * pi * 2; // ------------- VIEWING TRANSFORMATION ------------------- vec3 up = {0.0f, 1.0f, 0.0f}; lookAt(&viewingTransformation, &cameraPosition, &origin, &up); // -------------- PROJECTION TRANSFORMATION ---------------- mat4 projectionTransformation; GLfloat near = 0.1f; GLfloat far = 40.0f; perspectiveProjection(&projectionTransformation, near, far); // -------------- NORMALISATION TRANSFORMATION ------------- mat4 normalisationTransformation; GLfloat fovy = pi / 2; normalisedDeviceCoordinatesFov(&normalisationTransformation, fovy, aspectRatio, near, far); identity(&projection); multiply(&projection, &projectionTransformation, &projection); multiply(&projection, &normalisationTransformation, &projection); drawSkybox(); glEnable(GL_CULL_FACE); glUseProgram(program); glUniformMatrix4fv(glGetUniformLocation(program, "projection"), 1, GL_FALSE, (GLfloat*)&projection); // SET LIGHT DATA glUniform4f(glGetUniformLocation(program, "lightColor"), 0.2f, 0.2f, 0.2f, 0.5f); glUniform4f(glGetUniformLocation(program, "ambientLight"), 0.05f, 0.05f, 0.05f, 1.0f); vec4 lightPosition = {cos(stepi) * 5.0f, 5.0f, sin(stepi) * 5.0f, 1.0f}; multiplyAny((GLfloat*)&lightPosition, (GLfloat*)&viewingTransformation, (GLfloat*)&lightPosition, 4, 4, 1); glUniform3f(glGetUniformLocation(program, "lightPositions[0]"), lightPosition.x, lightPosition.y, lightPosition.z); glUniform3f(glGetUniformLocation(program, "lightPositions[1]"), -lightPosition.x, lightPosition.y, -lightPosition.z); glUniform1f(glGetUniformLocation(program, "lightBrightness[0]"), 0.5f); glUniform1f(glGetUniformLocation(program, "lightBrightness[1]"), 0.5f); renderSceneNode(rootNode); } /** * Changes viewport size and adjust aspect ratio when changing window size */ void framebuffer_size_callback(GLFWwindow *window, int width, int height) { glViewport(0, 0, width, height); aspectRatio = (float)width / height; } /** * Main function. */ int main(int argc, char **argv) { // initialise window glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); window = glfwCreateWindow(700, 700, "Computergrafik 1", NULL, NULL); if (!window) { printf("Failed to create window\n"); glfwTerminate(); return -1; } glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); glfwMakeContextCurrent(window); // disable framerate cap glfwSwapInterval(0); // register keyboard event handler glfwSetKeyCallback(window, keyboardHandler); // initialise glew glewInit(); printf("OpenGL version supported by this platform (%s):\n", glGetString(GL_VERSION)); init(); // exit when window should close or exit is requested (ESC) while (!glfwWindowShouldClose(window) && !exitRequested) { draw(); glfwSwapBuffers(window); glfwPollEvents(); } glfwTerminate(); return 0; }