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