diff --git a/README.md b/README.md index 5bd320e..b59d05a 100644 --- a/README.md +++ b/README.md @@ -161,15 +161,15 @@ möglichst viele der folgenden Anforderungen erfüllen: - [X] sinnvolle Aufteilung des Codes auf mehrere Dateien (insb. Shader-Code in separaten Dateien) - [X] Datentypen und Hilfsfunktionen für Shader, Geometriedaten, Texturen -- [?] Überprüfung übergebener Funktionsparameter durch Assertions (soweit möglich) +- [X] Überprüfung übergebener Funktionsparameter durch Assertions (soweit möglich) - [X] Tests für alle Matrixfunktionen - [x] Strukturierung der Szene durch einen einfachen Szenengraph - [X] einfache Benutzerinteraktion mit Kamera und/oder Objekten (z. B. über Tastatur) - [X] Beleuchtung der Szene mit mehr als einer Lichtquelle - [X] gleichzeitige Verwendung von mindestens zwei Texturen in einem Objekt -- [?] gleichzeitige Verwendung von mindestens zwei verschiedenen Shader-Programmen in einer Szene +- [X] gleichzeitige Verwendung von mindestens zwei verschiedenen Shader-Programmen in einer Szene - [ ] transparente Objekte -- [?] Verwendung einer Umgebungstextur +- [X] Verwendung einer Umgebungstextur - [?] Spiegelung der Umgebungstextur auf einigen Objekten - [ ] Nebel in einer komplexen 3D-Szene diff --git a/src/Makefile b/src/Makefile index cd091c7..c27ad1f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,7 +5,7 @@ OTHER_LIBS = -lm ALL_LIBS = $(GLEW_LIBS) $(GLFW_LIBS) $(OTHER_LIBS) OBJ = matrixMath.o transformation.o wavefrontobj.o sceneGraph.o objectHandler.o shader.o -SHADERS = fragmentShader.c vertexShader.c +SHADERS = fragmentShader.c vertexShader.c skyboxFragmentShader.c skyboxVertexShader.c cg1.out: test.out main.o $(OBJ) $(SHADERS) ./test.out diff --git a/src/main.c b/src/main.c index 540b84b..fbbdc11 100644 --- a/src/main.c +++ b/src/main.c @@ -9,6 +9,10 @@ #include "vertexShader.c" #include "fragmentShader.c" + +#include "skyboxVertexShader.c" +#include "skyboxFragmentShader.c" + #include "objectHandler.h" #include "matrixMath.h" #include "transformation.h" @@ -18,6 +22,10 @@ #include "inputHandler.c" GLuint program; +GLuint skyboxProgram; + +ObjectData* skyboxObject; +GLuint skyboxTexture; #define NUM_TEXTURES 5 @@ -47,11 +55,12 @@ 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.0f, 3.0f, 5.5f}; -bool cameraTraveling = true; +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; @@ -114,56 +123,76 @@ void renderNode(SceneNode* node) { draw_object(node->model->objectData); } -void init(void) { - //IDEE: shader in array speichern und dann so kompilieren etc - GLint status; - - Shader shaders[2] = { - {GL_VERTEX_SHADER, 0}, - {GL_FRAGMENT_SHADER, 0} - }; - - const GLchar* shaderSources[2] = { - vertexShader_glsl, - fragmentShader_glsl - }; - - int numShaders = sizeof(shaders) / sizeof(Shader); - compileShaders(shaders, shaderSources, numShaders); - - program = glCreateProgram(); - - // das müsste evtl noch angepasst werden - for (int i = 0; i < numShaders; i++) { - glAttachShader(program, shaders[i].id); - } - glLinkProgram(program); - - - glGetProgramiv(program, GL_LINK_STATUS, &status); +void linkAndValidateProgram(GLuint prog) { + GLuint status; + glLinkProgram(prog); + glGetProgramiv(prog, GL_LINK_STATUS, &status); if (!status) { printf("Error linking program: "); GLchar infoLog[1024]; - glGetProgramInfoLog(program, 1024, NULL, infoLog); - printf("%s",infoLog); + glGetProgramInfoLog(prog, 1024, NULL, infoLog); + printf("%d - %s\n",status, infoLog); exit(1); } - glValidateProgram(program); + glValidateProgram(prog); - glGetProgramiv(program, GL_VALIDATE_STATUS, &status); - + glGetProgramiv(prog, GL_VALIDATE_STATUS, &status); + if (!status) { printf("Error validating program: "); GLchar infoLog[1024]; - glGetProgramInfoLog(program, 1024, NULL, infoLog); - printf("%s",infoLog); + 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(); + - stbi_set_flip_vertically_on_load(flipFlag); // --------------- READ SCENE GRAPH + setFlipBit(1); setNodeRenderFunction(&renderNode); // read scene graph @@ -185,6 +214,33 @@ void updateStats() { 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. */ @@ -210,7 +266,6 @@ void draw(void) { handleInputs(deltaTime); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glUseProgram(program); // step for rotations // counts up to 1.0 and then resets back to 0.0 forever @@ -241,11 +296,18 @@ void draw(void) { GLfloat fovy = pi / 2; normalisedDeviceCoordinatesFov(&normalisationTransformation, fovy, aspectRatio, near, far); - mat4 projection; 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 diff --git a/src/sceneGraph.c b/src/sceneGraph.c index 06bff09..661d461 100644 --- a/src/sceneGraph.c +++ b/src/sceneGraph.c @@ -29,6 +29,47 @@ void (*renderFunction)(SceneNode*); +void setFlipBit(int flip) { + stbi_set_flip_vertically_on_load(flip); +} + +unsigned int loadCubemap(void) { + char* faces[6] = { + "../texture/skybox/right.jpg", + "../texture/skybox/left.jpg", + "../texture/skybox/top.jpg", + "../texture/skybox/bottom.jpg", + "../texture/skybox/front.jpg", + "../texture/skybox/back.jpg" + }; + + unsigned int textureID; + glGenTextures(1, &textureID); + glBindTexture(GL_TEXTURE_CUBE_MAP, textureID); + + int width, height, nrChannels; + for (unsigned int i = 0; i < 6; i++) { + unsigned char* image = stbi_load(faces[i], &width, &height, &nrChannels, 0); + if (image) { + + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); + stbi_image_free(image); + + } else { + fprintf(stderr, "Cubemap text failed to load at path: %s", faces[i]); + stbi_image_free(image); + exit(1); + } + } + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + return textureID; +} + void setNodeRenderFunction(void (*newRenderFunction)(SceneNode*)) { renderFunction = newRenderFunction; } diff --git a/src/sceneGraph.h b/src/sceneGraph.h index ac18022..6d75639 100644 --- a/src/sceneGraph.h +++ b/src/sceneGraph.h @@ -43,5 +43,7 @@ extern void renderSceneNode(SceneNode* node); extern void freeSceneNode(SceneNode* node); extern void printSceneGraph(SceneNode* root, int level); extern SceneNode* loadSceneGraphFromFile(char* path); +extern unsigned int loadCubemap(void); +extern void setFlipBit(int flip); #endif \ No newline at end of file diff --git a/src/skyboxFragmentShader.glsl b/src/skyboxFragmentShader.glsl new file mode 100644 index 0000000..5e23ab1 --- /dev/null +++ b/src/skyboxFragmentShader.glsl @@ -0,0 +1,10 @@ +#version 330 core + +in vec3 TexCoords; + +uniform samplerCube skybox; + +void main() +{ + gl_FragColor = texture(skybox, TexCoords); +} \ No newline at end of file diff --git a/src/skyboxVertexShader.glsl b/src/skyboxVertexShader.glsl new file mode 100644 index 0000000..8050685 --- /dev/null +++ b/src/skyboxVertexShader.glsl @@ -0,0 +1,12 @@ +#version 330 core + +layout (location = 0) in vec3 aPos; +out vec3 TexCoords; + +uniform mat4 projection; +uniform mat4 view; + +void main() { + TexCoords = aPos; + gl_Position = projection * view * vec4(aPos, 1.0); +} \ No newline at end of file diff --git a/texture/skybox/back.jpg b/texture/skybox/back.jpg new file mode 100644 index 0000000..470a679 Binary files /dev/null and b/texture/skybox/back.jpg differ diff --git a/texture/skybox/bottom.jpg b/texture/skybox/bottom.jpg new file mode 100644 index 0000000..893f394 Binary files /dev/null and b/texture/skybox/bottom.jpg differ diff --git a/texture/skybox/front.jpg b/texture/skybox/front.jpg new file mode 100644 index 0000000..4e17b77 Binary files /dev/null and b/texture/skybox/front.jpg differ diff --git a/texture/skybox/left.jpg b/texture/skybox/left.jpg new file mode 100644 index 0000000..5750b91 Binary files /dev/null and b/texture/skybox/left.jpg differ diff --git a/texture/skybox/right.jpg b/texture/skybox/right.jpg new file mode 100644 index 0000000..8963037 Binary files /dev/null and b/texture/skybox/right.jpg differ diff --git a/texture/skybox/top.jpg b/texture/skybox/top.jpg new file mode 100644 index 0000000..4db3c2a Binary files /dev/null and b/texture/skybox/top.jpg differ