Browse Source

Moved water rendering to WaterMaster. Sorted light list. Removed slick-util dependency. Formatting.

Tankernn 9 years ago
parent
commit
f64d489888

+ 1 - 1
.classpath

@@ -7,7 +7,6 @@
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
-	<classpathentry kind="lib" path="lib/slick-util/slick-util.jar"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/LWJGL">
 		<attributes>
 			<attribute name="org.eclipse.jdt.launching.CLASSPATH_ATTR_LIBRARY_PATH_ENTRY" value="Tankernn game engine/lib/lwjgl-2.9.3/native"/>
@@ -24,5 +23,6 @@
 			<attribute name="maven.pomderived" value="true"/>
 		</attributes>
 	</classpathentry>
+	<classpathentry kind="lib" path="lib/PNGDecoder.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>

BIN
lib/PNGDecoder.jar


+ 3 - 3
pom.xml

@@ -29,9 +29,9 @@
 			<version>2.9.3</version>
 		</dependency>
 		<dependency>
-			<groupId>org.slick2d</groupId>
-			<artifactId>slick2d-core</artifactId>
-			<version>1.0.0</version>
+			<groupId>org.l33tlabs.twl</groupId>
+			<artifactId>pngdecoder</artifactId>
+			<version>1.0</version>
 		</dependency>
 	</dependencies>
 

+ 2 - 2
src/main/java/eu/tankernn/gameEngine/entities/Camera.java

@@ -10,7 +10,7 @@ import org.lwjgl.util.vector.Vector3f;
 
 import eu.tankernn.gameEngine.terrains.TerrainPack;
 
