diff --git a/data/levels/Level1.xml b/data/levels/Level1.xml index ded32c5..01de205 100644 --- a/data/levels/Level1.xml +++ b/data/levels/Level1.xml @@ -13103,7 +13103,7 @@ 14.5 - skydomeNew.png + waterTexture.png diff --git a/data/shader/phong.fsh b/data/shader/phong.fsh index a4a563d..507e19a 100644 --- a/data/shader/phong.fsh +++ b/data/shader/phong.fsh @@ -45,6 +45,7 @@ uniform vec4 fogColorNight; uniform vec3 cameraCenter; uniform bool movingTexture; uniform vec2 movement; +uniform vec2 movingTextureOffset; uniform float time; vec2 poissonDisk[16] = vec2[]( @@ -249,7 +250,7 @@ void main() vec4 textureColor = vec4(0.0, 0.0, 0.0, 1.0); if (movingTexture == true) { - textureColor = texture(uTexture, vec2(vTexCoord.x + movement.x * time, vTexCoord.y + movement.y * time)).rgba; + textureColor = texture(uTexture, vec2(vTexCoord.x + movingTextureOffset.x, vTexCoord.y + movingTextureOffset.y)).rgba; } else { textureColor = texture(uTexture, vTexCoord).rgba; diff --git a/data/textures/waterTexture.png b/data/textures/waterTexture.png new file mode 100644 index 0000000..6c39f7b Binary files /dev/null and b/data/textures/waterTexture.png differ diff --git a/data/textures/waterTexture.xcf b/data/textures/waterTexture.xcf new file mode 100644 index 0000000..364c049 Binary files /dev/null and b/data/textures/waterTexture.xcf differ diff --git a/graphics.cc b/graphics.cc index b4bf2b6..acf473f 100644 --- a/graphics.cc +++ b/graphics.cc @@ -10,6 +10,7 @@ using namespace ACGL::OpenGL; const double lightUpdateDelay = 0.5f; +const double windUpdateDelay = 0.5f; Graphics::Graphics(glm::uvec2 windowSize, float nearPlane, float farPlane, int cube_size, @@ -45,7 +46,14 @@ void Graphics::init(Level* level) { // update lights on creation - lastUpdate = -lightUpdateDelay; + lastLightUpdate = -lightUpdateDelay; + + lastWindUpdate = - windUpdateDelay; + windTarget = 0.0f; + wind = glm::vec2(0.0f, 0.0f); + windDirection = glm::vec2(-1.0f, -1.0f); + windDirectionTarget = glm::vec2(-1.0f, -1.0f); + textureMovementPosition = glm::vec2(0.0, 0.0); // construct VAO to give shader correct Attribute locations SharedArrayBuffer ab = SharedArrayBuffer(new ArrayBuffer()); @@ -77,6 +85,25 @@ void Graphics::init(Level* level) { flameShader = ShaderProgramCreator("flame") .attributeLocations(flame_positions->getAttributeLocations()).create(); + fullscreen_quad_ab = SharedArrayBuffer(new ArrayBuffer()); + fullscreen_quad_ab->defineAttribute("aPosition", GL_FLOAT, 2); + fullscreen_quad_ab->defineAttribute("aTexCoord", GL_FLOAT, 2); + + float quadData[] = { + -1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + + 1.0f, -1.0f, 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, 0.0f, + -1.0f, 1.0f, 0.0f, 1.0f + }; + + fullscreen_quad_ab->setDataElements(6, quadData); + + fullscreen_quad = SharedVertexArrayObject(new VertexArrayObject); + fullscreen_quad->attachAllAttributes(fullscreen_quad_ab); + flamePostShader = ShaderProgramCreator("flame_post") .attributeLocations(fullscreen_quad->getAttributeLocations()).create(); @@ -173,35 +200,58 @@ void Graphics::renderLoadingScreen() { printf("You need at least 18 texture units to run this application. Exiting\n"); exit(-1); } - fullscreen_quad_ab = SharedArrayBuffer(new ArrayBuffer()); - fullscreen_quad_ab->defineAttribute("aPosition", GL_FLOAT, 2); - fullscreen_quad_ab->defineAttribute("aTexCoord", GL_FLOAT, 2); - - float quadData[] = { - -1.0f, 1.0f, 0.0f, 1.0f, - 1.0f, 1.0f, 1.0f, 1.0f, - 1.0f, -1.0f, 1.0f, 0.0f, - - 1.0f, -1.0f, 1.0f, 0.0f, - -1.0f, -1.0f, 0.0f, 0.0f, - -1.0f, 1.0f, 0.0f, 1.0f - }; - - fullscreen_quad_ab->setDataElements(6, quadData); - - fullscreen_quad = SharedVertexArrayObject(new VertexArrayObject); - fullscreen_quad->attachAllAttributes(fullscreen_quad_ab); loadingScreen = Texture2DFileManager::the()->get(Texture2DCreator(loadingScreenPath)); loadingScreen->generateMipmaps(); loadingContinueScreen = Texture2DFileManager::the()->get(Texture2DCreator(loadingScreenContinuePath)); loadingContinueScreen->generateMipmaps(); + loadingScreenWidth = (float)loadingScreen->getWidth(); + loadingScreenHeight = (float)loadingScreen->getHeight(); + + fullscreen_quad_ab_loading = SharedArrayBuffer(new ArrayBuffer()); + fullscreen_quad_ab_loading->defineAttribute("aPosition", GL_FLOAT, 2); + fullscreen_quad_ab_loading->defineAttribute("aTexCoord", GL_FLOAT, 2); + + float quadData[24]; + if (loadingScreenWidth/loadingScreenHeight < ((float)windowSize.x)/((float)windowSize.y)) { + float quadTemp[24] ={ + -(((float)windowSize.y*loadingScreenWidth)/((float)windowSize.x*loadingScreenHeight)), 1.0f, 0.0f, 1.0f, + (((float)windowSize.y*loadingScreenWidth)/((float)windowSize.x*loadingScreenHeight)), 1.0f, 1.0f, 1.0f, + (((float)windowSize.y*loadingScreenWidth)/((float)windowSize.x*loadingScreenHeight)), -1.0f, 1.0f, 0.0f, + + (((float)windowSize.y*loadingScreenWidth)/((float)windowSize.x*loadingScreenHeight)), -1.0f, 1.0f, 0.0f, + -(((float)windowSize.y*loadingScreenWidth)/((float)windowSize.x*loadingScreenHeight)), -1.0f, 0.0f, 0.0f, + -(((float)windowSize.y*loadingScreenWidth)/((float)windowSize.x*loadingScreenHeight)), 1.0f, 0.0f, 1.0f + }; + for(int i = 0; i<24; i++) { + quadData[i] = quadTemp[i]; + } + } + else { + float quadTemp[24] = { + -1.0f, ((float)windowSize.x*loadingScreenHeight)/((float)windowSize.y*loadingScreenWidth), 0.0f, 1.0f, + 1.0f, ((float)windowSize.x*loadingScreenHeight)/((float)windowSize.y*loadingScreenWidth), 1.0f, 1.0f, + 1.0f, -((float)windowSize.x*loadingScreenHeight)/((float)windowSize.y*loadingScreenWidth), 1.0f, 0.0f, + + 1.0f, -((float)windowSize.x*loadingScreenHeight)/((float)windowSize.y*loadingScreenWidth), 1.0f, 0.0f, + -1.0f, -((float)windowSize.x*loadingScreenHeight)/((float)windowSize.y*loadingScreenWidth), 0.0f, 0.0f, + -1.0f, ((float)windowSize.x*loadingScreenHeight)/((float)windowSize.y*loadingScreenWidth), 0.0f, 1.0f + }; + for(int i = 0; i<24; i++) { + quadData[i] = quadTemp[i]; + } + } + + fullscreen_quad_ab_loading->setDataElements(6, quadData); + + fullscreen_quad_loading = SharedVertexArrayObject(new VertexArrayObject); + fullscreen_quad_loading->attachAllAttributes(fullscreen_quad_ab_loading); loadingShader = ShaderProgramCreator("loading") - .attributeLocations(fullscreen_quad->getAttributeLocations()).create(); + .attributeLocations(fullscreen_quad_loading->getAttributeLocations()).create(); loadingShader->use(); loadingShader->setUniform("time", 0.0f); loadingShader->setTexture("screen", loadingScreen, 16); loadingShader->setTexture("screenContinue", loadingContinueScreen, 17); - fullscreen_quad->render(); + fullscreen_quad_loading->render(); } glm::uvec2 Graphics::getWindowSize() { @@ -215,14 +265,47 @@ void Graphics::render(double time) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); loadingShader->use(); loadingShader->setUniform("time", float(time)); - fullscreen_quad->render(); + float quadData[24]; + if (loadingScreenWidth/loadingScreenHeight < ((float)windowSize.x)/((float)windowSize.y)) { + float quadTemp[24] ={ + -(((float)windowSize.y*loadingScreenWidth)/((float)windowSize.x*loadingScreenHeight)), 1.0f, 0.0f, 1.0f, + (((float)windowSize.y*loadingScreenWidth)/((float)windowSize.x*loadingScreenHeight)), 1.0f, 1.0f, 1.0f, + (((float)windowSize.y*loadingScreenWidth)/((float)windowSize.x*loadingScreenHeight)), -1.0f, 1.0f, 0.0f, + + (((float)windowSize.y*loadingScreenWidth)/((float)windowSize.x*loadingScreenHeight)), -1.0f, 1.0f, 0.0f, + -(((float)windowSize.y*loadingScreenWidth)/((float)windowSize.x*loadingScreenHeight)), -1.0f, 0.0f, 0.0f, + -(((float)windowSize.y*loadingScreenWidth)/((float)windowSize.x*loadingScreenHeight)), 1.0f, 0.0f, 1.0f + }; + for(int i = 0; i<24; i++) { + quadData[i] = quadTemp[i]; + } + } + else { + float quadTemp[24] = { + -1.0f, ((float)windowSize.x*loadingScreenHeight)/((float)windowSize.y*loadingScreenWidth), 0.0f, 1.0f, + 1.0f, ((float)windowSize.x*loadingScreenHeight)/((float)windowSize.y*loadingScreenWidth), 1.0f, 1.0f, + 1.0f, -((float)windowSize.x*loadingScreenHeight)/((float)windowSize.y*loadingScreenWidth), 1.0f, 0.0f, + + 1.0f, -((float)windowSize.x*loadingScreenHeight)/((float)windowSize.y*loadingScreenWidth), 1.0f, 0.0f, + -1.0f, -((float)windowSize.x*loadingScreenHeight)/((float)windowSize.y*loadingScreenWidth), 0.0f, 0.0f, + -1.0f, ((float)windowSize.x*loadingScreenHeight)/((float)windowSize.y*loadingScreenWidth), 0.0f, 1.0f + }; + for(int i = 0; i<24; i++) { + quadData[i] = quadTemp[i]; + } + } + + fullscreen_quad_ab_loading->setDataElements(6, quadData); + fullscreen_quad_loading = SharedVertexArrayObject(new VertexArrayObject); + fullscreen_quad_loading->attachAllAttributes(fullscreen_quad_ab_loading); + fullscreen_quad_loading->render(); } else { - double nextUpdate = lastUpdate + lightUpdateDelay; - if (time >= nextUpdate) + double nextLightUpdate = lastLightUpdate + lightUpdateDelay; + if (time >= nextLightUpdate) { updateLights(); - lastUpdate = time; + lastLightUpdate = time; } // At first render shadows depthCubeShader->use(); @@ -292,7 +375,34 @@ void Graphics::render(double time) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //wind - glm::vec2 wind = glm::vec2(0.0f, 0.0f); + double nextWindUpdate = lastWindUpdate + lightUpdateDelay; + if (time >= nextWindUpdate) + { + const float windTargetEnd = 0.7f; + windTarget = static_cast(rand()) / static_cast(RAND_MAX/pow(windTargetEnd, 2)); + windTarget = sqrt(windTarget); + windTarget *= 0.8f*pow(sin(0.1f*time), 2) +0.2f; + const float windDirectionXEnd = 0.5f; + float windDirectionX = static_cast(rand()) / static_cast(RAND_MAX/pow(windDirectionXEnd, 2)); + windDirectionX = sqrt(windDirectionX); + const float windDirectionYEnd = 0.5f; + float windDirectionY = static_cast(rand()) / static_cast(RAND_MAX/pow(windDirectionYEnd, 2)); + windDirectionY = sqrt(windDirectionY); + windDirectionTarget = glm::vec2(windDirectionX, windDirectionY); + lastWindUpdate = time; + } + + const float windApproachSpeed= 0.0005f; + + if (windApproachSpeed*static_cast(time)>1.0f) { + wind = glm::normalize(windDirection)*windTarget; + windDirection = windDirectionTarget; + } + else { + windDirection.x = windDirection.x + windApproachSpeed*static_cast(time)*windDirectionTarget.x - windDirection.x; + windDirection.y = windDirection.y + windApproachSpeed*static_cast(time)*windDirectionTarget.y - windDirection.x; + wind = wind + (windApproachSpeed*static_cast(time)) * (glm::normalize(windDirection)*windTarget - wind); + } //set view and projection matrix glm::mat4 lightingViewProjectionMatrix = glm::perspective(1.571f, (float)windowSize.x/(float)windowSize.y, 0.1f, farPlane) * buildViewMatrix(level); @@ -342,7 +452,10 @@ void Graphics::render(double time) // set Material Parameters lightingShader->setUniform("ambientColor", level->getAmbientLight()); lightingShader->setUniform("camera", level->getPhysics()->getCameraPosition()); + textureMovementPosition += wind/5.0f; + lightingShader->setUniform("movingTextureOffset", textureMovementPosition); lightingShader->setUniform("movement", wind); + lightingShader->setUniform("time", (float) time); // render the level diff --git a/graphics.hh b/graphics.hh index 085b15c..cad8070 100644 --- a/graphics.hh +++ b/graphics.hh @@ -30,7 +30,13 @@ class Graphics { void updateClosestLights(); bool compareLightDistances(Light a, Light b); void saveDepthBufferToDisk(int face, std::string); - double lastUpdate; + double lastLightUpdate; + double lastWindUpdate; + float windTarget; + glm::vec2 wind; + glm::vec2 windDirection; + glm::vec2 windDirectionTarget; + glm::vec2 textureMovementPosition; glm::uvec2 windowSize; float nearPlane; float farPlane; @@ -56,11 +62,15 @@ class Graphics { SharedTexture2D light_fbo_depth_texture; SharedVertexArrayObject fullscreen_quad; SharedArrayBuffer fullscreen_quad_ab; + SharedVertexArrayObject fullscreen_quad_loading; + SharedArrayBuffer fullscreen_quad_ab_loading; int cube_size; unsigned int maxShadowRenderCount; Level* level; int number_of_texture_units = 0; bool gameStart; + float loadingScreenWidth; + float loadingScreenHeight; }; #endif diff --git a/level.cc b/level.cc index 574d5cd..f9abdcb 100644 --- a/level.cc +++ b/level.cc @@ -19,6 +19,7 @@ Level::~Level() { } for(unsigned int i = 0; irender(shader, lightingPass, true, viewProjectionMatrix, shadowVPs); + waterPlane->render(shader, lightingPass, true, viewProjectionMatrix, shadowVPs); } else { objects.at(i)->render(shader, lightingPass, false, viewProjectionMatrix, shadowVPs); @@ -319,3 +321,7 @@ void Level::forceMove(float x, float y, float z, unsigned indice){ void Level::activateEndgame(){ physics.activateEndgame(); } + +void Level::setWaterPlane(Object* water) { + this->waterPlane = water; +} diff --git a/level.hh b/level.hh index 7d55e9d..5811b9e 100644 --- a/level.hh +++ b/level.hh @@ -39,6 +39,7 @@ class Level { glm::vec4 getFogColourNight(); void setSkydomeSize(float size); float getSkydomeSize(); + void setWaterPlane(Object* water); Skydome* getSkydome(); std::vector* getObjects(); std::vector* getPhysicsObjects(); @@ -76,6 +77,7 @@ class Level { std::vector physicsObjects; std::vector lights; std::vector triggers; + Object* waterPlane; glm::vec3 ambientLight; glm::vec4 fogColourDay; glm::vec4 fogColourRise; diff --git a/loader.cc b/loader.cc index b9b588c..e2a3bf6 100644 --- a/loader.cc +++ b/loader.cc @@ -147,7 +147,7 @@ void Loader::load(std::string filePath, Level* level, std::string compositionsPa water_vao->attachAllAttributes(water_ab); Material water_material = Material(waterTexture, 0.1f, 0.2f, 0.8f, 5.0f, true); Object* water_object = new Object(water_vao, water_material, glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 0.0f, 0.0f), true); - level->addObject(water_object); + level->setWaterPlane(water_object); } //load lighting parameters