diff --git a/enc_temp_folder/56a7f5f31b1538028f7329a2820dd5/main.cpp b/enc_temp_folder/56a7f5f31b1538028f7329a2820dd5/main.cpp deleted file mode 100644 index f4cb614..0000000 --- a/enc_temp_folder/56a7f5f31b1538028f7329a2820dd5/main.cpp +++ /dev/null @@ -1,555 +0,0 @@ -#define STB_IMAGE_IMPLEMENTATION -#include "glew.h" -#include "freeglut.h" -#include "glm.hpp" -#include "ext.hpp" -#include -#include -#include -#include -#include "Shader_Loader.h" -#include "Render_Utils.h" -#include "Texture.h" -#include "Camera.h" -#include "SOIL/stb_image_aug.h" - -GLuint skyboxProgram, skyboxBuffer; -GLuint bubbleProgram; -GLuint programColor; -GLuint programTexture; - -GLuint textureSubmarine; -GLuint textureBubble; -GLuint textureFish; - -unsigned int cubemapTexture, skyboxVAO; -unsigned int cubeVAO, cubeVBO; - -float skyboxVerticeParameter = 50.0f; -float skyboxBoundary = 48.0f; - -std::vector bubbleArray[300]; -float old_x, old_y = -1; -glm::vec3 cursorDiff; -glm::vec3 lightDir = glm::normalize(glm::vec3(0.0f, skyboxVerticeParameter, 0.0f)); -glm::vec3 cameraPos = glm::vec3(0, 0, 0); -glm::vec3 oldCameraPos = glm::vec3(0, 0, 5); - -glm::vec3 cameraDir; // Wektor "do przodu" kamery -glm::vec3 cameraSide; // Wektor "w bok" kamery -float cameraAngle = 0; - -glm::quat rotation = glm::quat(1, 0, 0, 0); - -glm::mat4 cameraMatrix, perspectiveMatrix; - -Core::Shader_Loader shaderLoader; -Core::RenderContext submarineContext; -Core::RenderContext fishContext; -Core::RenderContext bubbleContext; - -std::vector fishKeyPoints({ -glm::vec3(-18.0f, -10.0f, -10.0f), -glm::vec3(-10.0f, -5.0f, -12.0f), -glm::vec3(8.0f, -3.0f, -3.0f), -glm::vec3(5.0f, 0.0f, 3.0f), -glm::vec3(3.0f, 2.0f, 4.0f), -glm::vec3(8.0f, 5.0f, 9.0f), -glm::vec3(14.0f, 6.0f, 15.0f), -glm::vec3(15.0f, 12.0f, 12.0f), -glm::vec3(10.0f, 17.0f, 15.0f), -glm::vec3(5.0f, 10.0f, 7.0f), -glm::vec3(-1.0f, 4.0f, 8.0f), -glm::vec3(-8.0f, 0.0f, 3.0f), -glm::vec3(-12.0f, -6.0f, -3.0f), -glm::vec3(-15.0f, -8.0f, -6.0f), -glm::vec3(-18.0f, -10.0f, -10.0f), - }); - -std::vector keyRotation; - -std::vector fish; - -std::string skyboxTextures[6] = { - "models/skybox/right.jpg", - "models/skybox/left.jpg", - "models/skybox/top.jpg", - "models/skybox/bottom.jpg", - "models/skybox/front.jpg", - "models/skybox/back.jpg" -}; - - - -float cubeVertices[] = { - // positions // normals - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f -}; - -float skyboxVertices[] = { - -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - - -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - -skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - - skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - - -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - - -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - - -skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter -}; - - -bool isInBoundaries(glm::vec3 nextPosition) { - return nextPosition.z > -skyboxBoundary && nextPosition.z < skyboxBoundary&& nextPosition.y > -skyboxBoundary && - nextPosition.y < skyboxBoundary&& nextPosition.x < skyboxBoundary&& nextPosition.x > -skyboxBoundary; -} - - -std::random_device rd; // obtain a random number from hardware -std::mt19937 gen(rd()); // seed the generator -std::uniform_int_distribution<> distr(-skyboxVerticeParameter, skyboxVerticeParameter); // define the range - -std::vector genBubbleKeyPoints() { - float random1 = distr(gen); - float random2 = distr(gen); - std::vector bubbleKeyPoints({ - glm::vec3(random1 , -skyboxVerticeParameter, random2), - glm::vec3(random1 , skyboxVerticeParameter, random2) - } - ); - return bubbleKeyPoints; -}; - -void generateBubbleArray() { - - for (int i = 0; i < 300; i++) { - bubbleArray[i] = genBubbleKeyPoints(); - } -} - -void keyboard(unsigned char key, int x, int y) -{ - float angleSpeed = 10.f; - float moveSpeed = 1.0f; - glm::vec3 nextPosition; - switch (key) - { - case 'z': cursorDiff.z -= angleSpeed; break; - case 'x': cursorDiff.z += angleSpeed; break; - case 'w': - nextPosition = cameraPos + (cameraDir * moveSpeed); - if (isInBoundaries(nextPosition)) { - cameraPos = nextPosition; - } - break; - case 's': - nextPosition = cameraPos - (cameraDir * moveSpeed); - if (isInBoundaries(nextPosition)) { - cameraPos = nextPosition; - } - break; - case 'd': - nextPosition = cameraPos + (cameraSide * moveSpeed); - if (isInBoundaries(nextPosition)) { - cameraPos = nextPosition; - } - break; - case 'a': - nextPosition = cameraPos - (cameraSide * moveSpeed); - if (isInBoundaries(nextPosition)) { - cameraPos = nextPosition; - } - break; - } -} - -void mouse(int x, int y) -{ - if (old_x >= 0) { - cursorDiff.x = x - old_x; - cursorDiff.y = y - old_y; - } - old_x = x; - old_y = y; - - if (x < 100 || x > 800 - 100) { //you can use values other than 100 for the screen edges if you like, kind of seems to depend on your mouse sensitivity for what ends up working best - old_x = 800 / 2; //centers the last known position, this way there isn't an odd jump with your cam as it resets - old_y = 800 / 2; - glutWarpPointer(800 / 2, 800 / 2); //centers the cursor - } - else if (y < 100 || y > 800 - 100) { - old_x = 800 / 2; - old_y = 800 / 2; - glutWarpPointer(800 / 2, 800 / 2); - } -} - -glm::mat4 createCameraMatrix() -{ - glm::quat rotation_x = glm::angleAxis(cursorDiff.y * 0.03f, glm::vec3(1, 0, 0)); - cursorDiff.y = 0; - glm::quat rotation_y = glm::angleAxis(cursorDiff.x * 0.03f, glm::vec3(0, 1, 0)); - cursorDiff.x = 0; - glm::quat rotation_z = glm::angleAxis(cursorDiff.z * 0.03f, glm::vec3(0, 0, 1)); - cursorDiff.z = 0; - - glm::quat rotationChange = rotation_x * rotation_y * rotation_z; - rotation = glm::normalize(rotationChange * rotation); - - cameraDir = glm::inverse(rotation) * glm::vec3(0, 0, -1); - cameraSide = glm::inverse(rotation) * glm::vec3(1, 0, 0); - - return Core::createViewMatrixQuat(cameraPos, rotation); -} - -std::vector changeKeyPoints(std::vector keyPoints, glm::vec3 toChange) { - std::vector result; - int size = keyPoints.size(); - glm::vec3 change; - - for (int i = 0; i < size; i++) { - change.x = keyPoints[i].x + toChange.x; - change.y = keyPoints[i].y + toChange.y; - change.z = keyPoints[i].z + toChange.z; - result.push_back(change); - } - - return result; -} - -glm::mat4 animationMatrix(float time, glm::vec3 change, std::vector keyPoints, glm::vec3 scaleValue, float speed) { - - time = time * speed; - std::vector distances; - std::vector newKeyPoints = changeKeyPoints(keyPoints, change); - float timeStep = 0; - for (int i = 0; i < keyPoints.size() - 1; i++) { - timeStep += (keyPoints[i] - keyPoints[i + 1]).length(); - distances.push_back((keyPoints[i] - keyPoints[i + 1]).length()); - } - time = fmod(time, timeStep); - - //index of first keyPoint - int index = 0; - - while (distances[index] <= time) { - time = time - distances[index]; - index += 1; - } - - float t = time / distances[index]; - - int size = keyPoints.size(); - int rotationSize = keyRotation.size(); - - glm::vec3 pos = glm::catmullRom(newKeyPoints[std::max(0, (index - 1) % size)], newKeyPoints[(index) % size], newKeyPoints[(index + 1) % size], newKeyPoints[(index + 2) % size], t); - - glm::quat divideByFour = glm::quat(0.25f, 0.25f, 0.25f, 0.25f); - auto a1 = keyRotation[index % rotationSize] * glm::exp(-(glm::log(glm::inverse(keyRotation[index % rotationSize]) * keyRotation[std::max(0, (index - 1) % rotationSize)]) + glm::log(glm::inverse(keyRotation[index % rotationSize]) * keyRotation[(index + 1) % rotationSize])) * divideByFour); - - auto a2 = keyRotation[(index + 1) % rotationSize] * glm::exp(-(glm::log(glm::inverse(keyRotation[(index + 1) % rotationSize]) * keyRotation[index % rotationSize]) + glm::log(glm::inverse(keyRotation[(index + 1) % rotationSize]) * keyRotation[(index + 2) % rotationSize])) * divideByFour); - - auto animationRotation = glm::squad(keyRotation[index % rotationSize], keyRotation[(index + 1) % rotationSize], a1, a2, t); - - glm::mat4 result = glm::translate(pos) * glm::scale(glm::vec3(scaleValue)) * glm::mat4_cast(animationRotation); - - return result; -} - -void drawObjectTexture(Core::RenderContext context, glm::mat4 modelMatrix, GLuint textureId, GLuint program) -{ - glUseProgram(program); - - glUniform3f(glGetUniformLocation(program, "lightDir"), lightDir.x, lightDir.y, lightDir.z); - Core::SetActiveTexture(textureId, "textureSampler", program, 0); - - glm::mat4 transformation = perspectiveMatrix * cameraMatrix * modelMatrix; - glUniformMatrix4fv(glGetUniformLocation(program, "modelViewProjectionMatrix"), 1, GL_FALSE, (float*)&transformation); - glUniformMatrix4fv(glGetUniformLocation(program, "modelMatrix"), 1, GL_FALSE, (float*)&modelMatrix); - - Core::DrawContext(context); - - glUseProgram(0); -} - - -void renderScene() -{ - cameraMatrix = createCameraMatrix(); - perspectiveMatrix = Core::createPerspectiveMatrix(); - - glClearColor(0.219f, 0.407f, 0.658f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - float time = glutGet(GLUT_ELAPSED_TIME) / 1000.f; - glUseProgram(skyboxProgram); - glUniform1i(glGetUniformLocation(skyboxProgram, "skybox"), 0); - glm::mat4 transformation = perspectiveMatrix * cameraMatrix; - glUniformMatrix4fv(glGetUniformLocation(skyboxProgram, "projectionViewMatrix"), 1, GL_FALSE, (float*)&transformation); - glBindVertexArray(skyboxVAO); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture); - glDrawArrays(GL_TRIANGLES, 0, 36); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glm::mat4 submarineInitialTransformation = glm::translate(glm::vec3(0, -0.5, -0.4)) * glm::rotate(glm::radians(180.0f), glm::vec3(0, 1, 0)) * glm::scale(glm::vec3(0.25f)); - glm::mat4 submarineModelMatrix = glm::translate(cameraPos + cameraDir) * glm::mat4_cast(glm::inverse(rotation)) * submarineInitialTransformation; - - glm::mat4 bubbleInitialTransformation = glm::translate(glm::vec3(0, -0.5, -0.4)) * glm::rotate(glm::radians(180.0f), glm::vec3(0, 1, 0)) * glm::scale(glm::vec3(0.5f)); - - glm::vec3 change1 = glm::vec3(0, 3, 0); - glm::vec3 change2 = glm::vec3(0, 0, 0); - glm::vec3 change3 = glm::vec3(3, 0, 0); - glm::vec3 change4 = glm::vec3(0, 2, 1); - - glm::vec3 change0 = glm::vec3(0, 0, 0); - - for (int j = 0; j < 100; j++) { - drawObjectTexture(bubbleContext, animationMatrix(time + j, change0, bubbleArray[j], glm::vec3(0.04f), 0.2f), cubemapTexture, bubbleProgram); - } - - for (int i = 0; i < 5; i++) { - if (time > -10) { - drawObjectTexture(fishContext, animationMatrix(time + 15, change1, fishKeyPoints, glm::vec3(0.25f), 1.f), textureFish, programTexture); - drawObjectTexture(fishContext, animationMatrix(time + 15, change2, fishKeyPoints, glm::vec3(0.25f), 1.f), textureFish, programTexture); - drawObjectTexture(fishContext, animationMatrix(time + 15, change3, fishKeyPoints, glm::vec3(0.25f), 1.f), textureFish, programTexture); - drawObjectTexture(fishContext, animationMatrix(time + 15, change4, fishKeyPoints, glm::vec3(0.25f), 1.f), textureFish, programTexture); - - time -= 6; - } - } - //drawObjectTexture(bubbleContext, submarineInitialTransformation, cubemapTexture, bubbleProgram); - drawObjectTexture(submarineContext, submarineModelMatrix, textureSubmarine, programTexture); - glutSwapBuffers(); -} - -void loadModelToContext(std::string path, Core::RenderContext& context) -{ - Assimp::Importer import; - const aiScene* scene = import.ReadFile(path, aiProcess_Triangulate | aiProcess_CalcTangentSpace); - - if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) - { - std::cout << "ERROR::ASSIMP::" << import.GetErrorString() << std::endl; - return; - } - context.initFromAssimpMesh(scene->mMeshes[0]); -} - -unsigned int loadCubemap() -{ - 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* data = stbi_load(skyboxTextures[i].c_str(), &width, &height, &nrChannels, STBI_rgb_alpha); - if (data) - { - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, - 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data - ); - stbi_image_free(data); - } - else - { - std::cout << stbi_failure_reason() << std::endl; - std::cout << "Cubemap tex failed to load at path: " << skyboxTextures[i] << std::endl; - stbi_image_free(data); - } - } - 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 initSkybox() -{ - glGenVertexArrays(1, &skyboxVAO); - glBindVertexArray(skyboxVAO); - - glGenBuffers(1, &skyboxBuffer); - glBindBuffer(GL_ARRAY_BUFFER, skyboxBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW); - - GLuint vPosition = glGetAttribLocation(skyboxProgram, "aPos"); - glEnableVertexAttribArray(vPosition); - - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(skyboxVertices), skyboxVertices); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); -} - -void initKeyRotation() { - glm::vec3 oldDirection = glm::vec3(0, 0, 1); - glm::quat oldRotationCamera = glm::quat(1, 0, 0, 0); - glm::vec3 direction; - glm::quat rotation; - for (int i = 0; i < fishKeyPoints.size() - 1; i++) { - //3.1 - direction = glm::normalize(fishKeyPoints[i + 1] - fishKeyPoints[i]); - //3.2 - rotation = glm::normalize(glm::rotationCamera(oldDirection, direction) * oldRotationCamera); - //3.3 - keyRotation.push_back(rotation); - //3.4 - oldDirection = direction; - oldRotationCamera = rotation; - } - keyRotation.push_back(glm::quat(1, 0, 0, 0)); -} - -void initCube() -{ - glGenVertexArrays(1, &cubeVAO); - glGenBuffers(1, &cubeVBO); - glBindVertexArray(cubeVAO); - glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); -} - -void init() -{ - glEnable(GL_DEPTH_TEST); - programColor = shaderLoader.CreateProgram((char*)"shaders/shader_color.vert", (char*)"shaders/shader_color.frag"); - programTexture = shaderLoader.CreateProgram((char*)"shaders/shader_tex.vert", (char*)"shaders/shader_tex.frag"); - skyboxProgram = shaderLoader.CreateProgram((char*)"shaders/skybox.vert", (char*)"shaders/skybox.frag"); - bubbleProgram = shaderLoader.CreateProgram((char*)"shaders/bubble.vert", (char*)"shaders/bubble.frag"); - cubemapTexture = loadCubemap(); - - loadModelToContext("models/submarine.obj", submarineContext); - textureSubmarine = Core::LoadTexture("textures/submarine.png"); - - loadModelToContext("models/fish.obj", fishContext); - textureFish = Core::LoadTexture("textures/fish.png"); - - initKeyRotation(); - loadModelToContext("models/submarine.obj", submarineContext); - textureSubmarine = Core::LoadTexture("textures/submarine.png"); - loadModelToContext("models/sphere.obj", bubbleContext); - textureBubble = Core::LoadTexture("textures/bubble.png"); - generateBubbleArray(); - initCube(); - initSkybox(); - -} - -void shutdown() -{ - shaderLoader.DeleteProgram(programColor); - shaderLoader.DeleteProgram(programTexture); - shaderLoader.DeleteProgram(skyboxProgram); - shaderLoader.DeleteProgram(bubbleProgram); - -} - -void idle() -{ - glutPostRedisplay(); -} - - -int main(int argc, char** argv) -{ - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA); - glutInitWindowPosition(200, 200); - glutInitWindowSize(800, 800); - glutCreateWindow("Water and shit"); - glewInit(); - - init(); - glutKeyboardFunc(keyboard); - glutPassiveMotionFunc(mouse); - glutDisplayFunc(renderScene); - glutIdleFunc(idle); - - glutSetCursor(GLUT_CURSOR_NONE); - glutMainLoop(); - shutdown(); - return 0; -} \ No newline at end of file diff --git a/grafika_projekt/Debug/Render_Utils.obj b/grafika_projekt/Debug/Render_Utils.obj deleted file mode 100644 index b785889..0000000 Binary files a/grafika_projekt/Debug/Render_Utils.obj and /dev/null differ diff --git a/grafika_projekt/Textures.h b/grafika_projekt/Textures.h deleted file mode 100644 index 649a53a..0000000 --- a/grafika_projekt/Textures.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include "glew.h" -#include "freeglut.h" -#include -#include - -namespace Core -{ - GLuint LoadTexture(const char* filepath); - - // textureID - identyfikator tekstury otrzymany z funkcji LoadTexture - // shaderVariableName - nazwa zmiennej typu 'sampler2D' w shaderze, z ktora ma zostac powiazana tekstura - // programID - identyfikator aktualnego programu karty graficznej - // textureUnit - indeks jednostki teksturujacej - liczba od 0 do 7. Jezeli uzywa sie wielu tekstur w jednym shaderze, to kazda z nich nalezy powiazac z inna jednostka. - void SetActiveTexture(GLuint textureID, const char* shaderVariableName, GLuint programID, int textureUnit); \ No newline at end of file diff --git a/grafika_projekt/grafika_projekt.vcxproj b/grafika_projekt/grafika_projekt.vcxproj index 954a0f5..caf784f 100644 --- a/grafika_projekt/grafika_projekt.vcxproj +++ b/grafika_projekt/grafika_projekt.vcxproj @@ -142,6 +142,8 @@ + + @@ -151,9 +153,14 @@ + + + + + @@ -164,7 +171,7 @@ - + diff --git a/grafika_projekt/grafika_projekt.vcxproj.filters b/grafika_projekt/grafika_projekt.vcxproj.filters index a927053..4abfd2a 100644 --- a/grafika_projekt/grafika_projekt.vcxproj.filters +++ b/grafika_projekt/grafika_projekt.vcxproj.filters @@ -42,6 +42,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -77,7 +86,19 @@ Header Files - + + Header Files + + + Header Files + + + Header Files + + + Header Files + + Header Files diff --git a/grafika_projekt/models/plane.obj b/grafika_projekt/models/plane.obj new file mode 100644 index 0000000..38bee40 --- /dev/null +++ b/grafika_projekt/models/plane.obj @@ -0,0 +1,18 @@ +v 0 50 0 +v 100 30 0 +v 0 1 100 +v 100 100 100 + +vt 0 0 +vt 20 0 +vt 0 20 +vt 20 20 + +vn 0.61 3.67 -0.78 +vn 0.99 2.89 -0.13 +vn 0.14 7.02 -0.98 +vn 0.5 7.3 -0.86 + +s off +f 1/1/1 3/3/3 2/2/2 +f 2/2/2 3/3/3 4/4/4 diff --git a/grafika_projekt/shaders/shader_tex.frag b/grafika_projekt/shaders/shader_tex.frag index b817324..a105e41 100644 --- a/grafika_projekt/shaders/shader_tex.frag +++ b/grafika_projekt/shaders/shader_tex.frag @@ -2,7 +2,6 @@ uniform sampler2D textureSampler; uniform vec3 lightDir; -uniform vec3 lightPos; uniform vec3 cameraPos; uniform vec3 objectColor; diff --git a/grafika_projekt/src/Camera.h b/grafika_projekt/src/Camera.h index fb093ad..02374ac 100644 --- a/grafika_projekt/src/Camera.h +++ b/grafika_projekt/src/Camera.h @@ -5,7 +5,7 @@ namespace Core { - glm::mat4 createPerspectiveMatrix(float zNear = 0.1f, float zFar = 200.0f); + glm::mat4 createPerspectiveMatrix(float zNear = 0.1f, float zFar = 500.0f); // position - pozycja kamery // forward - wektor "do przodu" kamery (jednostkowy) diff --git a/grafika_projekt/src/Engine.cpp b/grafika_projekt/src/Engine.cpp new file mode 100644 index 0000000..461c890 --- /dev/null +++ b/grafika_projekt/src/Engine.cpp @@ -0,0 +1,180 @@ +#include "Engine.h" + + +void Core::Engine::initShaderPrograms() { + this->textureShader = shaderLoader.CreateProgram((char*)"shaders/shader_tex.vert", (char*)"shaders/shader_tex.frag"); + this->skyboxShader = shaderLoader.CreateProgram((char*)"shaders/skybox.vert", (char*)"shaders/skybox.frag"); + this->bubbleShader = shaderLoader.CreateProgram((char*)"shaders/bubble.vert", (char*)"shaders/bubble.frag"); +} + +void Core::Engine::shutdownShaderPrograms() { + shaderLoader.DeleteProgram(this->textureShader); + shaderLoader.DeleteProgram(this->skyboxShader); + shaderLoader.DeleteProgram(this->bubbleShader); +} + +void Core::Engine::initRenderContexts() { + loadModelToContext("models/fish.obj", this->fishContext); + loadModelToContext("models/submarine.obj", this->submarineContext); + loadModelToContext("models/sphere.obj", this->bubbleContext); + + this->terrain = Terrain(this->heightGenerator); + obj::Model model = this->terrain.generateTerrain(); + this->terrainContext.initFromOBJ(model); +} + +void Core::Engine::loadTextures() { + this->fishTexture = LoadTexture("textures/fish.png"); + this->submarineTexture = LoadTexture("textures/submarine.png"); + this->bubbleTexture = LoadTexture("textures/bubble.png"); + this->terrainTexture = LoadTexture("textures/terrain.jpg"); + this->skyboxTexture = loadCubemap(); +} + +void Core::Engine::initCube() { + GLuint cubeVAO, cubeVBO; + glGenVertexArrays(1, &cubeVAO); + glGenBuffers(1, &cubeVBO); + glBindVertexArray(cubeVAO); + glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(this->cubeVertices), &this->cubeVertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); +} + +void Core::Engine::initSkybox() { + this->initCube(); + glGenVertexArrays(1, &this->skyboxVAO); + glBindVertexArray(this->skyboxVAO); + + glGenBuffers(1, &this->skyboxVBO); + glBindBuffer(GL_ARRAY_BUFFER, this->skyboxVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(this->skyboxVertices), &this->skyboxVertices, GL_STATIC_DRAW); + + GLuint vPosition = glGetAttribLocation(this->skyboxShader, "aPos"); + glEnableVertexAttribArray(vPosition); + + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(this->skyboxVertices), this->skyboxVertices); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); +} + +void Core::Engine::initRandomGenerator(std::default_random_engine gen, std::uniform_int_distribution<> distr) { + this->gen = gen; + this->distr = distr; +} + + +std::vector Core::Engine::genBubbleKeyPoints() { + float random1 = this->distr(this->gen); + float random2 = this->distr(this->gen); + std::vector bubbleKeyPoints({ + glm::vec3(random1 , -this->skyboxVerticeParameter, random2), + glm::vec3(random1 , this->skyboxVerticeParameter, random2) + } + ); + return bubbleKeyPoints; +}; + +void Core::Engine::generateBubbleArray() { + for (int i = 0; i < 300; i++) { + this->bubbleArray[i] = this->genBubbleKeyPoints(); + } +} + +void Core::Engine::initBubbles() { + this->generateBubbleArray(); +} + +const float Core::Engine::cubeVertices[216] = { + // positions // normals + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, + + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f +}; + +const float Core::Engine::skyboxVerticeParameter = 50.0f; + +const float Core::Engine::skyboxVertices[108] = { + -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, + -skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, + skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, + skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, + skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, + -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, + + -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, + -skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, + -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, + -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, + -skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, + -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, + + skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, + skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, + skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, + skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, + skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, + skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, + + -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, + -skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, + skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, + skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, + skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, + -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, + + -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, + skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, + skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, + skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, + -skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, + -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, + + -skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, + -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, + skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, + skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, + -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, + skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter +}; \ No newline at end of file diff --git a/grafika_projekt/src/Engine.h b/grafika_projekt/src/Engine.h new file mode 100644 index 0000000..b555dcf --- /dev/null +++ b/grafika_projekt/src/Engine.h @@ -0,0 +1,43 @@ +#pragma once +#include "glm.hpp" +#include "glew.h" +#include +#include +#include "Shader_Loader.h" +#include "Texture.h" +#include "Render_Utils.h" +#include "Terrain.h" +#include "HeightGenerator.h" +#include + + +namespace Core { + class Engine { + public: + GLuint textureShader, skyboxShader, bubbleShader; + GLuint submarineTexture, bubbleTexture, fishTexture, terrainTexture, skyboxTexture; + GLuint skyboxVAO; + Core::RenderContext submarineContext, fishContext, bubbleContext, terrainContext; + std::vector bubbleArray[300]; + void initShaderPrograms(); + void shutdownShaderPrograms(); + void initRenderContexts(); + void loadTextures(); + void initSkybox(); + void initBubbles(); + void initRandomGenerator(std::default_random_engine gen, std::uniform_int_distribution<> distr); + static const float skyboxVerticeParameter; + private: + HeightGenerator heightGenerator; + GLuint skyboxVBO; + Terrain terrain; + Shader_Loader shaderLoader; + static const float cubeVertices[216], skyboxVertices[108]; + std::uniform_int_distribution<> distr; + std::default_random_engine gen; + void initCube(); + void generateBubbleArray(); + std::vector genBubbleKeyPoints(); + }; + +} \ No newline at end of file diff --git a/grafika_projekt/src/HeightGenerator.cpp b/grafika_projekt/src/HeightGenerator.cpp new file mode 100644 index 0000000..6500f19 --- /dev/null +++ b/grafika_projekt/src/HeightGenerator.cpp @@ -0,0 +1,55 @@ +#include "HeightGenerator.h" +#include +#include +#include + +# define MY_PI 3.1415927 + +std::random_device rd; // obtain a random number from hardware + +const int HeightGenerator::SEED = rd(); + +float HeightGenerator::generateHeight(int x, int z) { + float total = 0; + int p = 0.5f; + for (int i = 0; i < 5; i++) { + float freq = pow(2, i); + float amp = pow(p, i); + total += getInterpolatedNoise(x * freq, z * freq) * amp; + } + return total; +} + +float HeightGenerator::getInterpolatedNoise(float x, float z) { + int intX = int(x); + int intZ = int(z); + float fracX = x - intX; + float fracZ = z - intZ; + + float v1 = getSmoothNoise(intX, intZ); + float v2 = getSmoothNoise(intX + 1, intZ); + float v3 = getSmoothNoise(intX, intZ + 1); + float v4 = getSmoothNoise(intX + 1, intZ + 1); + float i1 = interpolate(v1, v2, fracX); + float i2 = interpolate(v3, v4, fracX); + return interpolate(i1, i2, fracZ); +} + +float HeightGenerator::interpolate(float a, float b, float blend) { + double theta = blend * MY_PI; + float f = float(1.f - cos(theta)) * 0.5f; + return a * (1 - f) + b * f; +} + +float HeightGenerator::getSmoothNoise(int x, int z) { + float corners = float(getNoise(x - 1, z - 1) + getNoise(x + 1, z - 1) + getNoise(x - 1, z + 1) + getNoise(x + 1, z + 1)) / 16; + float sides = float(getNoise(x - 1, z) + getNoise(x + 1, z) + getNoise(x, z - 1) + getNoise(x, z + 1)) / 8; + float center = float(getNoise(x, z)) / 4; + return corners + sides + center; +} + +float HeightGenerator::getNoise(int x, int z) { + std::mt19937 gen(SEED + x * 49632 + z * 325176); + std::uniform_real_distribution<> distr(-3, 3); + return distr(gen); +} diff --git a/grafika_projekt/src/HeightGenerator.h b/grafika_projekt/src/HeightGenerator.h new file mode 100644 index 0000000..6ca80d0 --- /dev/null +++ b/grafika_projekt/src/HeightGenerator.h @@ -0,0 +1,13 @@ +#pragma once + +class HeightGenerator +{ +public: + float generateHeight(int x, int z); + static const int SEED; +private: + float getInterpolatedNoise(float x, float z); + float getSmoothNoise(int x, int z); + float interpolate(float a, float b, float blend); + float getNoise(int x, int z); +}; diff --git a/grafika_projekt/src/Render_Utils.cpp b/grafika_projekt/src/Render_Utils.cpp index b3d06fb..bcfe787 100644 --- a/grafika_projekt/src/Render_Utils.cpp +++ b/grafika_projekt/src/Render_Utils.cpp @@ -8,7 +8,6 @@ #include #include - void Core::RenderContext::initFromOBJ(obj::Model& model) { vertexArray = 0; @@ -19,7 +18,7 @@ void Core::RenderContext::initFromOBJ(obj::Model& model) unsigned int vertexTexBufferSize = sizeof(float) * model.texCoord.size(); size = model.faces["default"].size(); - unsigned int vertexElementBufferSize = sizeof(unsigned short) * size; + unsigned int vertexElementBufferSize = sizeof(unsigned int) * size; glGenVertexArrays(1, &vertexArray); @@ -167,3 +166,80 @@ void Core::DrawContext(Core::RenderContext& context) ); glBindVertexArray(0); } + +void Core::loadModelToContext(std::string path, Core::RenderContext& context) +{ + Assimp::Importer import; + const aiScene* scene = import.ReadFile(path, aiProcess_Triangulate | aiProcess_CalcTangentSpace); + + if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) + { + std::cout << "ERROR::ASSIMP::" << import.GetErrorString() << std::endl; + return; + } + context.initFromAssimpMesh(scene->mMeshes[0]); +} + +GLuint Core::loadCubemap() +{ + std::string skyboxTextures[6] = { + "models/skybox/right.jpg", + "models/skybox/left.jpg", + "models/skybox/top.jpg", + "models/skybox/bottom.jpg", + "models/skybox/front.jpg", + "models/skybox/back.jpg" + }; + GLuint textureID; + glGenTextures(1, &textureID); + glBindTexture(GL_TEXTURE_CUBE_MAP, textureID); + + int width, height, nrChannels; + for (unsigned int i = 0; i < 6; i++) + { + unsigned char* data = stbi_load(skyboxTextures[i].c_str(), &width, &height, &nrChannels, STBI_rgb_alpha); + if (data) + { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, + 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data + ); + stbi_image_free(data); + } + else + { + std::cout << stbi_failure_reason() << std::endl; + std::cout << "Cubemap tex failed to load at path: " << skyboxTextures[i] << std::endl; + stbi_image_free(data); + } + } + 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 Core::drawObjectTexture( + Core::RenderContext context, + glm::mat4 modelMatrix, + GLuint textureId, + GLuint program, + glm::vec3 lightDir, + glm::mat4 cameraMatrix, + glm::mat4 perspectiveMatrix +) { + glUseProgram(program); + + glUniform3f(glGetUniformLocation(program, "lightDir"), lightDir.x, lightDir.y, lightDir.z); + Core::SetActiveTexture(textureId, "textureSampler", program, 0); + + glm::mat4 transformation = perspectiveMatrix * cameraMatrix * modelMatrix; + glUniformMatrix4fv(glGetUniformLocation(program, "modelViewProjectionMatrix"), 1, GL_FALSE, (float*)&transformation); + glUniformMatrix4fv(glGetUniformLocation(program, "modelMatrix"), 1, GL_FALSE, (float*)&modelMatrix); + + Core::DrawContext(context); + + glUseProgram(0); +} diff --git a/grafika_projekt/src/Render_Utils.h b/grafika_projekt/src/Render_Utils.h index 2b142df..04bf927 100644 --- a/grafika_projekt/src/Render_Utils.h +++ b/grafika_projekt/src/Render_Utils.h @@ -5,12 +5,15 @@ #include #include #include +#include "SOIL/stb_image_aug.h" +#include "Texture.h" +#define STB_IMAGE_IMPLEMENTATION + #define BUFFER_OFFSET(i) ((char *)NULL + (i)) namespace Core { - struct RenderContext { @@ -76,4 +79,18 @@ namespace Core void DrawVertexArray(const VertexData & data); void DrawContext(RenderContext& context); + + void loadModelToContext(std::string path, Core::RenderContext& context); + + void drawObjectTexture( + Core::RenderContext context, + glm::mat4 modelMatrix, + GLuint textureId, + GLuint program, + glm::vec3 lightDir, + glm::mat4 cameraMatrix, + glm::mat4 perspectiveMatrix + ); + + GLuint loadCubemap(); } \ No newline at end of file diff --git a/grafika_projekt/src/Terrain.cpp b/grafika_projekt/src/Terrain.cpp new file mode 100644 index 0000000..8606964 --- /dev/null +++ b/grafika_projekt/src/Terrain.cpp @@ -0,0 +1,69 @@ +#include "Terrain.h" + + +const float Terrain::SIZE = 50.f; +const int Terrain::VERTEX_COUNT = 64; +const int Terrain::COUNT = Terrain::VERTEX_COUNT * Terrain::VERTEX_COUNT; + + +Terrain::Terrain(HeightGenerator heightGenerator) { + this->heightGenerator = heightGenerator; +} + +obj::Model Terrain::generateTerrain() { + float vertices[COUNT * 3]; + float normals[COUNT * 3]; + float textureCoords[COUNT * 2]; + int indices[6 * (VERTEX_COUNT - 1) * (VERTEX_COUNT - 1)]; + int vertexPointer = 0; + for (int i = 0; i < VERTEX_COUNT; i++) { + for (int j = 0; j < VERTEX_COUNT; j++) { + vertices[vertexPointer * 3] = float(j) / float(VERTEX_COUNT - 1) * SIZE; + vertices[vertexPointer * 3 + 1] = getHeight(j, i); + vertices[vertexPointer * 3 + 2] = float(i) / float(VERTEX_COUNT - 1) * SIZE; + glm::vec3 normal = calculateNormal(j, i); + normals[vertexPointer * 3] = normal.x; + normals[vertexPointer * 3 + 1] = normal.y; + normals[vertexPointer * 3 + 2] = normal.z; + textureCoords[vertexPointer * 2] = float(j) / float(VERTEX_COUNT - 1); + textureCoords[vertexPointer * 2 + 1] = float(i) / float(VERTEX_COUNT - 1); + vertexPointer++; + } + } + int pointer = 0; + for (int gz = 0; gz < VERTEX_COUNT - 1; gz++) { + for (int gx = 0; gx < VERTEX_COUNT - 1; gx++) { + int topLeft = gz * VERTEX_COUNT + gx; + int topRight = topLeft + 1; + int bottomLeft = (gz + 1) * VERTEX_COUNT + gx; + int bottomRight = bottomLeft + 1; + indices[pointer++] = topLeft; + indices[pointer++] = bottomLeft; + indices[pointer++] = topRight; + indices[pointer++] = topRight; + indices[pointer++] = bottomLeft; + indices[pointer++] = bottomRight; + } + } + std::vector vVertices(std::begin(vertices), std::end(vertices)); + std::vector vTextures(std::begin(textureCoords), std::end(textureCoords)); + std::vector vNormals(std::begin(normals), std::end(normals)); + std::map> faces; + faces[std::string("default")] = std::vector(std::begin(indices), std::end(indices)); + + obj::Model model = { vVertices, vTextures, vNormals, faces }; + return model; +} + +glm::vec3 Terrain::calculateNormal(int x, int z) { + float heightL = getHeight(x - 1, z); + float heightR = getHeight(x + 1, z); + float heightD = getHeight(x, z - 1); + float heightU = getHeight(x, z + 1); + glm::vec3 normal = glm::vec3(heightL - heightR, 2.f, heightD - heightU); + return glm::normalize(normal); +} + +float Terrain::getHeight(int x, int z) { + return heightGenerator.generateHeight(x, z); +} diff --git a/grafika_projekt/src/Terrain.h b/grafika_projekt/src/Terrain.h new file mode 100644 index 0000000..01fcc12 --- /dev/null +++ b/grafika_projekt/src/Terrain.h @@ -0,0 +1,22 @@ +#pragma once +#include "glew.h" +#include "freeglut.h" +#include "glm.hpp" +#include "HeightGenerator.h" +#include "objload.h" +#include + +class Terrain +{ +public: + Terrain() = default; + Terrain(HeightGenerator heightGenerator); + obj::Model generateTerrain(); +private: + static const float SIZE; + static const int VERTEX_COUNT; + static const int COUNT; + HeightGenerator heightGenerator; + glm::vec3 calculateNormal(int x, int z); + float getHeight(int x, int z); +}; diff --git a/grafika_projekt/src/main.cpp b/grafika_projekt/src/main.cpp index 0a3ca4c..968175f 100644 --- a/grafika_projekt/src/main.cpp +++ b/grafika_projekt/src/main.cpp @@ -1,4 +1,3 @@ -#define STB_IMAGE_IMPLEMENTATION #include "glew.h" #include "freeglut.h" #include "glm.hpp" @@ -12,25 +11,17 @@ #include "Texture.h" #include "Camera.h" #include "SOIL/stb_image_aug.h" +#include "HeightGenerator.h" +#include "Terrain.h" +#include "Engine.h" -GLuint skyboxProgram, skyboxBuffer; -GLuint bubbleProgram; -GLuint programTexture; +Core::Engine engine; -GLuint textureSubmarine; -GLuint textureBubble; -GLuint textureFish; - -unsigned int cubemapTexture, skyboxVAO; -unsigned int cubeVAO, cubeVBO; - -float skyboxVerticeParameter = 50.0f; float skyboxBoundary = 48.0f; -std::vector bubbleArray[300]; float old_x, old_y = -1; glm::vec3 cursorDiff; -glm::vec3 lightDir = glm::normalize(glm::vec3(0.0f, skyboxVerticeParameter, 0.0f)); +glm::vec3 lightDir = glm::normalize(glm::vec3(0.0f, engine.skyboxVerticeParameter, 0.0f)); glm::vec3 cameraPos = glm::vec3(0, 0, 0); glm::vec3 oldCameraPos = glm::vec3(0, 0, 5); @@ -42,162 +33,31 @@ glm::quat rotation = glm::quat(1, 0, 0, 0); glm::mat4 cameraMatrix, perspectiveMatrix; -Core::Shader_Loader shaderLoader; -Core::RenderContext submarineContext; -Core::RenderContext fishContext; -Core::RenderContext bubbleContext; - std::vector fishKeyPoints({ -glm::vec3(-18.0f, -10.0f, -10.0f), -glm::vec3(-10.0f, -5.0f, -12.0f), -glm::vec3(8.0f, -3.0f, -3.0f), -glm::vec3(5.0f, 0.0f, 3.0f), -glm::vec3(3.0f, 2.0f, 4.0f), -glm::vec3(8.0f, 5.0f, 9.0f), -glm::vec3(14.0f, 6.0f, 15.0f), -glm::vec3(15.0f, 12.0f, 12.0f), -glm::vec3(10.0f, 17.0f, 15.0f), -glm::vec3(5.0f, 10.0f, 7.0f), -glm::vec3(-1.0f, 4.0f, 8.0f), -glm::vec3(-8.0f, 0.0f, 3.0f), -glm::vec3(-12.0f, -6.0f, -3.0f), -glm::vec3(-15.0f, -8.0f, -6.0f), -glm::vec3(-18.0f, -10.0f, -10.0f), - }); + glm::vec3(-18.0f, -10.0f, -10.0f), + glm::vec3(-10.0f, -5.0f, -12.0f), + glm::vec3(8.0f, -3.0f, -3.0f), + glm::vec3(5.0f, 0.0f, 3.0f), + glm::vec3(3.0f, 2.0f, 4.0f), + glm::vec3(8.0f, 5.0f, 9.0f), + glm::vec3(14.0f, 6.0f, 15.0f), + glm::vec3(15.0f, 12.0f, 12.0f), + glm::vec3(10.0f, 17.0f, 15.0f), + glm::vec3(5.0f, 10.0f, 7.0f), + glm::vec3(-1.0f, 4.0f, 8.0f), + glm::vec3(-8.0f, 0.0f, 3.0f), + glm::vec3(-12.0f, -6.0f, -3.0f), + glm::vec3(-15.0f, -8.0f, -6.0f), + glm::vec3(-18.0f, -10.0f, -10.0f) +}); std::vector keyRotation; -std::vector fish; - -std::string skyboxTextures[6] = { - "models/skybox/right.jpg", - "models/skybox/left.jpg", - "models/skybox/top.jpg", - "models/skybox/bottom.jpg", - "models/skybox/front.jpg", - "models/skybox/back.jpg" -}; - - - -float cubeVertices[] = { - // positions // normals - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, - - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, - - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, - -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, - - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f -}; - -float skyboxVertices[] = { - -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - - -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - -skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - - skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - - -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - - -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, skyboxVerticeParameter, - -skyboxVerticeParameter, skyboxVerticeParameter, -skyboxVerticeParameter, - - -skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, -skyboxVerticeParameter, - -skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter, - skyboxVerticeParameter, -skyboxVerticeParameter, skyboxVerticeParameter -}; - - bool isInBoundaries(glm::vec3 nextPosition) { return nextPosition.z > -skyboxBoundary && nextPosition.z < skyboxBoundary&& nextPosition.y > -skyboxBoundary && nextPosition.y < skyboxBoundary&& nextPosition.x < skyboxBoundary&& nextPosition.x > -skyboxBoundary; } - -std::random_device rd; // obtain a random number from hardware -std::mt19937 gen(rd()); // seed the generator -std::uniform_int_distribution<> distr(-skyboxVerticeParameter, skyboxVerticeParameter); // define the range - -std::vector genBubbleKeyPoints() { - float random1 = distr(gen); - float random2 = distr(gen); - std::vector bubbleKeyPoints({ - glm::vec3(random1 , -skyboxVerticeParameter, random2), - glm::vec3(random1 , skyboxVerticeParameter, random2) - } - ); - return bubbleKeyPoints; -}; - -void generateBubbleArray() { - - for (int i = 0; i < 300; i++) { - bubbleArray[i] = genBubbleKeyPoints(); - } -} - void keyboard(unsigned char key, int x, int y) { float angleSpeed = 10.f; @@ -327,39 +187,23 @@ glm::mat4 animationMatrix(float time, glm::vec3 change, std::vector k return result; } -void drawObjectTexture(Core::RenderContext context, glm::mat4 modelMatrix, GLuint textureId, GLuint program) -{ - glUseProgram(program); - - glUniform3f(glGetUniformLocation(program, "lightDir"), lightDir.x, lightDir.y, lightDir.z); - Core::SetActiveTexture(textureId, "textureSampler", program, 0); - - glm::mat4 transformation = perspectiveMatrix * cameraMatrix * modelMatrix; - glUniformMatrix4fv(glGetUniformLocation(program, "modelViewProjectionMatrix"), 1, GL_FALSE, (float*)&transformation); - glUniformMatrix4fv(glGetUniformLocation(program, "modelMatrix"), 1, GL_FALSE, (float*)&modelMatrix); - - Core::DrawContext(context); - - glUseProgram(0); -} - - void renderScene() -{ +{ cameraMatrix = createCameraMatrix(); perspectiveMatrix = Core::createPerspectiveMatrix(); - glClearColor(0.219f, 0.407f, 0.658f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClearColor(0.219f, 0.407f, 0.658f, 1.0f); float time = glutGet(GLUT_ELAPSED_TIME) / 1000.f; - glUseProgram(skyboxProgram); - glUniform1i(glGetUniformLocation(skyboxProgram, "skybox"), 0); + glUseProgram(engine.skyboxShader); + glUniform1i(glGetUniformLocation(engine.skyboxShader, "skybox"), 0); glm::mat4 transformation = perspectiveMatrix * cameraMatrix; - glUniformMatrix4fv(glGetUniformLocation(skyboxProgram, "projectionViewMatrix"), 1, GL_FALSE, (float*)&transformation); - glBindVertexArray(skyboxVAO); + glUniformMatrix4fv(glGetUniformLocation(engine.skyboxShader, "projectionViewMatrix"), 1, GL_FALSE, (float*)&transformation); + glBindVertexArray(engine.skyboxVAO); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_CUBE_MAP, cubemapTexture); + + glBindTexture(GL_TEXTURE_CUBE_MAP, engine.skyboxTexture); glDrawArrays(GL_TRIANGLES, 0, 36); glEnable(GL_BLEND); @@ -368,6 +212,7 @@ void renderScene() glm::mat4 submarineInitialTransformation = glm::translate(glm::vec3(0, -0.5, -0.4)) * glm::rotate(glm::radians(180.0f), glm::vec3(0, 1, 0)) * glm::scale(glm::vec3(0.25f)); glm::mat4 submarineModelMatrix = glm::translate(cameraPos + cameraDir) * glm::mat4_cast(glm::inverse(rotation)) * submarineInitialTransformation; + glm::mat4 bubbleInitialTransformation = glm::translate(glm::vec3(0, -0.5, -0.4)) * glm::rotate(glm::radians(180.0f), glm::vec3(0, 1, 0)) * glm::scale(glm::vec3(0.5f)); glm::vec3 change1 = glm::vec3(0, 3, 0); @@ -378,87 +223,29 @@ void renderScene() glm::vec3 change0 = glm::vec3(0, 0, 0); for (int j = 0; j < 100; j++) { - drawObjectTexture(bubbleContext, animationMatrix(time + j, change0, bubbleArray[j], glm::vec3(0.04f), 0.2f), cubemapTexture, bubbleProgram); + Core::drawObjectTexture(engine.bubbleContext, animationMatrix(time + j, change0, engine.bubbleArray[j], glm::vec3(0.04f), 0.2f), engine.bubbleTexture, engine.bubbleShader, lightDir, cameraMatrix, perspectiveMatrix); } for (int i = 0; i < 5; i++) { if (time > -10) { - drawObjectTexture(fishContext, animationMatrix(time + 15, change1, fishKeyPoints, glm::vec3(0.25f), 1.f), textureFish, programTexture); - drawObjectTexture(fishContext, animationMatrix(time + 15, change2, fishKeyPoints, glm::vec3(0.25f), 1.f), textureFish, programTexture); - drawObjectTexture(fishContext, animationMatrix(time + 15, change3, fishKeyPoints, glm::vec3(0.25f), 1.f), textureFish, programTexture); - drawObjectTexture(fishContext, animationMatrix(time + 15, change4, fishKeyPoints, glm::vec3(0.25f), 1.f), textureFish, programTexture); + Core::drawObjectTexture(engine.fishContext, animationMatrix(time + 15, change1, fishKeyPoints, glm::vec3(0.25f), 1.f), engine.fishTexture, engine.textureShader, lightDir, cameraMatrix, perspectiveMatrix); + Core::drawObjectTexture(engine.fishContext, animationMatrix(time + 15, change2, fishKeyPoints, glm::vec3(0.25f), 1.f), engine.fishTexture, engine.textureShader, lightDir, cameraMatrix, perspectiveMatrix); + Core::drawObjectTexture(engine.fishContext, animationMatrix(time + 15, change3, fishKeyPoints, glm::vec3(0.25f), 1.f), engine.fishTexture, engine.textureShader, lightDir, cameraMatrix, perspectiveMatrix); + Core::drawObjectTexture(engine.fishContext, animationMatrix(time + 15, change4, fishKeyPoints, glm::vec3(0.25f), 1.f), engine.fishTexture, engine.textureShader, lightDir, cameraMatrix, perspectiveMatrix); time -= 6; } } - //drawObjectTexture(bubbleContext, submarineInitialTransformation, cubemapTexture, bubbleProgram); - drawObjectTexture(submarineContext, submarineModelMatrix, textureSubmarine, programTexture); + Core::drawObjectTexture(engine.submarineContext, submarineModelMatrix, engine.submarineTexture, engine.textureShader, lightDir, cameraMatrix, perspectiveMatrix); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glm::mat4 terrainTransformation = glm::translate(glm::vec3(50, -45, 50)) * glm::rotate(glm::radians(180.f), glm::vec3(0, 1, 0)) * glm::scale(glm::vec3(2.f)); + + Core::drawObjectTexture(engine.terrainContext, terrainTransformation, engine.terrainTexture, engine.textureShader, lightDir, cameraMatrix, perspectiveMatrix); + glutSwapBuffers(); } -void loadModelToContext(std::string path, Core::RenderContext& context) -{ - Assimp::Importer import; - const aiScene* scene = import.ReadFile(path, aiProcess_Triangulate | aiProcess_CalcTangentSpace); - - if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) - { - std::cout << "ERROR::ASSIMP::" << import.GetErrorString() << std::endl; - return; - } - context.initFromAssimpMesh(scene->mMeshes[0]); -} - -unsigned int loadCubemap() -{ - 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* data = stbi_load(skyboxTextures[i].c_str(), &width, &height, &nrChannels, STBI_rgb_alpha); - if (data) - { - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, - 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data - ); - stbi_image_free(data); - } - else - { - std::cout << stbi_failure_reason() << std::endl; - std::cout << "Cubemap tex failed to load at path: " << skyboxTextures[i] << std::endl; - stbi_image_free(data); - } - } - 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 initSkybox() -{ - glGenVertexArrays(1, &skyboxVAO); - glBindVertexArray(skyboxVAO); - - glGenBuffers(1, &skyboxBuffer); - glBindBuffer(GL_ARRAY_BUFFER, skyboxBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW); - - GLuint vPosition = glGetAttribLocation(skyboxProgram, "aPos"); - glEnableVertexAttribArray(vPosition); - - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(skyboxVertices), skyboxVertices); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); -} - void initKeyRotation() { glm::vec3 oldDirection = glm::vec3(0, 0, 1); glm::quat oldRotationCamera = glm::quat(1, 0, 0, 0); @@ -478,50 +265,18 @@ void initKeyRotation() { keyRotation.push_back(glm::quat(1, 0, 0, 0)); } -void initCube() -{ - glGenVertexArrays(1, &cubeVAO); - glGenBuffers(1, &cubeVBO); - glBindVertexArray(cubeVAO); - glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); - glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); -} - void init() { + std::default_random_engine gen(HeightGenerator::SEED); + std::uniform_int_distribution<> distr(-engine.skyboxVerticeParameter, engine.skyboxVerticeParameter); + engine.initRandomGenerator(gen, distr); glEnable(GL_DEPTH_TEST); - programTexture = shaderLoader.CreateProgram((char*)"shaders/shader_tex.vert", (char*)"shaders/shader_tex.frag"); - skyboxProgram = shaderLoader.CreateProgram((char*)"shaders/skybox.vert", (char*)"shaders/skybox.frag"); - bubbleProgram = shaderLoader.CreateProgram((char*)"shaders/bubble.vert", (char*)"shaders/bubble.frag"); - cubemapTexture = loadCubemap(); - - loadModelToContext("models/submarine.obj", submarineContext); - textureSubmarine = Core::LoadTexture("textures/submarine.png"); - - loadModelToContext("models/fish.obj", fishContext); - textureFish = Core::LoadTexture("textures/fish.png"); - + engine.initShaderPrograms(); + engine.initRenderContexts(); + engine.loadTextures(); + engine.initSkybox(); + engine.initBubbles(); initKeyRotation(); - loadModelToContext("models/submarine.obj", submarineContext); - textureSubmarine = Core::LoadTexture("textures/submarine.png"); - loadModelToContext("models/sphere.obj", bubbleContext); - textureBubble = Core::LoadTexture("textures/bubble.png"); - generateBubbleArray(); - initCube(); - initSkybox(); - -} - -void shutdown() -{ - shaderLoader.DeleteProgram(programTexture); - shaderLoader.DeleteProgram(skyboxProgram); - shaderLoader.DeleteProgram(bubbleProgram); - } void idle() @@ -547,6 +302,6 @@ int main(int argc, char** argv) glutSetCursor(GLUT_CURSOR_NONE); glutMainLoop(); - shutdown(); + engine.shutdownShaderPrograms(); return 0; } \ No newline at end of file diff --git a/grafika_projekt/src/mesh.h b/grafika_projekt/src/mesh.h new file mode 100644 index 0000000..33e81f9 --- /dev/null +++ b/grafika_projekt/src/mesh.h @@ -0,0 +1,140 @@ + + +#ifndef MESH_H +#define MESH_H + +#include "glew.h" +#include "freeglut.h" +#include "glm.hpp" +#include "ext.hpp" +#include +#include + +#include +#include +using namespace std; + +struct Vertex { + // position + glm::vec3 Position; + // normal + glm::vec3 Normal; + // texCoords + glm::vec2 TexCoords; + // tangent + glm::vec3 Tangent; + // bitangent + glm::vec3 Bitangent; +}; + +struct Texture { + unsigned int id; + string type; + string path; +}; + +class Mesh { +public: + // mesh Data + vector vertices; + vector indices; + vector textures; + glm::mat4 matrix; + unsigned int VAO; + + // constructor + Mesh(vector vertices, vector indices, vector textures,glm::mat4 matrix) + { + this->vertices = vertices; + this->indices = indices; + this->textures = textures; + this->matrix = matrix; + + // now that we have all the required data, set the vertex buffers and its attribute pointers. + setupMesh(); + } + + // render the mesh + void Draw(GLuint program) + { + // bind appropriate textures + unsigned int diffuseNr = 1; + unsigned int specularNr = 1; + unsigned int normalNr = 1; + unsigned int heightNr = 1; + for (unsigned int i = 0; i < textures.size(); i++) + { + glActiveTexture(GL_TEXTURE0 + i); // active proper texture unit before binding + // retrieve texture number (the N in diffuse_textureN) + string number; + string name = textures[i].type; + if (name == "texture_diffuse") + number = std::to_string(diffuseNr++); + else if (name == "texture_specular") + number = std::to_string(specularNr++); // transfer unsigned int to stream + else if (name == "texture_normal") + number = std::to_string(normalNr++); // transfer unsigned int to stream + else if (name == "texture_height") + number = std::to_string(heightNr++); // transfer unsigned int to stream + + // now set the sampler to the correct texture unit + glUniform1i(glGetUniformLocation(program, (name + number).c_str()), i); + // and finally bind the texture + glBindTexture(GL_TEXTURE_2D, textures[i].id); + } + + glUniformMatrix4fv(glGetUniformLocation(program, "model"), 1, GL_FALSE, (float*)&matrix); + // draw mesh + glBindVertexArray(VAO); + glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); + glBindVertexArray(0); + + // always good practice to set everything back to defaults once configured. + glActiveTexture(GL_TEXTURE0); + } + +private: + // render data + unsigned int VBO, EBO; + + // initializes all the buffer objects/arrays + void setupMesh() + { + // create buffers/arrays + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + glGenBuffers(1, &EBO); + + glBindVertexArray(VAO); + // load data into vertex buffers + glBindBuffer(GL_ARRAY_BUFFER, VBO); + // A great thing about structs is that their memory layout is sequential for all its items. + // The effect is that we can simply pass a pointer to the struct and it translates perfectly to a glm::vec3/2 array which + // again translates to 3/2 floats which translates to a byte array. + glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW); + + // set the vertex attribute pointers + // vertex Positions + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0); + // vertex normals + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal)); + // vertex texture coords + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords)); + // vertex tangent + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Tangent)); + // vertex bitangent + glEnableVertexAttribArray(4); + glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Bitangent)); + + glBindVertexArray(0); + } +}; +#endif + diff --git a/grafika_projekt/src/model.h b/grafika_projekt/src/model.h new file mode 100644 index 0000000..ac8bf72 --- /dev/null +++ b/grafika_projekt/src/model.h @@ -0,0 +1,250 @@ +#pragma once + + + + +#include "glew.h" +#include "freeglut.h" +#include "glm.hpp" +#include "ext.hpp" +#include +#include +#include +#include +#include + +#include "stb_image.h" +#include "mesh.h" + +#include +#include +#include +#include +#include +#include +using namespace std; + + +unsigned int TextureFromFile(const char* path, const string& directory, bool gamma = false); + +class Model +{ +public: + // model data + vector textures_loaded; // stores all the textures loaded so far, optimization to make sure textures aren't loaded more than once. + vector meshes; + string directory; + bool gammaCorrection; + + // constructor, expects a filepath to a 3D model. + Model(string const& path, bool gamma = false) : gammaCorrection(gamma) + { + loadModel(path); + } + + // draws the model, and thus all its meshes + void Draw(GLuint shader) + { + for (unsigned int i = 0; i < meshes.size(); i++) + meshes[i].Draw(shader); + } + +private: + // loads a model with supported ASSIMP extensions from file and stores the resulting meshes in the meshes vector. + void loadModel(string const& path) + { + // read file via ASSIMP + Assimp::Importer importer; + const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs | aiProcess_CalcTangentSpace); + // check for errors + if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero + { + cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << endl; + return; + } + // retrieve the directory path of the filepath + directory = path.substr(0, path.find_last_of('/')); + + // process ASSIMP's root node recursively + processNode(scene->mRootNode, scene,glm::mat4()); + } + + // processes a node in a recursive fashion. Processes each individual mesh located at the node and repeats this process on its children nodes (if any). + void processNode(aiNode* node, const aiScene* scene,glm::mat4 matrix) + { + glm::mat4 outMatrix = matrix * mat4_cast(node->mTransformation); + // process each mesh located at the current node + for (unsigned int i = 0; i < node->mNumMeshes; i++) + { + // the node object only contains indices to index the actual objects in the scene. + // the scene contains all the data, node is just to keep stuff organized (like relations between nodes). + aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; + meshes.push_back(processMesh(mesh, scene, outMatrix)); + } + // after we've processed all of the meshes (if any) we then recursively process each of the children nodes + for (unsigned int i = 0; i < node->mNumChildren; i++) + { + processNode(node->mChildren[i], scene, outMatrix); + } + + } + + Mesh processMesh(aiMesh* mesh, const aiScene* scene, glm::mat4 matrix) + { + // data to fill + vector vertices; + vector indices; + vector textures; + + // walk through each of the mesh's vertices + for (unsigned int i = 0; i < mesh->mNumVertices; i++) + { + Vertex vertex; + glm::vec3 vector; // we declare a placeholder vector since assimp uses its own vector class that doesn't directly convert to glm's vec3 class so we transfer the data to this placeholder glm::vec3 first. + // positions + vector.x = mesh->mVertices[i].x; + vector.y = mesh->mVertices[i].y; + vector.z = mesh->mVertices[i].z; + vertex.Position = vector; + // normals + if (mesh->HasNormals()) + { + vector.x = mesh->mNormals[i].x; + vector.y = mesh->mNormals[i].y; + vector.z = mesh->mNormals[i].z; + vertex.Normal = vector; + } + // texture coordinates + if (mesh->mTextureCoords[0]) // does the mesh contain texture coordinates? + { + glm::vec2 vec; + // a vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't + // use models where a vertex can have multiple texture coordinates so we always take the first set (0). + vec.x = mesh->mTextureCoords[0][i].x; + vec.y = mesh->mTextureCoords[0][i].y; + vertex.TexCoords = vec; + // tangent + vector.x = mesh->mTangents[i].x; + vector.y = mesh->mTangents[i].y; + vector.z = mesh->mTangents[i].z; + vertex.Tangent = vector; + // bitangent + vector.x = mesh->mBitangents[i].x; + vector.y = mesh->mBitangents[i].y; + vector.z = mesh->mBitangents[i].z; + vertex.Bitangent = vector; + } + else + vertex.TexCoords = glm::vec2(0.0f, 0.0f); + + vertices.push_back(vertex); + } + // now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices. + for (unsigned int i = 0; i < mesh->mNumFaces; i++) + { + aiFace face = mesh->mFaces[i]; + // retrieve all indices of the face and store them in the indices vector + for (unsigned int j = 0; j < face.mNumIndices; j++) + indices.push_back(face.mIndices[j]); + } + // process materials + aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; + // we assume a convention for sampler names in the shaders. Each diffuse texture should be named + // as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER. + // Same applies to other texture as the following list summarizes: + // diffuse: texture_diffuseN + // specular: texture_specularN + // normal: texture_normalN + + // 1. diffuse maps + vector diffuseMaps = loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse"); + textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end()); + // 2. specular maps + vector specularMaps = loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular"); + textures.insert(textures.end(), specularMaps.begin(), specularMaps.end()); + // 3. normal maps + std::vector normalMaps = loadMaterialTextures(material, aiTextureType_HEIGHT, "texture_normal"); + textures.insert(textures.end(), normalMaps.begin(), normalMaps.end()); + // 4. height maps + std::vector heightMaps = loadMaterialTextures(material, aiTextureType_AMBIENT, "texture_height"); + textures.insert(textures.end(), heightMaps.begin(), heightMaps.end()); + + + // return a mesh object created from the extracted mesh data + return Mesh(vertices, indices, textures, matrix); + } + + // checks all material textures of a given type and loads the textures if they're not loaded yet. + // the required info is returned as a Texture struct. + vector loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName) + { + vector textures; + for (unsigned int i = 0; i < mat->GetTextureCount(type); i++) + { + aiString str; + mat->GetTexture(type, i, &str); + // check if texture was loaded before and if so, continue to next iteration: skip loading a new texture + bool skip = false; + for (unsigned int j = 0; j < textures_loaded.size(); j++) + { + if (std::strcmp(textures_loaded[j].path.data(), str.C_Str()) == 0) + { + textures.push_back(textures_loaded[j]); + skip = true; // a texture with the same filepath has already been loaded, continue to next one. (optimization) + break; + } + } + if (!skip) + { // if texture hasn't been loaded already, load it + Texture texture; + texture.id = TextureFromFile(str.C_Str(), this->directory); + texture.type = typeName; + texture.path = str.C_Str(); + textures.push_back(texture); + textures_loaded.push_back(texture); // store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures. + } + } + return textures; + } +}; + + +unsigned int TextureFromFile(const char* path, const string& directory, bool gamma) +{ + string filename = string(path); + filename = directory + '/' + filename; + + unsigned int textureID; + glGenTextures(1, &textureID); + + int width, height, nrComponents; + unsigned char* data = stbi_load(filename.c_str(), &width, &height, &nrComponents, 0); + if (data) + { + GLenum format; + if (nrComponents == 1) + format = GL_RED; + else if (nrComponents == 3) + format = GL_RGB; + else if (nrComponents == 4) + format = GL_RGBA; + + glBindTexture(GL_TEXTURE_2D, textureID); + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); + glGenerateMipmap(GL_TEXTURE_2D); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + stbi_image_free(data); + } + else + { + std::cout << "Texture failed to load at path: " << path << std::endl; + stbi_image_free(data); + } + + return textureID; +} \ No newline at end of file diff --git a/grafika_projekt/src/objload.h b/grafika_projekt/src/objload.h index 004ab4e..5bc514e 100644 --- a/grafika_projekt/src/objload.h +++ b/grafika_projekt/src/objload.h @@ -40,7 +40,7 @@ struct Model { std::vector texCoord; //< 2 * N entries std::vector normal; //< 3 * N entries - std::map > faces; //< assume triangels and uniform indexing + std::map > faces; //< assume triangels and uniform indexing }; struct ObjModel { @@ -221,10 +221,10 @@ Model convertToModel( const ObjModel & obj ) { for(std::map::const_iterator g = obj.faces.begin(); g != obj.faces.end(); ++g){ const std::string & name = g->first; const ObjModel::FaceList & fl = g->second; - std::vector & v = model.faces[g->first]; + std::vector & v = model.faces[g->first]; v.reserve(fl.first.size()); for(std::vector::const_iterator f = fl.first.begin(); f != fl.first.end(); ++f){ - const unsigned short index = std::distance(unique.begin(), std::lower_bound(unique.begin(), unique.end(), *f)); + const unsigned int index = std::distance(unique.begin(), std::lower_bound(unique.begin(), unique.end(), *f)); v.push_back(index); } } @@ -276,7 +276,7 @@ std::ostream & operator<<( std::ostream & out, const Model & m ){ } if(!m.faces.empty()){ out << "faces\t"; - for(std::map >::const_iterator g = m.faces.begin(); g != m.faces.end(); ++g){ + for(std::map >::const_iterator g = m.faces.begin(); g != m.faces.end(); ++g){ out << g->first << " "; } out << "\n"; diff --git a/grafika_projekt/textures/terrain.jpg b/grafika_projekt/textures/terrain.jpg new file mode 100644 index 0000000..207472a Binary files /dev/null and b/grafika_projekt/textures/terrain.jpg differ