-public class Camera {
+public class Camera implements Positionable {
 	
 	private float distanceFromPlayer = 50;
 	private float angleAroundPlayer = 0;
@@ -47,8 +47,8 @@ public class Camera {
 			calculateAngleAroundPlayer();
 			
 			if (Mouse.isButtonDown(1)) {
+				float targetRot = this.angleAroundPlayer + this.lockedPosition;
 				this.lockedPosition = 0;
-				float targetRot = this.angleAroundPlayer;
 				float delta = targetRot - player.getRotY();
 				player.increaseRotation(0, delta, 0);
 			}

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/entities/Entity.java

@@ -5,7 +5,7 @@ import org.lwjgl.util.vector.Vector3f;
 import eu.tankernn.gameEngine.models.AABB;
 import eu.tankernn.gameEngine.models.TexturedModel;
 
-public class Entity {
+public class Entity implements Positionable {
 	private static final Vector3f SIZE = new Vector3f(2, 4, 2);
 	
 	private TexturedModel model;

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/entities/Light.java

@@ -2,7 +2,7 @@ package eu.tankernn.gameEngine.entities;
 
 import org.lwjgl.util.vector.Vector3f;
 
-public class Light {
+public class Light implements Positionable {
 	private Vector3f position;
 	private Vector3f color;
 	private Vector3f attenuation = new Vector3f(1, 0, 0);

+ 7 - 0
src/main/java/eu/tankernn/gameEngine/entities/Positionable.java

@@ -0,0 +1,7 @@
+package eu.tankernn.gameEngine.entities;
+
+import org.lwjgl.util.vector.Vector3f;
+
+public interface Positionable {
+	public Vector3f getPosition();
+}

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/font/meshCreator/GUIText.java

@@ -88,7 +88,7 @@ public class GUIText {
 	 * @param b
 	 *            - blue value, between 0 and 1.
 	 */
-	public void setColour(float r, float g, float b) {
+	public void setColor(float r, float g, float b) {
 		colour.set(r, g, b);
 	}
 

+ 1 - 4
src/main/java/eu/tankernn/gameEngine/normalMapping/objConverter/NormalMappedObjLoader.java

@@ -1,9 +1,6 @@
 package eu.tankernn.gameEngine.normalMapping.objConverter;
 
 import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
@@ -79,7 +76,7 @@ public class NormalMappedObjLoader {
 		float[] texturesArray = new float[vertices.size() * 2];
 		float[] normalsArray = new float[vertices.size() * 3];
 		float[] tangentsArray = new float[vertices.size() * 3];
-		float furthest = convertDataToArrays(vertices, textures, normals, verticesArray,
+		/*float furthest = */convertDataToArrays(vertices, textures, normals, verticesArray,
 				texturesArray, normalsArray, tangentsArray);
 		int[] indicesArray = convertIndicesListToArray(indices);
 

+ 55 - 24
src/main/java/eu/tankernn/gameEngine/renderEngine/Loader.java

@@ -1,7 +1,5 @@
 package eu.tankernn.gameEngine.renderEngine;
 
-import java.awt.Font;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
@@ -18,11 +16,8 @@ import org.lwjgl.opengl.GL15;
 import org.lwjgl.opengl.GL20;
 import org.lwjgl.opengl.GL30;
 import org.lwjgl.opengl.GL33;
-import org.newdawn.slick.TrueTypeFont;
-import org.newdawn.slick.opengl.PNGDecoder;
-import org.newdawn.slick.opengl.Texture;
-import org.newdawn.slick.opengl.TextureLoader;
-
+import de.matthiasmann.twl.utils.PNGDecoder;
+import de.matthiasmann.twl.utils.PNGDecoder.Format;
 import eu.tankernn.gameEngine.models.RawModel;
 import eu.tankernn.gameEngine.objLoader.ModelData;
 import eu.tankernn.gameEngine.textures.TextureData;
@@ -101,28 +96,68 @@ public class Loader {
 	}
 	
 	public int loadTexture(String filename) {
-		Texture texture = null;
+		int textureID = 0;
 		try {
-			texture = TextureLoader.getTexture("PNG", getClass().getResourceAsStream("/" + filename + ".png") /*new FileInputStream("res/" + filename + ".png")*/);
-			GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
-			GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR);
+			textureID = loadPNGTexture(getClass().getResourceAsStream("/" + filename + ".png"), GL13.GL_TEXTURE0);
 			GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, -2.4f);
-		} catch (FileNotFoundException e) {
+		} catch (NullPointerException e) {
 			System.err.println("Could not load texture: " + filename);
 			e.printStackTrace();
+		}
+		
+		textures.add(textureID);
+		
+		return textureID;
+	}
+	
+	private int loadPNGTexture(InputStream file, int textureUnit) {
+		ByteBuffer buf = null;
+		int tWidth = 0;
+		int tHeight = 0;
+		
+		try {
+			// Link the PNG decoder to this stream
+			PNGDecoder decoder = new PNGDecoder(file);
+			
+			// Get the width and height of the texture
+			tWidth = decoder.getWidth();
+			tHeight = decoder.getHeight();
+			
+			// Decode the PNG file in a ByteBuffer
+			buf = ByteBuffer.allocateDirect(4 * decoder.getWidth() * decoder.getHeight());
+			decoder.decode(buf, decoder.getWidth() * 4, Format.RGBA);
+			buf.flip();
+			
+			file.close();
 		} catch (IOException e) {
 			e.printStackTrace();
+			System.exit(-1);
 		}
 		
-		int textureID = texture.getTextureID();
-		textures.add(textureID);
+		// Create a new texture object in memory and bind it
+		int texId = GL11.glGenTextures();
+		GL13.glActiveTexture(textureUnit);
+		GL11.glBindTexture(GL11.GL_TEXTURE_2D, texId);
+		
+		// All RGB bytes are aligned to each other and each component is 1 byte
+		GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
+		
+		// Upload the texture data and generate mip maps (for scaling)
+		GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, tWidth, tHeight, 0,
+				GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buf);
+		GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
 		
-		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
-		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
+		// Setup the ST coordinate system
 		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
 		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
 		
-		return textureID;
+		// Setup what to do when the texture has to be scaled
+		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER,
+				GL11.GL_NEAREST);
+		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER,
+				GL11.GL_LINEAR_MIPMAP_LINEAR);
+		
+		return texId;
 	}
 	
 	/**
@@ -133,6 +168,7 @@ public class Loader {
 	 * File 3: Bottom face
 	 * File 4: Back face
 	 * File 5: Front face
+	 * 
 	 * @param textureFiles Filenames of images that make up the cube map
 	 * @return The ID of the new cube map
 	 */
@@ -147,7 +183,7 @@ public class Loader {
 			GL11.glTexImage2D(GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL11.GL_RGBA, data.getWidth(), data.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, data.getBuffer());
 		}
 		GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
-		GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);		
+		GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
 		textures.add(texID);
 		return texID;
 	}
@@ -162,7 +198,7 @@ public class Loader {
 			width = decoder.getWidth();
 			height = decoder.getHeight();
 			buffer = ByteBuffer.allocateDirect(4 * width * height);
-			decoder.decode(buffer, width * 4, PNGDecoder.RGBA);
+			decoder.decode(buffer, width * 4, Format.RGBA);
 			buffer.flip();
 			in.close();
 		} catch (Exception e) {
@@ -173,11 +209,6 @@ public class Loader {
 		return new TextureData(buffer, width, height);
 	}
 	
-	public TrueTypeFont loadFont(String fontName) {
-		Font awtFont = new Font(fontName, Font.BOLD, 24);
-		return new TrueTypeFont(awtFont, false);
-	}
-	
 	public void cleanUp() {
 		for (int vao: vaos)
 			GL30.glDeleteVertexArrays(vao);

+ 5 - 6
src/main/java/eu/tankernn/gameEngine/renderEngine/MasterRenderer.java

@@ -30,7 +30,6 @@ import eu.tankernn.gameEngine.shaders.TerrainShader;
 import eu.tankernn.gameEngine.shadows.ShadowMapMasterRenderer;
 import eu.tankernn.gameEngine.skybox.SkyboxRenderer;
 import eu.tankernn.gameEngine.terrains.Terrain;
-import eu.tankernn.gameEngine.terrains.TerrainPack;
 
 public class MasterRenderer {
 	private StaticShader staticShader = new StaticShader();
@@ -69,15 +68,15 @@ public class MasterRenderer {
 		GL11.glDisable(GL11.GL_CULL_FACE);
 	}
 	
-	public void renderScene(List<Entity> entities, List<Entity> normalEntities, TerrainPack terrainPack, List<Light> lights, Camera camera, Vector4f clipPlane) {
-		terrainPack.prepareRenderTerrains(this);
-		for (Entity e : entities) {
+	public void renderScene(Scene scene, Vector4f clipPlane) {
+		scene.getTerrainPack().prepareRenderTerrains(this);
+		for (Entity e : scene.getEntities()) {
 			processEntity(e);
 		}
-		for (Entity e : normalEntities) {
+		for (Entity e : scene.getNormalEntities()) {
 			processNormalMappedEntity(e);
 		}
-		render(lights, camera, clipPlane);
+		render(scene.getLights(), scene.getCamera(), clipPlane);
 	}
 	
 	public void render(List<Light> lights, Camera camera, Vector4f clipPlane) {

+ 44 - 0
src/main/java/eu/tankernn/gameEngine/renderEngine/Scene.java

@@ -0,0 +1,44 @@
+package eu.tankernn.gameEngine.renderEngine;
+
+import java.util.List;
+
+import eu.tankernn.gameEngine.entities.Camera;
+import eu.tankernn.gameEngine.entities.Entity;
+import eu.tankernn.gameEngine.entities.Light;
+import eu.tankernn.gameEngine.terrains.TerrainPack;
+
+public class Scene {
+	private List<Entity> entities;
+	private List<Entity> normalEntities;
+	private TerrainPack terrainPack;
+	private List<Light> lights;
+	private Camera camera;
+	
+	public Scene(List<Entity> entities, List<Entity> normalEntities, TerrainPack terrainPack, List<Light> lights, Camera camera) {
+		this.entities = entities;
+		this.normalEntities = normalEntities;
+		this.terrainPack = terrainPack;
+		this.lights = lights;
+		this.camera = camera;
+	}
+
+	public List<Entity> getEntities() {
+		return entities;
+	}
+
+	public List<Entity> getNormalEntities() {
+		return normalEntities;
+	}
+
+	public TerrainPack getTerrainPack() {
+		return terrainPack;
+	}
+
+	public List<Light> getLights() {
+		return lights;
+	}
+
+	public Camera getCamera() {
+		return camera;
+	}
+}

+ 0 - 3
src/main/java/eu/tankernn/gameEngine/shaders/ShaderProgram.java

@@ -1,11 +1,8 @@
 package eu.tankernn.gameEngine.shaders;
 
 import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
-import java.net.URLDecoder;
 import java.nio.FloatBuffer;
 
 import org.lwjgl.opengl.GL11;

+ 13 - 13
src/main/java/eu/tankernn/gameEngine/skybox/SkyboxRenderer.java

@@ -92,35 +92,35 @@ public class SkyboxRenderer {
 		shader.stop();
 	}
 	
-	private void bindTextures(){ //TODO make day/night cycle better
+	private void bindTextures() {
 		time += DisplayManager.getFrameTimeSeconds() * 1000;
 		time %= DAY_LENGTH;
 		
-		int morning = (int) (DAY_LENGTH/4.8);
-		int noon = (int) (DAY_LENGTH/3);
-		int evening = (int) (DAY_LENGTH/1.14);
+		int morning = (int) (DAY_LENGTH / 4.8);
+		int noon = (int) (DAY_LENGTH / 3);
+		int evening = (int) (DAY_LENGTH / 1.14);
 		
 		int texture1;
 		int texture2;
 		float blendFactor;
-		if(time >= 0 && time < morning){
+		if (time >= 0 && time < morning) {
 			texture1 = nightTexture;
 			texture2 = nightTexture;
-			blendFactor = (time - 0)/(morning - 0);
-		}else if(time >= morning && time < noon){
+			blendFactor = (time - 0) / (morning - 0);
+		} else if (time >= morning && time < noon) {
 			texture1 = nightTexture;
 			texture2 = texture;
-			blendFactor = (time - morning)/(noon - morning);
-		}else if(time >= noon && time < evening){
+			blendFactor = (time - morning) / (noon - morning);
+		} else if (time >= noon && time < evening) {
 			texture1 = texture;
 			texture2 = texture;
-			blendFactor = (time - noon)/(evening - noon);
-		}else{
+			blendFactor = (time - noon) / (evening - noon);
+		} else {
 			texture1 = texture;
 			texture2 = nightTexture;
-			blendFactor = (time - evening)/(DAY_LENGTH - evening);
+			blendFactor = (time - evening) / (DAY_LENGTH - evening);
 		}
-
+		
 		GL13.glActiveTexture(GL13.GL_TEXTURE0);
 		GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texture1);
 		GL13.glActiveTexture(GL13.GL_TEXTURE1);

+ 27 - 40
src/main/java/eu/tankernn/gameEngine/tester/MainLoop.java

@@ -36,13 +36,16 @@ import eu.tankernn.gameEngine.particles.ParticleTexture;
 import eu.tankernn.gameEngine.renderEngine.DisplayManager;
 import eu.tankernn.gameEngine.renderEngine.Loader;
 import eu.tankernn.gameEngine.renderEngine.MasterRenderer;
+import eu.tankernn.gameEngine.renderEngine.Scene;
 import eu.tankernn.gameEngine.terrains.Terrain;
 import eu.tankernn.gameEngine.terrains.TerrainPack;
 import eu.tankernn.gameEngine.textures.ModelTexture;
 import eu.tankernn.gameEngine.textures.TerrainTexture;
 import eu.tankernn.gameEngine.textures.TerrainTexturePack;
 import eu.tankernn.gameEngine.util.MousePicker;
+import eu.tankernn.gameEngine.util.Sorter;
 import eu.tankernn.gameEngine.water.WaterFrameBuffers;
+import eu.tankernn.gameEngine.water.WaterMaster;
 import eu.tankernn.gameEngine.water.WaterRenderer;
 import eu.tankernn.gameEngine.water.WaterShader;
 import eu.tankernn.gameEngine.water.WaterTile;
@@ -72,8 +75,6 @@ public class MainLoop {
 //		AL10.alSourceQueueBuffers(source, buffer);
 //		AL10.alSourcePlay(source);
 		
-		
-		
 		// Monkey
 		ModelData monkeyData = OBJFileLoader.loadOBJ("character");
 		RawModel monkeyModel = loader.loadToVAO(monkeyData);
@@ -96,20 +97,21 @@ public class MainLoop {
 		
 		FontType font = new FontType(loader.loadTexture("arial"), "arial.fnt");
 		GUIText text = new GUIText("Sample text", 3, font, new Vector2f(0.5f, 0.5f), 0.5f, true);
-		text.setColour(1, 1, 1);
+		text.setColor(1, 1, 1);
 		
 		//Barrel
 		TexturedModel barrelModel = new TexturedModel(NormalMappedObjLoader.loadOBJ("barrel", loader), new ModelTexture(loader.loadTexture("barrel")));
 		barrelModel.getTexture().setNormalMap(loader.loadTexture("barrelNormal"));
 		barrelModel.getTexture().setShineDamper(10);
 		barrelModel.getTexture().setReflectivity(0.5f);
-		
-		normalMapEntities.add(new Entity(barrelModel, new Vector3f(75, 10, 75), 0, 0, 0, 1f));
+		Entity barrel = new Entity(barrelModel, new Vector3f(75, 10, 75), 0, 0, 0, 1f);
+		normalMapEntities.add(barrel);
 		
 		Light sun = new Light(new Vector3f(100000, 150000, -70000), new Vector3f(1, 1, 1));
-		List<Light> lights = new ArrayList<Light>(); //TODO Sort this list
+		Light flashLight = new Light(new Vector3f(0, 10, -10), new Vector3f(2, 0, 0), new Vector3f(1, 0.01f, 0.002f));
+		List<Light> lights = new ArrayList<Light>();
 		lights.add(sun);
-		lights.add(new Light(new Vector3f(0, 10, -10), new Vector3f(2, 0, 0), new Vector3f(1, 0.01f, 0.002f)));
+		lights.add(flashLight);
 		
 		// ### Terrain textures ###
 		
@@ -145,17 +147,14 @@ public class MainLoop {
 		MousePicker picker = new MousePicker(camera, renderer.getProjectionMatrix(), terrainPack, entities);
 		
 		// #### Water rendering ####
-		WaterFrameBuffers buffers = new WaterFrameBuffers();
-		WaterShader waterShader = new WaterShader();
-		WaterRenderer waterRenderer = new WaterRenderer(loader, waterShader, renderer.getProjectionMatrix(), buffers);
-		List<WaterTile> waterTiles = new ArrayList<WaterTile>();
+		WaterMaster waterMaster = new WaterMaster(loader, renderer);
 		WaterTile water = new WaterTile(75, 75, 0);
-		waterTiles.add(water);
+		waterMaster.addWaterTile(water);
 		
 		// #### Gui rendering ####
 		List<GuiTexture> guis = new ArrayList<GuiTexture>();
-		GuiTexture depth = new GuiTexture(buffers.getRefractionDepthTexture(), new Vector2f(0.5f, 0.5f), new Vector2f(0.25f, 0.25f));
-		GuiTexture refraction = new GuiTexture(renderer.getShadowMapTexture(), new Vector2f(-0.5f, 0.5f), new Vector2f(0.25f, 0.25f));
+		GuiTexture depth = new GuiTexture(waterMaster.getBuffers().getRefractionDepthTexture(), new Vector2f(0.5f, 0.5f), new Vector2f(0.25f, 0.25f));
+		GuiTexture refraction = new GuiTexture(waterMaster.getBuffers().getRefractionTexture(), new Vector2f(-0.5f, 0.5f), new Vector2f(0.25f, 0.25f));
 		guis.add(depth);
 		guis.add(refraction);
 		
@@ -165,14 +164,16 @@ public class MainLoop {
 		ParticleSystem ps = new ParticleSystem(particleTexture, 50, 10, 0.3f, 4);
 		
 		while (!Display.isCloseRequested()) {
-			entity.increaseRotation(0, 1, 0);
+			barrel.increaseRotation(0, 1, 0);
 			player.move(terrainPack);
 			camera.move();
 			picker.update();
 			
 			if (picker.getCurrentTerrainPoint() != null) {
-				lights.get(1).getPosition().x = picker.getCurrentTerrainPoint().x;
-				lights.get(1).getPosition().z = picker.getCurrentTerrainPoint().z;
+				Vector3f currentPoint = picker.getCurrentTerrainPoint();
+				flashLight.getPosition().x = currentPoint.x;
+				flashLight.getPosition().z = currentPoint.z;
+				flashLight.getPosition().y = terrainPack.getTerrainHeightByWorldPos(currentPoint.x, currentPoint.z) + 1.0f;
 			}
 			
 			// Update debug info
@@ -184,33 +185,20 @@ public class MainLoop {
 				String textString = "X: " + Math.floor(pos.x) + " Y: " + Math.floor(pos.y) + " Z: " + Math.floor(pos.z);
 				text = new GUIText(textString, 1, font, new Vector2f(0.5f, 0f), 0.5f, false);
 			}
+			
+			//Sort list of lights
+			lights = Sorter.sortByDistance(camera, lights);
+			
 			renderer.renderShadowMap(entities, sun);
 			
 			ps.generateParticles(player.getPosition());
 			ParticleMaster.update(camera);
 			
-			GL11.glEnable(GL30.GL_CLIP_DISTANCE0);
-			
-			// Reflection
-			buffers.bindReflectionFrameBuffer();
-			float distance = 2 * (camera.getPosition().y - water.getHeight());
-			camera.getPosition().y -= distance;
-			camera.invertPitch();
-			camera.invertRoll();
-			renderer.renderScene(entities, normalMapEntities, terrainPack, lights, camera, new Vector4f(0, 1, 0, -water.getHeight()));
-			camera.getPosition().y += distance;
-			camera.invertPitch();
-			camera.invertRoll();
-			
-			// Refraction
-			buffers.bindRefractionFrameBuffer();
-			renderer.renderScene(entities, normalMapEntities, terrainPack, lights, camera, new Vector4f(0, -1, 0, water.getHeight()));
+			Scene scene = new Scene(entities, normalMapEntities, terrainPack, lights, camera);
 			
-			// Screen
-			GL11.glDisable(GL30.GL_CLIP_DISTANCE0);
-			buffers.unbindCurrentFrameBuffer();
-			renderer.renderScene(entities, normalMapEntities, terrainPack, lights, camera, new Vector4f(0, 1, 0, Float.MAX_VALUE));
-			waterRenderer.render(waterTiles, camera, lights);
+			waterMaster.renderBuffers(renderer, scene);
+			renderer.renderScene(scene, new Vector4f(0, 1, 0, Float.MAX_VALUE));
+			waterMaster.renderWater(camera, lights);
 			ParticleMaster.renderParticles(camera);
 			guiRenderer.render(guis);
 			TextMaster.render();
@@ -220,8 +208,7 @@ public class MainLoop {
 		
 		ParticleMaster.cleanUp();
 		TextMaster.cleanUp();
-		buffers.cleanUp();
-		waterShader.cleanUp();
+		waterMaster.cleanUp();
 		guiRenderer.cleanUp();
 		renderer.cleanUp();
 		loader.cleanUp();

+ 11 - 0
src/main/java/eu/tankernn/gameEngine/util/Maths.java

@@ -8,6 +8,17 @@ import org.lwjgl.util.vector.Vector4f;
 import eu.tankernn.gameEngine.entities.Camera;
 
 public class Maths {
+	public static float distanceBetweenPoints(Vector3f pos1, Vector3f pos2) {
+		float baseWidth = pos1.x - pos2.x;
+		float baseDepth = pos1.z - pos2.z;
+		
+		float baseDiagonal = (float) Math.sqrt(Math.pow(baseWidth, 2) + Math.pow(baseDepth, 2));
+		
+		float cubeHeight = pos1.y - pos2.y;
+		float cubeDiagonal = (float) Math.sqrt(Math.pow(baseDiagonal, 2) + Math.pow(cubeHeight, 2));
+		return cubeDiagonal;
+	}
+	
 	public static Vector4f slerp(Vector4f qa, Vector4f qb, double time) {
 		// quaternion to return
 		Vector4f qm = new Vector4f();

+ 33 - 0
src/main/java/eu/tankernn/gameEngine/util/Sorter.java

@@ -0,0 +1,33 @@
+package eu.tankernn.gameEngine.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import eu.tankernn.gameEngine.entities.Positionable;
+
+public class Sorter {
+	public static <T extends Positionable> List<T> sortByDistance(Positionable centerPoint, List<T> objects) {
+		if (objects.size() < 2)
+			return objects;
+		
+		Map<T, Float> lengths = new HashMap<T, Float>();
+		for (T pos : objects)
+			lengths.put(pos, Maths.distanceBetweenPoints(centerPoint.getPosition(), pos.getPosition()));
+		
+		List<T> sortedList = new ArrayList<T>();
+		sortedList.addAll(objects);
+		
+		for (int j = 1; j < sortedList.size(); j++) {
+			for (int i = j; i < sortedList.size(); i++) {
+				if (lengths.get(sortedList.get(i)) < lengths.get(sortedList.get(i - 1))) {
+					T temp = sortedList.get(i);
+					sortedList.set(i, sortedList.get(i - 1));
+					sortedList.set(i - 1, temp);
+				}
+			}
+		}
+		return sortedList;
+	}
+}

+ 66 - 0
src/main/java/eu/tankernn/gameEngine/water/WaterMaster.java

@@ -0,0 +1,66 @@
+package eu.tankernn.gameEngine.water;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL30;
+import org.lwjgl.util.vector.Vector4f;
+
+import eu.tankernn.gameEngine.entities.Camera;
+import eu.tankernn.gameEngine.entities.Light;
+import eu.tankernn.gameEngine.renderEngine.Loader;
+import eu.tankernn.gameEngine.renderEngine.MasterRenderer;
+import eu.tankernn.gameEngine.renderEngine.Scene;
+
+public class WaterMaster {
+	private WaterFrameBuffers buffers = new WaterFrameBuffers();
+	private WaterShader waterShader = new WaterShader();
+	private List<WaterTile> waterTiles = new ArrayList<WaterTile>();
+	private WaterRenderer waterRenderer;
+	
+	public WaterMaster(Loader loader, MasterRenderer renderer) {
+		waterRenderer = new WaterRenderer(loader, waterShader, renderer.getProjectionMatrix(), buffers);
+	}
+	
+	public void addWaterTile(WaterTile water) {
+		waterTiles.add(water);
+	}
+	
+	public void renderBuffers(MasterRenderer renderer, Scene scene) {
+		float waterHeight = waterTiles.get(0).getHeight(); //TODO Using only the first watertile is BAD
+		GL11.glEnable(GL30.GL_CLIP_DISTANCE0);
+		
+		// Reflection
+		buffers.bindReflectionFrameBuffer();
+		float distance = 2 * (scene.getCamera().getPosition().y - waterHeight);
+		scene.getCamera().getPosition().y -= distance;
+		scene.getCamera().invertPitch();
+		scene.getCamera().invertRoll();
+		renderer.renderScene(scene, new Vector4f(0, 1, 0, -waterHeight));
+		scene.getCamera().getPosition().y += distance;
+		scene.getCamera().invertPitch();
+		scene.getCamera().invertRoll();
+		
+		// Refraction
+		buffers.bindRefractionFrameBuffer();
+		renderer.renderScene(scene, new Vector4f(0, -1, 0, waterHeight));
+		
+		// Screen
+		GL11.glDisable(GL30.GL_CLIP_DISTANCE0);
+		buffers.unbindCurrentFrameBuffer();
+	}
+	
+	public void renderWater(Camera camera, List<Light> lights) {
+		waterRenderer.render(waterTiles, camera, lights);
+	}
+	
+	public void cleanUp() {
+		buffers.cleanUp();
+		waterShader.cleanUp();
+	}
+
+	public WaterFrameBuffers getBuffers() {
+		return buffers;
+	}
+}

+ 6 - 8
src/main/java/eu/tankernn/gameEngine/water/WaterTile.java

@@ -5,26 +5,24 @@ public class WaterTile {
 	public static final float TILE_SIZE = 60;
 	
 	private float height;
-	private float x,z;
+	private float x, z;
 	
-	public WaterTile(float centerX, float centerZ, float height){
+	public WaterTile(float centerX, float centerZ, float height) {
 		this.x = centerX;
 		this.z = centerZ;
 		this.height = height;
 	}
-
+	
 	public float getHeight() {
 		return height;
 	}
-
+	
 	public float getX() {
 		return x;
 	}
-
+	
 	public float getZ() {
 		return z;
 	}
-
-
-
+	
 }