Forráskód Böngészése

Shader overhaul and cubemap rendering started

Tankernn 8 éve
szülő
commit
b58e1b31a2
71 módosított fájl, 1716 hozzáadás és 1199 törlés
  1. 1 0
      .gitignore
  2. 0 7
      .project
  3. 12 1
      TODO.txt
  4. 31 25
      pom.xml
  5. 29 19
      src/main/java/eu/tankernn/gameEngine/MainLoop.java
  6. 4 3
      src/main/java/eu/tankernn/gameEngine/TankernnGame.java
  7. 1 0
      src/main/java/eu/tankernn/gameEngine/animation/Bone.java
  8. 63 3
      src/main/java/eu/tankernn/gameEngine/entities/Camera.java
  9. 1 1
      src/main/java/eu/tankernn/gameEngine/entities/Player.java
  10. 3 0
      src/main/java/eu/tankernn/gameEngine/entities/PlayerCamera.java
  11. 108 0
      src/main/java/eu/tankernn/gameEngine/environmentMap/CubeMapCamera.java
  12. 39 0
      src/main/java/eu/tankernn/gameEngine/environmentMap/EnvironmentMapRenderer.java
  13. 2 2
      src/main/java/eu/tankernn/gameEngine/font/rendering/FontRenderer.java
  14. 6 26
      src/main/java/eu/tankernn/gameEngine/font/rendering/FontShader.java
  15. 1 1
      src/main/java/eu/tankernn/gameEngine/gui/GuiRenderer.java
  16. 4 18
      src/main/java/eu/tankernn/gameEngine/gui/GuiShader.java
  17. 14 13
      src/main/java/eu/tankernn/gameEngine/normalMapping/renderer/NormalMappingRenderer.java
  18. 54 101
      src/main/java/eu/tankernn/gameEngine/normalMapping/renderer/NormalMappingShader.java
  19. 3 3
      src/main/java/eu/tankernn/gameEngine/normalMapping/renderer/normalMapFShader.glsl
  20. 3 3
      src/main/java/eu/tankernn/gameEngine/particles/ParticleRenderer.java
  21. 7 27
      src/main/java/eu/tankernn/gameEngine/particles/ParticleShader.java
  22. 1 9
      src/main/java/eu/tankernn/gameEngine/postProcessing/ContrastShader.java
  23. 1 10
      src/main/java/eu/tankernn/gameEngine/postProcessing/bloom/BrightFilterShader.java
  24. 7 16
      src/main/java/eu/tankernn/gameEngine/postProcessing/bloom/CombineShader.java
  25. 1 1
      src/main/java/eu/tankernn/gameEngine/postProcessing/gaussianBlur/HorizontalBlur.java
  26. 6 18
      src/main/java/eu/tankernn/gameEngine/postProcessing/gaussianBlur/HorizontalBlurShader.java
  27. 1 1
      src/main/java/eu/tankernn/gameEngine/postProcessing/gaussianBlur/VerticalBlur.java
  28. 4 16
      src/main/java/eu/tankernn/gameEngine/postProcessing/gaussianBlur/VerticalBlurShader.java
  29. 2 2
      src/main/java/eu/tankernn/gameEngine/renderEngine/DisplayManager.java
  30. 0 102
      src/main/java/eu/tankernn/gameEngine/renderEngine/EntityRenderer.java
  31. 64 88
      src/main/java/eu/tankernn/gameEngine/renderEngine/MasterRenderer.java
  32. 20 1
      src/main/java/eu/tankernn/gameEngine/renderEngine/Scene.java
  33. 132 0
      src/main/java/eu/tankernn/gameEngine/renderEngine/Vao.java
  34. 58 0
      src/main/java/eu/tankernn/gameEngine/renderEngine/Vbo.java
  35. 126 0
      src/main/java/eu/tankernn/gameEngine/renderEngine/entities/EntityRenderer.java
  36. 50 0
      src/main/java/eu/tankernn/gameEngine/renderEngine/entities/EntityShader.java
  37. 2 2
      src/main/java/eu/tankernn/gameEngine/renderEngine/entities/fragmentShader.glsl
  38. 0 1
      src/main/java/eu/tankernn/gameEngine/renderEngine/entities/vertexShader.glsl
  39. 41 19
      src/main/java/eu/tankernn/gameEngine/renderEngine/terrain/TerrainRenderer.java
  40. 49 0
      src/main/java/eu/tankernn/gameEngine/renderEngine/terrain/TerrainShader.java
  41. 0 0
      src/main/java/eu/tankernn/gameEngine/renderEngine/terrain/terrainFragmentShader.glsl
  42. 0 0
      src/main/java/eu/tankernn/gameEngine/renderEngine/terrain/terrainVertexShader.glsl
  43. 76 78
      src/main/java/eu/tankernn/gameEngine/shaders/ShaderProgram.java
  44. 0 159
      src/main/java/eu/tankernn/gameEngine/shaders/StaticShader.java
  45. 0 140
      src/main/java/eu/tankernn/gameEngine/shaders/TerrainShader.java
  46. 35 0
      src/main/java/eu/tankernn/gameEngine/shaders/Uniform.java
  47. 21 0
      src/main/java/eu/tankernn/gameEngine/shaders/UniformBoolean.java
  48. 21 0
      src/main/java/eu/tankernn/gameEngine/shaders/UniformFloat.java
  49. 24 0
      src/main/java/eu/tankernn/gameEngine/shaders/UniformMatrix.java
  50. 21 0
      src/main/java/eu/tankernn/gameEngine/shaders/UniformSampler.java
  51. 28 0
      src/main/java/eu/tankernn/gameEngine/shaders/UniformVec2.java
  52. 29 0
      src/main/java/eu/tankernn/gameEngine/shaders/UniformVec3.java
  53. 21 0
      src/main/java/eu/tankernn/gameEngine/shaders/UniformVec4.java
  54. 15 0
      src/main/java/eu/tankernn/gameEngine/shaders/UniformViewMatrix.java
  55. 1 1
      src/main/java/eu/tankernn/gameEngine/shadows/ShadowMapEntityRenderer.java
  56. 4 20
      src/main/java/eu/tankernn/gameEngine/shadows/ShadowShader.java
  57. 23 0
      src/main/java/eu/tankernn/gameEngine/skybox/CubeGenerator.java
  58. 0 70
      src/main/java/eu/tankernn/gameEngine/skybox/CubeMap.java
  59. 34 0
      src/main/java/eu/tankernn/gameEngine/skybox/Skybox.java
  60. 27 30
      src/main/java/eu/tankernn/gameEngine/skybox/SkyboxRenderer.java
  61. 18 41
      src/main/java/eu/tankernn/gameEngine/skybox/SkyboxShader.java
  62. 50 0
      src/main/java/eu/tankernn/gameEngine/textures/Texture.java
  63. 64 0
      src/main/java/eu/tankernn/gameEngine/textures/TextureBuilder.java
  64. 24 24
      src/main/java/eu/tankernn/gameEngine/textures/TextureData.java
  65. 109 0
      src/main/java/eu/tankernn/gameEngine/textures/TextureUtils.java
  66. 14 0
      src/main/java/eu/tankernn/gameEngine/util/ICamera.java
  67. 2 2
      src/main/java/eu/tankernn/gameEngine/util/MousePicker.java
  68. 71 0
      src/main/java/eu/tankernn/gameEngine/util/MyFile.java
  69. 3 2
      src/main/java/eu/tankernn/gameEngine/water/WaterMaster.java
  70. 5 4
      src/main/java/eu/tankernn/gameEngine/water/WaterRenderer.java
  71. 25 89
      src/main/java/eu/tankernn/gameEngine/water/WaterShader.java

+ 1 - 0
.gitignore

@@ -1,2 +1,3 @@
 /bin/
 /target/
+/res/

+ 0 - 7
.project

@@ -20,11 +20,4 @@
 		<nature>org.eclipse.m2e.core.maven2Nature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
 	</natures>
-	<linkedResources>
-		<link>
-			<name>res</name>
-			<type>2</type>
-			<location>C:/Users/Frans/Documents/eclipse workspace/Tankernn 3D Game/res</location>
-		</link>
-	</linkedResources>
 </projectDescription>

+ 12 - 1
TODO.txt

@@ -1,2 +1,13 @@
 Make text variables uniform/ change text rendering method
-Fix player movement
+Fix player movement
+
+Useful regex-expressions:
+
+--------------------------------
+private int location_(.*);
+to
+protected UniformMatrix $1 = new UniformMatrix("$1");
+------------------------------------
+super.loadInt\(location_(.*), (.)\);
+to
+$1.loadTexUnit($2);

+ 31 - 25
pom.xml

@@ -33,35 +33,41 @@
 			<artifactId>pngdecoder</artifactId>
 			<version>1.0</version>
 		</dependency>
+		<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
+		<dependency>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>commons-lang3</artifactId>
+			<version>3.5</version>
+		</dependency>
 	</dependencies>
 
 	<build>
 		<finalName>${project.artifactId}-${project.version}.${build.number}</finalName>
-			<plugins>
-				<plugin>
-					<groupId>org.apache.maven.plugins</groupId>
-					<artifactId>maven-compiler-plugin</artifactId>
-					<version>3.5.1</version>
-					<configuration>
-						<source>1.8</source>
-						<target>1.8</target>
-					</configuration>
-				</plugin>
-				<plugin>
-					<groupId>com.googlecode.mavennatives</groupId>
-					<artifactId>maven-nativedependencies-plugin</artifactId>
-					<version>0.0.6</version>
-					<executions>
-						<execution>
-							<id>unpacknatives</id>
-							<phase>package</phase>
-							<goals>
-								<goal>copy</goal>
-							</goals>
-						</execution>
-					</executions>
-				</plugin>
-			</plugins>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>3.5.1</version>
+				<configuration>
+					<source>1.8</source>
+					<target>1.8</target>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>com.googlecode.mavennatives</groupId>
+				<artifactId>maven-nativedependencies-plugin</artifactId>
+				<version>0.0.6</version>
+				<executions>
+					<execution>
+						<id>unpacknatives</id>
+						<phase>package</phase>
+						<goals>
+							<goal>copy</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
 
 		<resources>
 			<resource>

+ 29 - 19
src/main/java/eu/tankernn/gameEngine/MainLoop.java

@@ -1,10 +1,7 @@
 package eu.tankernn.gameEngine;
 
 import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.URL;
 import java.util.ArrayList;
-import java.util.Enumeration;
 import java.util.List;
 import java.util.Random;
 
@@ -20,6 +17,7 @@ import eu.tankernn.gameEngine.entities.Entity;
 import eu.tankernn.gameEngine.entities.Light;
 import eu.tankernn.gameEngine.entities.Player;
 import eu.tankernn.gameEngine.entities.PlayerCamera;
+import eu.tankernn.gameEngine.environmentMap.EnvironmentMapRenderer;
 import eu.tankernn.gameEngine.font.meshCreator.FontType;
 import eu.tankernn.gameEngine.font.meshCreator.GUIText;
 import eu.tankernn.gameEngine.font.rendering.TextMaster;
@@ -40,13 +38,16 @@ 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.skybox.Skybox;
 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.textures.Texture;
 import eu.tankernn.gameEngine.util.DistanceSorter;
 import eu.tankernn.gameEngine.util.MousePicker;
+import eu.tankernn.gameEngine.util.MyFile;
 import eu.tankernn.gameEngine.water.WaterMaster;
 import eu.tankernn.gameEngine.water.WaterTile;
 
@@ -73,14 +74,6 @@ public class MainLoop {
 		DisplayManager.createDisplay("Tankernn Game Engine tester");
 		Loader loader = new Loader();
 		
-		try {
-			Enumeration<URL> urls = MainLoop.class.getClassLoader().getResources("");
-			while (urls.hasMoreElements())
-				System.out.println(urls.nextElement().toString());
-		} catch (IOException e) {
-			e.printStackTrace();
-		}
-		
 		// Monkey
 		ModelData monkeyData = OBJFileLoader.loadOBJ("character");
 		RawModel monkeyModel = loader.loadToVAO(monkeyData);
@@ -97,9 +90,18 @@ public class MainLoop {
 		Player player = new Player(monkey, new Vector3f(10, 0, 50), 0, 0, 0, 1, terrainPack);
 		entities.add(player);
 		Camera camera = new PlayerCamera(player, terrainPack);
-
-		MasterRenderer renderer = new MasterRenderer(loader, camera, TEXTURE_FILES, NIGHT_TEXTURE_FILES);
-		ParticleMaster.init(loader, renderer.getProjectionMatrix());
+		
+		MyFile[] dayTextures = new MyFile[TEXTURE_FILES.length], nightTextures = new MyFile[NIGHT_TEXTURE_FILES.length];
+		
+		for (int i = 0; i < TEXTURE_FILES.length; i++)
+			dayTextures[i] = new MyFile("skybox/" + TEXTURE_FILES[i] + ".png");
+		for (int i = 0; i < NIGHT_TEXTURE_FILES.length; i++)
+			nightTextures[i] = new MyFile("skybox/" + NIGHT_TEXTURE_FILES[i] + ".png");
+		
+		Skybox skybox = new Skybox(Texture.newCubeMap(dayTextures, 500), Texture.newCubeMap(nightTextures, 500), 500);
+		
+		MasterRenderer renderer = new MasterRenderer(loader, camera, skybox);
+		ParticleMaster.init(loader, camera.getProjectionMatrix());
 		TextMaster.init(loader);
 
 		FontType font = new FontType(loader.loadTexture("arial"), "arial.fnt");
@@ -162,12 +164,16 @@ public class MainLoop {
 		}
 
 		// #### Water rendering ####
-		WaterMaster waterMaster = new WaterMaster(loader, DUDV_MAP, NORMAL_MAP, renderer);
+		WaterMaster waterMaster = new WaterMaster(loader, DUDV_MAP, NORMAL_MAP, camera);
 		WaterTile water = new WaterTile(75, 75, 0);
 		waterMaster.addWaterTile(water);
 
 		// #### Gui rendering ####
 		List<GuiTexture> guis = new ArrayList<GuiTexture>();
+		
+		GuiTexture debug = new GuiTexture(0, new Vector2f(1, 1), new Vector2f(1, 1));
+		
+		guis.add(debug);
 
 		GuiRenderer guiRenderer = new GuiRenderer(loader);
 
@@ -181,8 +187,8 @@ public class MainLoop {
 
 		PostProcessing.init(loader);
 
-		MousePicker picker = new MousePicker(camera, renderer.getProjectionMatrix(), terrainPack, entities, guis);
-
+		MousePicker picker = new MousePicker(camera, camera.getProjectionMatrix(), terrainPack, entities, guis);
+		
 		while (!Display.isCloseRequested()) {
 			barrel.increaseRotation(0, 1, 0);
 			player.move(terrainPack);
@@ -225,8 +231,12 @@ public class MainLoop {
 			ps.generateParticles(player.getPosition());
 			ParticleMaster.update(camera);
 
-			Scene scene = new Scene(entities, normalMapEntities, terrainPack, lights, camera);
-
+			Scene scene = new Scene(entities, normalMapEntities, terrainPack, lights, camera, skybox);
+			
+			EnvironmentMapRenderer.renderEnvironmentMap(scene.getEnvironmentMap(), scene, player.getPosition(), renderer);
+			
+			debug = new GuiTexture(scene.getEnvironmentMap().textureId, new Vector2f(1, 1), new Vector2f(1, 1));
+			
 			waterMaster.renderBuffers(renderer, scene);
 
 			multisampleFbo.bindFrameBuffer();

+ 4 - 3
src/main/java/eu/tankernn/gameEngine/TankernnGame.java

@@ -4,6 +4,7 @@ import eu.tankernn.gameEngine.entities.Camera;
 import eu.tankernn.gameEngine.renderEngine.DisplayManager;
 import eu.tankernn.gameEngine.renderEngine.Loader;
 import eu.tankernn.gameEngine.renderEngine.MasterRenderer;
+import eu.tankernn.gameEngine.skybox.Skybox;
 import eu.tankernn.gameEngine.water.WaterMaster;
 
 public class TankernnGame {
@@ -12,11 +13,11 @@ public class TankernnGame {
 	protected WaterMaster waterMaster;
 	protected Camera camera;
 	
-	public TankernnGame(String[] dayTextureFiles, String[] nightTextureFiles, String dudvMap, String normalMap) {
+	public TankernnGame(Skybox skybox, String dudvMap, String normalMap) {
 		loader = new Loader();
 		camera = new Camera();
-		renderer = new MasterRenderer(loader, camera, dayTextureFiles, nightTextureFiles);
-		waterMaster = new WaterMaster(loader, dudvMap, normalMap, renderer);
+		renderer = new MasterRenderer(loader, camera, skybox);
+		waterMaster = new WaterMaster(loader, dudvMap, normalMap, camera);
 	}
 	
 	public void update() {

+ 1 - 0
src/main/java/eu/tankernn/gameEngine/animation/Bone.java

@@ -6,6 +6,7 @@ import java.io.FileReader;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+
 import org.lwjgl.util.vector.Vector3f;
 import org.lwjgl.util.vector.Vector4f;
 

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

@@ -1,13 +1,25 @@
 package eu.tankernn.gameEngine.entities;
 
+import static eu.tankernn.gameEngine.settings.Settings.FAR_PLANE;
+import static eu.tankernn.gameEngine.settings.Settings.FOV;
+import static eu.tankernn.gameEngine.settings.Settings.NEAR_PLANE;
+
+import org.lwjgl.opengl.Display;
+import org.lwjgl.util.vector.Matrix4f;
 import org.lwjgl.util.vector.Vector3f;
 
+import eu.tankernn.gameEngine.util.ICamera;
+import eu.tankernn.gameEngine.util.Maths;
+
 /**
  * Camera for determining the view frustum when rendering.
  * 
  * @author Frans
  */
-public class Camera implements Positionable {
+public class Camera implements Positionable, ICamera {
+	
+	private Matrix4f projectionMatrix;
+	private Matrix4f viewMatrix = new Matrix4f();
 	
 	protected Vector3f position = new Vector3f(0, 10, 0);
 	protected float pitch = 20;
@@ -15,11 +27,12 @@ public class Camera implements Positionable {
 	protected float roll;
 	
 	public Camera(Vector3f position) {
+		this();
 		this.position = position;
 	}
 	
 	public Camera() {
-		
+		this.projectionMatrix = createProjectionMatrix();
 	}
 	
 	/**
@@ -40,7 +53,7 @@ public class Camera implements Positionable {
 	}
 	
 	public void update() {
-		
+		updateViewMatrix();
 	}
 	
 	public Vector3f getPosition() {
@@ -73,4 +86,51 @@ public class Camera implements Positionable {
 		this.roll = -roll;
 	}
 	
+	private void updateViewMatrix() {
+		viewMatrix.setIdentity();
+		Matrix4f.rotate((float) Math.toRadians(pitch), new Vector3f(1, 0, 0), viewMatrix,
+				viewMatrix);
+		Matrix4f.rotate((float) Math.toRadians(yaw), new Vector3f(0, 1, 0), viewMatrix, viewMatrix);
+		Vector3f negativeCameraPos = new Vector3f(-position.x,-position.y,-position.z);
+		Matrix4f.translate(negativeCameraPos, viewMatrix, viewMatrix);
+	}
+	
+	private static Matrix4f createProjectionMatrix(){
+		Matrix4f projectionMatrix = new Matrix4f();
+		float aspectRatio = (float) Display.getWidth() / (float) Display.getHeight();
+		float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))));
+		float x_scale = y_scale / aspectRatio;
+		float frustum_length = FAR_PLANE - NEAR_PLANE;
+	
+		projectionMatrix.m00 = x_scale;
+		projectionMatrix.m11 = y_scale;
+		projectionMatrix.m22 = -((FAR_PLANE + NEAR_PLANE) / frustum_length);
+		projectionMatrix.m23 = -1;
+		projectionMatrix.m32 = -((2 * NEAR_PLANE * FAR_PLANE) / frustum_length);
+		projectionMatrix.m33 = 0;
+		return projectionMatrix;
+	}
+
+	@Override
+	public Matrix4f getViewMatrix() {
+		return Maths.createViewMatrix(this);
+	}
+	
+	@Override
+	public void reflect(float height){
+		this.pitch = -pitch;
+		this.position.y = position.y - 2 * (position.y - height);
+		updateViewMatrix();
+	}
+
+	@Override
+	public Matrix4f getProjectionMatrix() {
+		return projectionMatrix;
+	}
+
+	@Override
+	public Matrix4f getProjectionViewMatrix() {
+		return Matrix4f.mul(projectionMatrix, viewMatrix, null);
+	}
+	
 }

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

@@ -6,9 +6,9 @@ import org.lwjgl.util.vector.Vector3f;
 
 import eu.tankernn.gameEngine.models.TexturedModel;
 import eu.tankernn.gameEngine.renderEngine.DisplayManager;
+import eu.tankernn.gameEngine.settings.Physics;
 import eu.tankernn.gameEngine.terrains.Terrain;
 import eu.tankernn.gameEngine.terrains.TerrainPack;
-import eu.tankernn.gameEngine.settings.Physics;
 
 public class Player extends Entity {
 	

+ 3 - 0
src/main/java/eu/tankernn/gameEngine/entities/PlayerCamera.java

@@ -20,6 +20,7 @@ public class PlayerCamera extends Camera {
 	private TerrainPack terrainPack;
 	
 	public PlayerCamera(Player player, TerrainPack terrainPack) {
+		super();
 		this.player = player;
 		this.terrainPack = terrainPack;
 	}
@@ -65,6 +66,8 @@ public class PlayerCamera extends Camera {
 			this.yaw = 180 - (lockedPosition + angleAroundPlayer);
 		} else
 			this.yaw = 180 - (player.getRotY() + angleAroundPlayer);
+		
+		super.update();
 	}
 	
 	private void adjustToCenter() {

+ 108 - 0
src/main/java/eu/tankernn/gameEngine/environmentMap/CubeMapCamera.java

@@ -0,0 +1,108 @@
+package eu.tankernn.gameEngine.environmentMap;
+
+import org.lwjgl.util.vector.Matrix4f;
+import org.lwjgl.util.vector.Vector3f;
+
+import eu.tankernn.gameEngine.util.ICamera;
+
+
+public class CubeMapCamera implements ICamera {
+
+	private static final float NEAR_PLANE = 0.1f;
+	private static final float FAR_PLANE = 200f;
+	private static final float FOV = 90;// don't change!
+	private static final float ASPECT_RATIO = 1;
+
+	private final Vector3f center;
+	private float pitch = 0;
+	private float yaw = 0;
+
+	private Matrix4f projectionMatrix = new Matrix4f();
+	private Matrix4f viewMatrix = new Matrix4f();
+	private Matrix4f projectionViewMatrix = new Matrix4f();
+
+	public CubeMapCamera(Vector3f center) {
+		this.center = center;
+		createProjectionMatrix();
+	}
+
+	public void switchToFace(int faceIndex) {
+		switch (faceIndex) {
+		case 0:
+			pitch = 0;
+			yaw = 90;
+			break;
+		case 1:
+			pitch = 0;
+			yaw = -90;
+			break;
+		case 2:
+			pitch = -90;
+			yaw = 180;
+			break;
+		case 3:
+			pitch = 90;
+			yaw = 180;
+			break;
+		case 4:
+			pitch = 0;
+			yaw = 180;
+			break;
+		case 5:
+			pitch = 0;
+			yaw = 0;
+			break;
+		}
+		updateViewMatrix();
+	}
+
+	@Override
+	public Vector3f getPosition() {
+		return center;
+	}
+
+	@Override
+	public Matrix4f getViewMatrix() {
+		return viewMatrix;
+	}
+
+	@Override
+	public void reflect(float height) {
+
+	}
+
+	@Override
+	public Matrix4f getProjectionMatrix() {
+		return projectionMatrix;
+	}
+
+	@Override
+	public Matrix4f getProjectionViewMatrix() {
+		return projectionViewMatrix;
+	}
+
+	private void createProjectionMatrix() {
+		float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))));
+		float x_scale = y_scale / ASPECT_RATIO;
+		float frustum_length = FAR_PLANE - NEAR_PLANE;
+
+		projectionMatrix.m00 = x_scale;
+		projectionMatrix.m11 = y_scale;
+		projectionMatrix.m22 = -((FAR_PLANE + NEAR_PLANE) / frustum_length);
+		projectionMatrix.m23 = -1;
+		projectionMatrix.m32 = -((2 * NEAR_PLANE * FAR_PLANE) / frustum_length);
+		projectionMatrix.m33 = 0;
+	}
+
+	private void updateViewMatrix() {
+		viewMatrix.setIdentity();
+		Matrix4f.rotate((float) Math.toRadians(180), new Vector3f(0, 0, 1), viewMatrix, viewMatrix);
+		Matrix4f.rotate((float) Math.toRadians(pitch), new Vector3f(1, 0, 0), viewMatrix, viewMatrix);
+		Matrix4f.rotate((float) Math.toRadians(yaw), new Vector3f(0, 1, 0), viewMatrix, viewMatrix);
+		Vector3f negativeCameraPos = new Vector3f(-center.x, -center.y, -center.z);
+		Matrix4f.translate(negativeCameraPos, viewMatrix, viewMatrix);
+
+		Matrix4f.mul(projectionMatrix, viewMatrix, projectionViewMatrix);
+	}
+
+}

+ 39 - 0
src/main/java/eu/tankernn/gameEngine/environmentMap/EnvironmentMapRenderer.java

@@ -0,0 +1,39 @@
+package eu.tankernn.gameEngine.environmentMap;
+
+import org.lwjgl.opengl.Display;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL13;
+import org.lwjgl.opengl.GL14;
+import org.lwjgl.opengl.GL30;
+import org.lwjgl.util.vector.Vector3f;
+
+import eu.tankernn.gameEngine.renderEngine.MasterRenderer;
+import eu.tankernn.gameEngine.renderEngine.Scene;
+import eu.tankernn.gameEngine.textures.Texture;
+
+public class EnvironmentMapRenderer {
+	public static void renderEnvironmentMap(Texture cubeMap, Scene scene, Vector3f center, MasterRenderer renderer) {
+		CubeMapCamera camera = new CubeMapCamera(center);
+		
+		int fbo = GL30.glGenFramebuffers();
+		GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, fbo);
+		GL11.glDrawBuffer(GL30.GL_COLOR_ATTACHMENT0);
+		
+		int depthBuffer = GL30.glGenRenderbuffers();
+		GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBuffer);
+		GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL14.GL_DEPTH_COMPONENT24, cubeMap.size, cubeMap.size);
+		GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL30.GL_RENDERBUFFER, depthBuffer);
+		GL11.glViewport(0, 0, cubeMap.size, cubeMap.size);
+		
+		for (int i = 0; i < 6; i++) {
+			GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubeMap.textureId, 0);
+			
+			camera.switchToFace(i);
+			
+			renderer.renderLowQualityScene(scene, camera);
+		}
+		
+		GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
+		GL11.glViewport(0, 0, Display.getWidth(), Display.getHeight());
+	}
+}

+ 2 - 2
src/main/java/eu/tankernn/gameEngine/font/rendering/FontRenderer.java

@@ -46,8 +46,8 @@ public class FontRenderer {
 		GL30.glBindVertexArray(text.getMesh());
 		GL20.glEnableVertexAttribArray(0);
 		GL20.glEnableVertexAttribArray(1);
-		shader.loadColor(text.getColor());
-		shader.loadTranslation(text.getPosition());
+		shader.color.loadVec3(text.getColor());
+		shader.translation.loadVec2(text.getPosition());
 		GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, text.getVertexCount());
 		GL20.glDisableVertexAttribArray(0);
 		GL20.glDisableVertexAttribArray(1);

+ 6 - 26
src/main/java/eu/tankernn/gameEngine/font/rendering/FontShader.java

@@ -1,40 +1,20 @@
 package eu.tankernn.gameEngine.font.rendering;
 
-import org.lwjgl.util.vector.Vector2f;
-import org.lwjgl.util.vector.Vector3f;
-
 import eu.tankernn.gameEngine.shaders.ShaderProgram;
+import eu.tankernn.gameEngine.shaders.UniformVec2;
+import eu.tankernn.gameEngine.shaders.UniformVec3;
 
 public class FontShader extends ShaderProgram{
 
 	private static final String VERTEX_FILE = "/eu/tankernn/gameEngine/font/rendering/fontVertex.glsl";
 	private static final String FRAGMENT_FILE = "/eu/tankernn/gameEngine/font/rendering/fontFragment.glsl";
 	
-	private int location_color;
-	private int location_translation;
+	protected UniformVec3 color = new UniformVec3("color");
+	protected UniformVec2 translation = new UniformVec2("translation");
 	
 	public FontShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
-	}
-
-	@Override
-	protected void getAllUniformLocations() {
-		location_color = super.getUniformLocation("color");
-		location_translation = super.getUniformLocation("translation");
-	}
-
-	@Override
-	protected void bindAttributes() {
-		super.bindAttribute(0, "position");
-		super.bindAttribute(1, "textureCoords");
-	}
-	
-	protected void loadColor(Vector3f color) {
-		super.loadVector(location_color, color);
-	}
-	
-	protected void loadTranslation(Vector2f translation) {
-		super.load2DVector(location_translation, translation);
+		super(VERTEX_FILE, FRAGMENT_FILE, "position", "textureCoords");
+		super.storeAllUniformLocations(color, translation);
 	}
 	
 }

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/gui/GuiRenderer.java

@@ -34,7 +34,7 @@ public class GuiRenderer {
 			GL13.glActiveTexture(GL13.GL_TEXTURE0);
 			GL11.glBindTexture(GL11.GL_TEXTURE_2D, gui.getTexture());
 			Matrix4f matrix = Maths.createTransformationMatrix(gui.getPosition(), gui.getScale());
-			shader.loadTransformation(matrix);
+			shader.transformationMatrix.loadMatrix(matrix);
 			GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, quad.getVertexCount());
 		}
 		GL11.glEnable(GL11.GL_DEPTH_TEST);

+ 4 - 18
src/main/java/eu/tankernn/gameEngine/gui/GuiShader.java

@@ -1,31 +1,17 @@
 package eu.tankernn.gameEngine.gui;
 
-import org.lwjgl.util.vector.Matrix4f;
-
 import eu.tankernn.gameEngine.shaders.ShaderProgram;
+import eu.tankernn.gameEngine.shaders.UniformMatrix;
 
 public class GuiShader extends ShaderProgram {
 	private static final String VERTEX_FILE = "/eu/tankernn/gameEngine/gui/guiVertexShader.glsl";
 	private static final String FRAGMENT_FILE = "/eu/tankernn/gameEngine/gui/guiFragmentShader.glsl";
 	
-	private int location_transformationMatrix;
+	protected UniformMatrix transformationMatrix = new UniformMatrix("transformationMatrix");
 	
 	public GuiShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
-	}
-	
-	public void loadTransformation(Matrix4f matrix) {
-		super.loadMatrix(location_transformationMatrix, matrix);
-	}
-	
-	@Override
-	protected void getAllUniformLocations() {
-		location_transformationMatrix = super.getUniformLocation("transformationMatrix");
-	}
-	
-	@Override
-	protected void bindAttributes() {
-		super.bindAttribute(0, "position");
+		super(VERTEX_FILE, FRAGMENT_FILE, "position");
+		super.storeAllUniformLocations(transformationMatrix);
 	}
 	
 }

+ 14 - 13
src/main/java/eu/tankernn/gameEngine/normalMapping/renderer/NormalMappingRenderer.java

@@ -10,7 +10,6 @@ import org.lwjgl.opengl.GL30;
 import org.lwjgl.util.vector.Matrix4f;
 import org.lwjgl.util.vector.Vector4f;
 
-import eu.tankernn.gameEngine.entities.Camera;
 import eu.tankernn.gameEngine.entities.Entity;
 import eu.tankernn.gameEngine.entities.Light;
 import eu.tankernn.gameEngine.models.RawModel;
@@ -18,6 +17,7 @@ import eu.tankernn.gameEngine.models.TexturedModel;
 import eu.tankernn.gameEngine.renderEngine.MasterRenderer;
 import eu.tankernn.gameEngine.settings.Settings;
 import eu.tankernn.gameEngine.textures.ModelTexture;
+import eu.tankernn.gameEngine.util.ICamera;
 import eu.tankernn.gameEngine.util.Maths;
 
 public class NormalMappingRenderer {
@@ -27,12 +27,12 @@ public class NormalMappingRenderer {
 	public NormalMappingRenderer(Matrix4f projectionMatrix) {
 		this.shader = new NormalMappingShader();
 		shader.start();
-		shader.loadProjectionMatrix(projectionMatrix);
+		shader.projectionMatrix.loadMatrix(projectionMatrix);
 		shader.connectTextureUnits();
 		shader.stop();
 	}
 
-	public void render(Map<TexturedModel, List<Entity>> entities, Vector4f clipPlane, List<Light> lights, Camera camera) {
+	public void render(Map<TexturedModel, List<Entity>> entities, Vector4f clipPlane, List<Light> lights, ICamera camera) {
 		shader.start();
 		prepare(clipPlane, lights, camera);
 		for (TexturedModel model : entities.keySet()) {
@@ -59,16 +59,17 @@ public class NormalMappingRenderer {
 		GL20.glEnableVertexAttribArray(2);
 		GL20.glEnableVertexAttribArray(3);
 		ModelTexture texture = model.getTexture();
-		shader.loadNumberOfRows(texture.getNumberOfRows());
+		shader.numberOfRows.loadFloat(texture.getNumberOfRows());
 		if (texture.hasTransparency()) {
 			MasterRenderer.disableCulling();
 		}
-		shader.loadShineVariables(texture.getShineDamper(), texture.getReflectivity());
+		shader.shineDamper.loadFloat(texture.getShineDamper());
+		shader.reflectivity.loadFloat(texture.getReflectivity());
 		GL13.glActiveTexture(GL13.GL_TEXTURE0);
 		GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getTexture().getID());
 		GL13.glActiveTexture(GL13.GL_TEXTURE1);
 		GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getTexture().getNormalMap());
-		shader.loadUseSpecularMap(texture.hasSpecularMap());
+		shader.usesSpecularMap.loadBoolean(texture.hasSpecularMap());
 		if (texture.hasSpecularMap()) {
 			GL13.glActiveTexture(GL13.GL_TEXTURE2);
 			GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture.getSpecularMap());
@@ -87,18 +88,18 @@ public class NormalMappingRenderer {
 	private void prepareInstance(Entity entity) {
 		Matrix4f transformationMatrix = Maths.createTransformationMatrix(entity.getPosition(), entity.getRotX(),
 				entity.getRotY(), entity.getRotZ(), entity.getScale());
-		shader.loadTransformationMatrix(transformationMatrix);
-		shader.loadOffset(entity.getTextureXOffset(), entity.getTextureYOffset());
+		shader.transformationMatrix.loadMatrix(transformationMatrix);
+		shader.offset.loadVec2(entity.getTextureXOffset(), entity.getTextureYOffset());
 	}
 
-	private void prepare(Vector4f clipPlane, List<Light> lights, Camera camera) {
-		shader.loadClipPlane(clipPlane);
+	private void prepare(Vector4f clipPlane, List<Light> lights, ICamera camera) {
+		shader.plane.loadVec4(clipPlane);
 		//need to be public variables in MasterRenderer
-		shader.loadSkyColour(Settings.RED, Settings.GREEN, Settings.BLUE);
-		Matrix4f viewMatrix = Maths.createViewMatrix(camera);
+		shader.skyColour.loadVec3(Settings.RED, Settings.GREEN, Settings.BLUE);
+		Matrix4f viewMatrix = camera.getViewMatrix();
 		
 		shader.loadLights(lights, viewMatrix);
-		shader.loadViewMatrix(viewMatrix);
+		shader.viewMatrix.loadMatrix(viewMatrix);
 	}
 
 }

+ 54 - 101
src/main/java/eu/tankernn/gameEngine/normalMapping/renderer/NormalMappingShader.java

@@ -3,137 +3,90 @@ package eu.tankernn.gameEngine.normalMapping.renderer;
 import java.util.List;
 
 import org.lwjgl.util.vector.Matrix4f;
-import org.lwjgl.util.vector.Vector2f;
 import org.lwjgl.util.vector.Vector3f;
 import org.lwjgl.util.vector.Vector4f;
 
 import eu.tankernn.gameEngine.entities.Light;
 import eu.tankernn.gameEngine.shaders.ShaderProgram;
+import eu.tankernn.gameEngine.shaders.UniformBoolean;
+import eu.tankernn.gameEngine.shaders.UniformFloat;
+import eu.tankernn.gameEngine.shaders.UniformMatrix;
+import eu.tankernn.gameEngine.shaders.UniformSampler;
+import eu.tankernn.gameEngine.shaders.UniformVec2;
+import eu.tankernn.gameEngine.shaders.UniformVec3;
+import eu.tankernn.gameEngine.shaders.UniformVec4;
 
 public class NormalMappingShader extends ShaderProgram {
-	
-	private static final int MAX_LIGHTS = 4;
-	
+
 	private static final String VERTEX_FILE = "/eu/tankernn/gameEngine/normalMapping/renderer/normalMapVShader.glsl";
 	private static final String FRAGMENT_FILE = "/eu/tankernn/gameEngine/normalMapping/renderer/normalMapFShader.glsl";
-	
-	private int location_transformationMatrix;
-	private int location_projectionMatrix;
-	private int location_viewMatrix;
-	private int location_lightPositionEyeSpace[];
-	private int location_lightColour[];
-	private int location_attenuation[];
-	private int location_shineDamper;
-	private int location_reflectivity;
-	private int location_skyColour;
-	private int location_numberOfRows;
-	private int location_offset;
-	private int location_plane;
-	private int location_modelTexture;
-	private int location_normalMap;
-	private int location_specularMap;
-	private int location_usesSpecularMap;
-	
+
+	protected UniformMatrix transformationMatrix = new UniformMatrix("transformationMatrix");
+	protected UniformMatrix projectionMatrix = new UniformMatrix("projectionMatrix");
+	protected UniformMatrix viewMatrix = new UniformMatrix("viewMatrix");
+	private UniformVec3[] lightPositionEyeSpace;
+	protected UniformFloat shineDamper = new UniformFloat("shineDamper");
+	protected UniformFloat reflectivity = new UniformFloat("reflectivity");
+	protected UniformVec3 skyColour = new UniformVec3("skyColour");
+	protected UniformFloat numberOfRows = new UniformFloat("numberOfRows");
+	protected UniformVec2 offset = new UniformVec2("offset");
+	protected UniformVec4 plane = new UniformVec4("plane");
+	protected UniformSampler modelTexture = new UniformSampler("modelTexture");
+	protected UniformSampler normalMap = new UniformSampler("normalMap");
+	protected UniformSampler specularMap = new UniformSampler("specularMap");
+	protected UniformBoolean usesSpecularMap = new UniformBoolean("usesSpecularMap");
+
 	public NormalMappingShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
-	}
-	
-	@Override
-	protected void bindAttributes() {
-		super.bindAttribute(0, "position");
-		super.bindAttribute(1, "textureCoordinates");
-		super.bindAttribute(2, "normal");
-		super.bindAttribute(3, "tangent");
+		super(VERTEX_FILE, FRAGMENT_FILE, "position", "textureCoordinates", "normal", "tangent");
+		this.getLightUniformLocations();
+		super.storeAllUniformLocations(transformationMatrix, projectionMatrix, viewMatrix, viewMatrix, shineDamper,
+				reflectivity, skyColour, numberOfRows, offset, plane, modelTexture, normalMap, specularMap,
+				usesSpecularMap);
+		super.storeAllUniformLocations(lightPositionEyeSpace);
 	}
 	
 	@Override
-	protected void getAllUniformLocations() {
-		location_transformationMatrix = super.getUniformLocation("transformationMatrix");
-		location_projectionMatrix = super.getUniformLocation("projectionMatrix");
-		location_viewMatrix = super.getUniformLocation("viewMatrix");
-		location_shineDamper = super.getUniformLocation("shineDamper");
-		location_reflectivity = super.getUniformLocation("reflectivity");
-		location_skyColour = super.getUniformLocation("skyColour");
-		location_numberOfRows = super.getUniformLocation("numberOfRows");
-		location_offset = super.getUniformLocation("offset");
-		location_plane = super.getUniformLocation("plane");
-		location_modelTexture = super.getUniformLocation("modelTexture");
-		location_normalMap = super.getUniformLocation("normalMap");
-		location_specularMap = super.getUniformLocation("specularMap");
-		location_usesSpecularMap = super.getUniformLocation("usesSpecularMap");
-		
-		location_lightPositionEyeSpace = new int[MAX_LIGHTS];
-		location_lightColour = new int[MAX_LIGHTS];
-		location_attenuation = new int[MAX_LIGHTS];
+	protected void getLightUniformLocations() {
+		lightPositionEyeSpace = new UniformVec3[MAX_LIGHTS];
+		lightColor = new UniformVec3[MAX_LIGHTS];
+		attenuation = new UniformVec3[MAX_LIGHTS];
 		for (int i = 0; i < MAX_LIGHTS; i++) {
-			location_lightPositionEyeSpace[i] = super.getUniformLocation("lightPositionEyeSpace[" + i + "]");
-			location_lightColour[i] = super.getUniformLocation("lightColour[" + i + "]");
-			location_attenuation[i] = super.getUniformLocation("attenuation[" + i + "]");
+			lightPositionEyeSpace[i] = new UniformVec3("lightPositionEyeSpace[" + i + "]");
+			lightColor[i] = new UniformVec3("lightColor[" + i + "]");
+			attenuation[i] = new UniformVec3("attenuation[" + i + "]");
 		}
 	}
 	
-	protected void connectTextureUnits() {
-		super.loadInt(location_modelTexture, 0);
-		super.loadInt(location_normalMap, 1);
-		super.loadInt(location_specularMap, 2);
-	}
-	
-	public void loadUseSpecularMap(boolean useSpecularMap) {
-		super.loadBoolean(location_usesSpecularMap, useSpecularMap);
-	}
-	
-	protected void loadClipPlane(Vector4f plane) {
-		super.loadVector(location_plane, plane);
-	}
-	
-	protected void loadNumberOfRows(int numberOfRows) {
-		super.loadFloat(location_numberOfRows, numberOfRows);
-	}
-	
-	protected void loadOffset(float x, float y) {
-		super.load2DVector(location_offset, new Vector2f(x, y));
-	}
-	
-	protected void loadSkyColour(float r, float g, float b) {
-		super.loadVector(location_skyColour, new Vector3f(r, g, b));
-	}
-	
-	protected void loadShineVariables(float damper, float reflectivity) {
-		super.loadFloat(location_shineDamper, damper);
-		super.loadFloat(location_reflectivity, reflectivity);
-	}
-	
-	protected void loadTransformationMatrix(Matrix4f matrix) {
-		super.loadMatrix(location_transformationMatrix, matrix);
-	}
-	
-	protected void loadLights(List<Light> lights, Matrix4f viewMatrix) {
+	public void loadLights(List<Light> lights, Matrix4f viewMatrix) {
 		for (int i = 0; i < MAX_LIGHTS; i++) {
 			if (i < lights.size()) {
-				super.loadVector(location_lightPositionEyeSpace[i], getEyeSpacePosition(lights.get(i), viewMatrix));
-				super.loadVector(location_lightColour[i], lights.get(i).getColor());
-				super.loadVector(location_attenuation[i], lights.get(i).getAttenuation());
+				lightPositionEyeSpace[i].loadVec3(getEyeSpacePosition(lights.get(i), viewMatrix));
+				lightColor[i].loadVec3(lights.get(i).getColor());
+				attenuation[i].loadVec3(lights.get(i).getAttenuation());
 			} else {
-				super.loadVector(location_lightPositionEyeSpace[i], new Vector3f(0, 0, 0));
-				super.loadVector(location_lightColour[i], new Vector3f(0, 0, 0));
-				super.loadVector(location_attenuation[i], new Vector3f(1, 0, 0));
+				lightPositionEyeSpace[i].loadVec3(new Vector3f(0, 0, 0));
+				lightColor[i].loadVec3(new Vector3f(0, 0, 0));
+				attenuation[i].loadVec3(new Vector3f(1, 0, 0));
 			}
 		}
 	}
 	
-	protected void loadViewMatrix(Matrix4f viewMatrix) {
-		super.loadMatrix(location_viewMatrix, viewMatrix);
+	@Override
+	public void loadLights(List<Light> lights) {
+		throw new NullPointerException("Use loadLights(List<Light> lights, Matrix4f viewMatrix) instead.");
 	}
-	
-	protected void loadProjectionMatrix(Matrix4f projection) {
-		super.loadMatrix(location_projectionMatrix, projection);
+
+	protected void connectTextureUnits() {
+		modelTexture.loadTexUnit(0);
+		normalMap.loadTexUnit(1);
+		specularMap.loadTexUnit(2);
 	}
-	
+
 	private Vector3f getEyeSpacePosition(Light light, Matrix4f viewMatrix) {
 		Vector3f position = light.getPosition();
 		Vector4f eyeSpacePos = new Vector4f(position.x, position.y, position.z, 1f);
 		Matrix4f.transform(viewMatrix, eyeSpacePos, eyeSpacePos);
 		return new Vector3f(eyeSpacePos);
 	}
-	
+
 }

+ 3 - 3
src/main/java/eu/tankernn/gameEngine/normalMapping/renderer/normalMapFShader.glsl

@@ -12,7 +12,7 @@ uniform sampler2D modelTexture;
 uniform sampler2D normalMap;
 uniform sampler2D specularMap;
 uniform float usesSpecularMap;
-uniform vec3 lightColour[4];
+uniform vec3 lightColor[4];
 uniform vec3 attenuation[4];
 uniform float shineDamper;
 uniform float reflectivity;
@@ -39,8 +39,8 @@ void main(void){
 		float specularFactor = dot(reflectedLightDirection , unitVectorToCamera);
 		specularFactor = max(specularFactor,0.0);
 		float dampedFactor = pow(specularFactor,shineDamper);
-		totalDiffuse = totalDiffuse + (brightness * lightColour[i])/attFactor;
-		totalSpecular = totalSpecular + (dampedFactor * reflectivity * lightColour[i])/attFactor;
+		totalDiffuse = totalDiffuse + (brightness * lightColor[i])/attFactor;
+		totalSpecular = totalSpecular + (dampedFactor * reflectivity * lightColor[i])/attFactor;
 	}
 	totalDiffuse = max(totalDiffuse, 0.2);
 	

+ 3 - 3
src/main/java/eu/tankernn/gameEngine/particles/ParticleRenderer.java

@@ -42,12 +42,12 @@ public class ParticleRenderer {
 		loader.addInstacedAttribute(quad.getVaoID(), vbo, 6, 1, INSTANCE_DATA_LENGTH, 20);
 		shader = new ParticleShader();
 		shader.start();
-		shader.loadProjectionMatrix(projectionMatrix);
+		shader.projectionMatrix.loadMatrix(projectionMatrix);
 		shader.stop();
 	}
 	
 	protected void render(Map<ParticleTexture, List<Particle>> particles, Camera camera) {
-		Matrix4f viewMatrix = Maths.createViewMatrix(camera);
+		Matrix4f viewMatrix = camera.getViewMatrix();
 		prepare();
 		for (ParticleTexture texture: particles.keySet()) {
 			bindTexture(texture);
@@ -81,7 +81,7 @@ public class ParticleRenderer {
 		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, blendType);
 		GL13.glActiveTexture(GL13.GL_TEXTURE0);
 		GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture.getTextureID());
-		shader.loadNumberOfRows(texture.getNumberOfRows());
+		shader.numberOfRows.loadFloat(texture.getNumberOfRows());
 	}
 	
 	private void updateModelViewMatrix(Vector3f position, float rotation, float scale, Matrix4f viewMatrix, float[] vboData) {

+ 7 - 27
src/main/java/eu/tankernn/gameEngine/particles/ParticleShader.java

@@ -1,41 +1,21 @@
 package eu.tankernn.gameEngine.particles;
 
-import org.lwjgl.util.vector.Matrix4f;
-
 import eu.tankernn.gameEngine.shaders.ShaderProgram;
+import eu.tankernn.gameEngine.shaders.UniformFloat;
+import eu.tankernn.gameEngine.shaders.UniformMatrix;
 
 public class ParticleShader extends ShaderProgram {
 
 	private static final String VERTEX_FILE = "/eu/tankernn/gameEngine/particles/particleVShader.glsl";
 	private static final String FRAGMENT_FILE = "/eu/tankernn/gameEngine/particles/particleFShader.glsl";
 
-	private int location_numberOfRows;
-	private int location_projectionMatrix;
+	protected UniformFloat numberOfRows = new UniformFloat("numberOfRows");
+	protected UniformMatrix projectionMatrix = new UniformMatrix("projectionMatrix");
 
 	public ParticleShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
-	}
-
-	@Override
-	protected void getAllUniformLocations() {
-		location_numberOfRows = super.getUniformLocation("numberOfRows");
-		location_projectionMatrix = super.getUniformLocation("projectionMatrix");
-	}
-
-	@Override
-	protected void bindAttributes() {
-		super.bindAttribute(0, "position");
-		super.bindAttribute(1, "modelViewMatrix");
-		super.bindAttribute(5, "texOffsets");
-		super.bindAttribute(6, "blendFactor");
-	}
-	
-	protected void loadNumberOfRows(float numberOfRows) {
-		super.loadFloat(location_numberOfRows, numberOfRows);
-	}
-
-	protected void loadProjectionMatrix(Matrix4f projectionMatrix) {
-		super.loadMatrix(location_projectionMatrix, projectionMatrix);
+		//																 0,					1,						5,				6
+		super(VERTEX_FILE, FRAGMENT_FILE, "position", "modelViewMatrix", "texOffsets", "blendFactor");
+		super.storeAllUniformLocations(numberOfRows, projectionMatrix);
 	}
 
 }

+ 1 - 9
src/main/java/eu/tankernn/gameEngine/postProcessing/ContrastShader.java

@@ -8,15 +8,7 @@ public class ContrastShader extends ShaderProgram {
 	private static final String FRAGMENT_FILE = "/eu/tankernn/gameEngine/postProcessing/contrastFragment.glsl";
 	
 	public ContrastShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
-	}
-	
-	@Override
-	protected void getAllUniformLocations() {}
-	
-	@Override
-	protected void bindAttributes() {
-		super.bindAttribute(0, "position");
+		super(VERTEX_FILE, FRAGMENT_FILE, "position");
 	}
 	
 }

+ 1 - 10
src/main/java/eu/tankernn/gameEngine/postProcessing/bloom/BrightFilterShader.java

@@ -8,16 +8,7 @@ public class BrightFilterShader extends ShaderProgram{
 	private static final String FRAGMENT_FILE = "/eu/tankernn/gameEngine/postProcessing/bloom/brightFilterFragment.glsl";
 	
 	public BrightFilterShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
-	}
-
-	@Override
-	protected void getAllUniformLocations() {	
-	}
-
-	@Override
-	protected void bindAttributes() {
-		super.bindAttribute(0, "position");
+		super(VERTEX_FILE, FRAGMENT_FILE, "position");
 	}
 
 }

+ 7 - 16
src/main/java/eu/tankernn/gameEngine/postProcessing/bloom/CombineShader.java

@@ -1,33 +1,24 @@
 package eu.tankernn.gameEngine.postProcessing.bloom;
 
 import eu.tankernn.gameEngine.shaders.ShaderProgram;
+import eu.tankernn.gameEngine.shaders.UniformSampler;
 
 public class CombineShader extends ShaderProgram {
 
 	private static final String VERTEX_FILE = "/eu/tankernn/gameEngine/postProcessing/bloom/simpleVertex.glsl";
 	private static final String FRAGMENT_FILE = "/eu/tankernn/gameEngine/postProcessing/bloom/combineFragment.glsl";
 	
-	private int location_colourTexture;
-	private int location_highlightTexture;
+	protected UniformSampler colourTexture = new UniformSampler("colourTexture");
+	protected UniformSampler highlightTexture = new UniformSampler("highlightTexture");
 	
 	protected CombineShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
-	}
-	
-	@Override
-	protected void getAllUniformLocations() {
-		location_colourTexture = super.getUniformLocation("colourTexture");
-		location_highlightTexture = super.getUniformLocation("highlightTexture");
+		super(VERTEX_FILE, FRAGMENT_FILE, "position");
+		connectTextureUnits();
 	}
 	
 	protected void connectTextureUnits(){
-		super.loadInt(location_colourTexture, 0);
-		super.loadInt(location_highlightTexture, 1);
-	}
-
-	@Override
-	protected void bindAttributes() {
-		super.bindAttribute(0, "position");
+		colourTexture.loadTexUnit(0);
+		highlightTexture.loadTexUnit(1);
 	}
 	
 }

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/postProcessing/gaussianBlur/HorizontalBlur.java

@@ -13,7 +13,7 @@ public class HorizontalBlur {
 	public HorizontalBlur(int targetFboWidth, int targetFboHeight){
 		shader = new HorizontalBlurShader();
 		shader.start();
-		shader.loadTargetWidth(targetFboWidth);
+		shader.targetWidth.loadFloat(targetFboWidth);
 		shader.stop();
 		renderer = new ImageRenderer(targetFboWidth, targetFboHeight);
 	}

+ 6 - 18
src/main/java/eu/tankernn/gameEngine/postProcessing/gaussianBlur/HorizontalBlurShader.java

@@ -1,30 +1,18 @@
 package eu.tankernn.gameEngine.postProcessing.gaussianBlur;
 
 import eu.tankernn.gameEngine.shaders.ShaderProgram;
+import eu.tankernn.gameEngine.shaders.UniformFloat;
 
 public class HorizontalBlurShader extends ShaderProgram {
 
 	private static final String VERTEX_FILE = "/eu/tankernn/gameEngine/postProcessing/gaussianBlur/horizontalBlurVertex.glsl";
 	private static final String FRAGMENT_FILE = "/eu/tankernn/gameEngine/postProcessing/gaussianBlur/blurFragment.glsl";
-	
-	private int location_targetWidth;
-	
-	protected HorizontalBlurShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
-	}
 
-	protected void loadTargetWidth(float width){
-		super.loadFloat(location_targetWidth, width);
-	}
-	
-	@Override
-	protected void getAllUniformLocations() {
-		location_targetWidth = super.getUniformLocation("targetWidth");
-	}
+	protected UniformFloat targetWidth = new UniformFloat("targetWidth");
 
-	@Override
-	protected void bindAttributes() {
-		super.bindAttribute(0, "position");
+	protected HorizontalBlurShader() {
+		super(VERTEX_FILE, FRAGMENT_FILE, "position");
+		super.storeAllUniformLocations(targetWidth);
 	}
-	
+
 }

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/postProcessing/gaussianBlur/VerticalBlur.java

@@ -14,7 +14,7 @@ public class VerticalBlur {
 		shader = new VerticalBlurShader();
 		renderer = new ImageRenderer(targetFboWidth, targetFboHeight);
 		shader.start();
-		shader.loadTargetHeight(targetFboHeight);
+		shader.targetHeight.loadFloat(targetFboHeight);
 		shader.stop();
 	}
 

+ 4 - 16
src/main/java/eu/tankernn/gameEngine/postProcessing/gaussianBlur/VerticalBlurShader.java

@@ -1,29 +1,17 @@
 package eu.tankernn.gameEngine.postProcessing.gaussianBlur;
 
 import eu.tankernn.gameEngine.shaders.ShaderProgram;
+import eu.tankernn.gameEngine.shaders.UniformFloat;
 
 public class VerticalBlurShader extends ShaderProgram{
 
 	private static final String VERTEX_FILE = "/eu/tankernn/gameEngine/postProcessing/gaussianBlur/verticalBlurVertex.glsl";
 	private static final String FRAGMENT_FILE = "/eu/tankernn/gameEngine/postProcessing/gaussianBlur/blurFragment.glsl";
 	
-	private int location_targetHeight;
+	protected UniformFloat targetHeight = new UniformFloat("targetHeight");
 	
 	protected VerticalBlurShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
-	}
-	
-	protected void loadTargetHeight(float height){
-		super.loadFloat(location_targetHeight, height);
-	}
-
-	@Override
-	protected void getAllUniformLocations() {	
-		location_targetHeight = super.getUniformLocation("targetHeight");
-	}
-
-	@Override
-	protected void bindAttributes() {
-		super.bindAttribute(0, "position");
+		super(VERTEX_FILE, FRAGMENT_FILE, "position");
+		super.storeAllUniformLocations(targetHeight);
 	}
 }

+ 2 - 2
src/main/java/eu/tankernn/gameEngine/renderEngine/DisplayManager.java

@@ -3,13 +3,13 @@ package eu.tankernn.gameEngine.renderEngine;
 import java.awt.Dimension;
 import java.awt.Toolkit;
 
-import org.lwjgl.input.Keyboard;
-import org.lwjgl.opengl.GL11;
 import org.lwjgl.LWJGLException;
 import org.lwjgl.Sys;
+import org.lwjgl.input.Keyboard;
 import org.lwjgl.opengl.ContextAttribs;
 import org.lwjgl.opengl.Display;
 import org.lwjgl.opengl.DisplayMode;
+import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL13;
 import org.lwjgl.opengl.PixelFormat;
 

+ 0 - 102
src/main/java/eu/tankernn/gameEngine/renderEngine/EntityRenderer.java

@@ -1,102 +0,0 @@
-package eu.tankernn.gameEngine.renderEngine;
-
-import java.util.List;
-import java.util.Map;
-
-import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GL13;
-import org.lwjgl.opengl.GL20;
-import org.lwjgl.opengl.GL30;
-import org.lwjgl.util.vector.Matrix4f;
-
-import eu.tankernn.gameEngine.entities.Camera;
-import eu.tankernn.gameEngine.entities.Entity;
-import eu.tankernn.gameEngine.models.TexturedModel;
-import eu.tankernn.gameEngine.shaders.StaticShader;
-import eu.tankernn.gameEngine.skybox.CubeMap;
-import eu.tankernn.gameEngine.textures.ModelTexture;
-import eu.tankernn.gameEngine.util.Maths;
-/**
- * Renderer for entities.
- * @author Frans
- *
- */
-public class EntityRenderer {
-	private StaticShader shader;
-	private CubeMap environmentMap;
-	
-	/**
-	 * Starts shader and loads initial values.
-	 * @param shader The shader to use when rendering entities
-	 * @param projectionMatrix The projection matrix to use when rendering entities
-	 */
-	public EntityRenderer(StaticShader shader, Matrix4f projectionMatrix, CubeMap environmentMap) {
-		this.shader = shader;
-		this.environmentMap = environmentMap;
-		shader.start();
-		shader.loadProjectionMatrix(projectionMatrix);
-		shader.connectTextureUnits();
-		shader.stop();
-	}
-	
-	/**
-	 * Renders entities to the current frame buffer.
-	 * 
-	 * @param entities The entities to render.
-	 * @param toShadowSpace Transformation matrix to shadow space. Used for
-	 *        applying shadows.
-	 */
-	public void render(Map<TexturedModel, List<Entity>> entities, Matrix4f toShadowSpace, Camera cam) {
-		shader.loadToShadowSpaceMatrix(toShadowSpace);
-		shader.loadCameraPosition(cam.getPosition());
-		for (TexturedModel model: entities.keySet()) {
-			prepareTexturedModel(model);
-			List<Entity> batch = entities.get(model);
-			for (Entity entity: batch) {
-				prepareInstance(entity);
-				GL11.glDrawElements(GL11.GL_TRIANGLES, model.getRawModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
-			}
-			unbindTexturedModel();
-		}
-	}
-	
-	private void prepareTexturedModel(TexturedModel model) {
-		GL30.glBindVertexArray(model.getRawModel().getVaoID());
-		GL20.glEnableVertexAttribArray(0);
-		GL20.glEnableVertexAttribArray(1);
-		GL20.glEnableVertexAttribArray(2);
-		ModelTexture texture = model.getTexture();
-		shader.loadNumberOfRows(texture.getNumberOfRows());
-		if (texture.hasTransparency())
-			MasterRenderer.disableCulling();
-		shader.loadFakeLightingVariable(texture.isUseFakeLighting());
-		shader.loadShineVariables(texture.getShineDamper(), texture.getReflectivity());
-		GL13.glActiveTexture(GL13.GL_TEXTURE0);
-		GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getTexture().getID());
-		shader.loadUseSpecularMap(texture.hasSpecularMap());
-		if (texture.hasSpecularMap()) {
-			GL13.glActiveTexture(GL13.GL_TEXTURE1);
-			GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture.getSpecularMap());
-		}
-		bindEnvironmentMap();
-	}
-	
-	private void bindEnvironmentMap() {
-		GL13.glActiveTexture(GL13.GL_TEXTURE10);
-		GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, environmentMap.getTexture());
-	}
-	
-	private void unbindTexturedModel() {
-		MasterRenderer.enableCulling();
-		GL20.glDisableVertexAttribArray(0);
-		GL20.glDisableVertexAttribArray(1);
-		GL20.glDisableVertexAttribArray(2);
-		GL30.glBindVertexArray(0);
-	}
-	
-	private void prepareInstance(Entity entity) {
-		Matrix4f transformationMatrix = Maths.createTransformationMatrix(entity.getPosition(), entity.getRotX(), entity.getRotY(), entity.getRotZ(), entity.getScale());
-		shader.loadTransformationMatrix(transformationMatrix);
-		shader.loadOffset(entity.getTextureXOffset(), entity.getTextureYOffset());
-	}
-}

+ 64 - 88
src/main/java/eu/tankernn/gameEngine/renderEngine/MasterRenderer.java

@@ -1,10 +1,7 @@
 package eu.tankernn.gameEngine.renderEngine;
 
 import static eu.tankernn.gameEngine.settings.Settings.BLUE;
-import static eu.tankernn.gameEngine.settings.Settings.FAR_PLANE;
-import static eu.tankernn.gameEngine.settings.Settings.FOV;
 import static eu.tankernn.gameEngine.settings.Settings.GREEN;
-import static eu.tankernn.gameEngine.settings.Settings.NEAR_PLANE;
 import static eu.tankernn.gameEngine.settings.Settings.RED;
 import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
 import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
@@ -14,10 +11,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.lwjgl.opengl.Display;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL13;
-import org.lwjgl.util.vector.Matrix4f;
 import org.lwjgl.util.vector.Vector4f;
 
 import eu.tankernn.gameEngine.entities.Camera;
@@ -25,11 +20,14 @@ import eu.tankernn.gameEngine.entities.Entity;
 import eu.tankernn.gameEngine.entities.Light;
 import eu.tankernn.gameEngine.models.TexturedModel;
 import eu.tankernn.gameEngine.normalMapping.renderer.NormalMappingRenderer;
-import eu.tankernn.gameEngine.shaders.StaticShader;
-import eu.tankernn.gameEngine.shaders.TerrainShader;
+import eu.tankernn.gameEngine.renderEngine.entities.EntityRenderer;
+import eu.tankernn.gameEngine.renderEngine.terrain.TerrainRenderer;
 import eu.tankernn.gameEngine.shadows.ShadowMapMasterRenderer;
+import eu.tankernn.gameEngine.skybox.Skybox;
 import eu.tankernn.gameEngine.skybox.SkyboxRenderer;
 import eu.tankernn.gameEngine.terrains.Terrain;
+import eu.tankernn.gameEngine.textures.Texture;
+import eu.tankernn.gameEngine.util.ICamera;
 
 /**
  * Handles most of the rendering in the game.
@@ -37,8 +35,7 @@ import eu.tankernn.gameEngine.terrains.Terrain;
  * @author Frans
  */
 public class MasterRenderer {
-	private StaticShader staticShader = new StaticShader();
-	private TerrainShader terrainShader = new TerrainShader();
+	private static final Vector4f NO_CLIP = new Vector4f(0, 0, 0, 1);
 	
 	private EntityRenderer entityRenderer;
 	private TerrainRenderer terrainRenderer;
@@ -46,28 +43,27 @@ public class MasterRenderer {
 	private NormalMappingRenderer normalMapRenderer;
 	private ShadowMapMasterRenderer shadowMapRenderer;
 	
-	private Matrix4f projectionMatrix;
-	
 	private Map<TexturedModel, List<Entity>> entities = new HashMap<TexturedModel, List<Entity>>();
 	private Map<TexturedModel, List<Entity>> normalMapEntities = new HashMap<TexturedModel, List<Entity>>();
 	private List<Terrain> terrains = new ArrayList<Terrain>();
-	
+
 	/**
 	 * Sets up most other renderers for rendering.
 	 * 
-	 * @param loader The main <code>Loader</code>, used by some other renderers
-	 * @param camera The main <code>Camera</code>
+	 * @param loader
+	 *            The main <code>Loader</code>, used by some other renderers
+	 * @param camera
+	 *            The main <code>Camera</code>
 	 */
-	public MasterRenderer(Loader loader, Camera camera, String[] dayTextureFiles, String[] nightTextureFiles) {
+	public MasterRenderer(Loader loader, Camera camera, Skybox skybox) {
 		enableCulling();
-		createProjectionMatrix();
-		terrainRenderer = new TerrainRenderer(terrainShader, projectionMatrix);
-		normalMapRenderer = new NormalMappingRenderer(projectionMatrix);
+		terrainRenderer = new TerrainRenderer(camera.getProjectionMatrix());
+		normalMapRenderer = new NormalMappingRenderer(camera.getProjectionMatrix());
 		shadowMapRenderer = new ShadowMapMasterRenderer(camera);
-		skyboxRenderer = new SkyboxRenderer(loader, projectionMatrix, dayTextureFiles, nightTextureFiles);
-		entityRenderer = new EntityRenderer(staticShader, projectionMatrix, skyboxRenderer.getCubeMap());
+		skyboxRenderer = new SkyboxRenderer(loader, camera.getProjectionMatrix(), skybox);
+		entityRenderer = new EntityRenderer(camera.getProjectionMatrix());
 	}
-	
+
 	/**
 	 * Enables culling of faces facing away from the camera.
 	 */
@@ -75,7 +71,7 @@ public class MasterRenderer {
 		GL11.glEnable(GL11.GL_CULL_FACE);
 		GL11.glCullFace(GL11.GL_BACK);
 	}
-	
+
 	/**
 	 * Disables culling of faces facing away from the camera. Used when
 	 * rendering flat objects.
@@ -83,63 +79,62 @@ public class MasterRenderer {
 	public static void disableCulling() {
 		GL11.glDisable(GL11.GL_CULL_FACE);
 	}
-	
+
 	/**
 	 * Renders a scene.
 	 * 
-	 * @param scene The <code>Scene</code> to render.
-	 * @param clipPlane The clip plane.
+	 * @param scene
+	 *            The <code>Scene</code> to render.
+	 * @param clipPlane
+	 *            The clip plane.
 	 */
 	public void renderScene(Scene scene, Vector4f clipPlane) {
 		scene.getTerrainPack().prepareRenderTerrains(this);
-		for (Entity e: scene.getEntities()) {
+		for (Entity e : scene.getEntities()) {
 			processEntity(e);
 		}
-		for (Entity e: scene.getNormalEntities()) {
+		for (Entity e : scene.getNormalEntities()) {
 			processNormalMappedEntity(e);
 		}
-		render(scene.getLights(), scene.getCamera(), clipPlane);
+		render(scene.getLights(), scene.getCamera(), clipPlane, scene.getEnvironmentMap());
 	}
 	
+	public void renderLowQualityScene(Scene scene, ICamera camera) {
+		prepare();
+		entityRenderer.render(entities, shadowMapRenderer.getToShadowMapSpaceMatrix(), camera, NO_CLIP, scene.getLights(), scene.getEnvironmentMap());
+		normalMapRenderer.render(normalMapEntities, NO_CLIP, scene.getLights(), camera);
+		terrainRenderer.render(terrains, shadowMapRenderer.getToShadowMapSpaceMatrix(), camera, NO_CLIP, scene.getLights());
+		
+	}
+
 	/**
 	 * Renders the current scene to the current buffer.
 	 * 
-	 * @param lights List of lights in the scene.
-	 * @param camera The main camera.
-	 * @param clipPlane The clip plane.
+	 * @param lights
+	 *            List of lights in the scene.
+	 * @param camera
+	 *            The main camera.
+	 * @param clipPlane
+	 *            The clip plane.
 	 */
-	public void render(List<Light> lights, Camera camera, Vector4f clipPlane) {
+	public void render(List<Light> lights, ICamera camera, Vector4f clipPlane, Texture environmentMap) {
 		prepare();
-		staticShader.start();
-		staticShader.loadClipPlane(clipPlane);
-		staticShader.loadSkyColor(RED, GREEN, BLUE);
-		staticShader.loadLights(lights);
-		staticShader.loadViewMatrix(camera);
-		entityRenderer.render(entities, shadowMapRenderer.getToShadowMapSpaceMatrix(), camera);
-		staticShader.stop();
-		
+
+		entityRenderer.render(entities, shadowMapRenderer.getToShadowMapSpaceMatrix(), camera, clipPlane, lights, environmentMap);
 		normalMapRenderer.render(normalMapEntities, clipPlane, lights, camera);
-		
-		terrainShader.start();
-		terrainShader.loadClipPlane(clipPlane);
-		terrainShader.loadSkyColor(RED, GREEN, BLUE);
-		terrainShader.loadShadowMapSize(ShadowMapMasterRenderer.SHADOW_MAP_SIZE);
-		terrainShader.loadLights(lights);
-		terrainShader.loadViewMatrix(camera);
-		terrainRenderer.render(terrains, shadowMapRenderer.getToShadowMapSpaceMatrix());
-		terrainShader.stop();
-		
+		terrainRenderer.render(terrains, shadowMapRenderer.getToShadowMapSpaceMatrix(), camera, clipPlane, lights);
 		skyboxRenderer.render(camera, RED, GREEN, BLUE);
-		
+
 		entities.clear();
 		terrains.clear();
 		normalMapEntities.clear();
 	}
-	
+
 	/**
 	 * Adds an entity to the list of entities.
 	 * 
-	 * @param entity Entity to add to the list
+	 * @param entity
+	 *            Entity to add to the list
 	 */
 	public void processEntity(Entity entity) {
 		TexturedModel entityModel = entity.getModel();
@@ -152,11 +147,12 @@ public class MasterRenderer {
 			entities.put(entityModel, newBatch);
 		}
 	}
-	
+
 	/**
 	 * Same as {@link #processEntity(Entity)}, but for normal-mapped entities.
 	 * 
-	 * @param entity Entity to add to the list
+	 * @param entity
+	 *            Entity to add to the list
 	 */
 	public void processNormalMappedEntity(Entity entity) {
 		TexturedModel entityModel = entity.getModel();
@@ -169,24 +165,25 @@ public class MasterRenderer {
 			normalMapEntities.put(entityModel, newBatch);
 		}
 	}
-	
+
 	/**
 	 * Adds specified terrain to the terrain list.
 	 * 
-	 * @param terrain Terrain object to add to list
+	 * @param terrain
+	 *            Terrain object to add to list
 	 */
 	public void processTerrain(Terrain terrain) {
 		terrains.add(terrain);
 	}
-	
+
 	public void renderShadowMap(List<Entity> entityList, Light sun) {
-		for (Entity e: entityList) {
+		for (Entity e : entityList) {
 			processEntity(e);
 		}
 		shadowMapRenderer.render(entities, sun);
 		entities.clear();
 	}
-	
+
 	/**
 	 * Gets the shadow map texture from the <code>shadowMapRenderer</code>.
 	 * 
@@ -195,48 +192,27 @@ public class MasterRenderer {
 	public int getShadowMapTexture() {
 		return shadowMapRenderer.getShadowMap();
 	}
-	
+
 	/**
 	 * Runs the cleanup method for the other renderers.
 	 */
 	public void cleanUp() {
-		staticShader.cleanUp();
-		terrainShader.cleanUp();
+		entityRenderer.cleanUp();
+		terrainRenderer.cleanUp();
 		normalMapRenderer.cleanUp();
 		shadowMapRenderer.cleanUp();
 	}
-	
+
 	/**
 	 * Prepares the current buffer for rendering.
 	 */
 	public void prepare() {
 		GL11.glEnable(GL11.GL_DEPTH_TEST | GL11.GL_DEPTH_BUFFER_BIT);
 		GL11.glClearColor(RED, GREEN, BLUE, 1);
-		GL11.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer
+		GL11.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the
+																	// framebuffer
 		GL13.glActiveTexture(GL13.GL_TEXTURE5);
 		GL11.glBindTexture(GL11.GL_TEXTURE_2D, getShadowMapTexture());
 	}
-	
-	private void createProjectionMatrix() {
-		float aspectRatio = (float) Display.getWidth() / (float) Display.getHeight();
-		float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))));
-		float x_scale = y_scale / aspectRatio;
-		float frustum_length = FAR_PLANE - NEAR_PLANE;
-		
-		projectionMatrix = new Matrix4f();
-		projectionMatrix.m00 = x_scale;
-		projectionMatrix.m11 = y_scale;
-		projectionMatrix.m22 = -((FAR_PLANE + NEAR_PLANE) / frustum_length);
-		projectionMatrix.m23 = -1;
-		projectionMatrix.m32 = -((2 * FAR_PLANE * NEAR_PLANE) / frustum_length);
-		projectionMatrix.m33 = 0;
-	}
-	/**
-	 * Gets the current projection matrix.
-	 * @return The current projection matrix
-	 */
-	public Matrix4f getProjectionMatrix() {
-		return projectionMatrix;
-	}
-	
+
 }

+ 20 - 1
src/main/java/eu/tankernn/gameEngine/renderEngine/Scene.java

@@ -5,7 +5,9 @@ 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.skybox.Skybox;
 import eu.tankernn.gameEngine.terrains.TerrainPack;
+import eu.tankernn.gameEngine.textures.Texture;
 
 public class Scene {
 	private List<Entity> entities;
@@ -13,13 +15,18 @@ public class Scene {
 	private TerrainPack terrainPack;
 	private List<Light> lights;
 	private Camera camera;
+	private Skybox sky;
 	
-	public Scene(List<Entity> entities, List<Entity> normalEntities, TerrainPack terrainPack, List<Light> lights, Camera camera) {
+	private Texture environmentMap;
+	
+	public Scene(List<Entity> entities, List<Entity> normalEntities, TerrainPack terrainPack, List<Light> lights, Camera camera, Skybox sky) {
 		this.entities = entities;
 		this.normalEntities = normalEntities;
 		this.terrainPack = terrainPack;
 		this.lights = lights;
 		this.camera = camera;
+		this.sky = sky;
+		this.environmentMap = Texture.newEmptyCubeMap(128);
 	}
 
 	public List<Entity> getEntities() {
@@ -41,4 +48,16 @@ public class Scene {
 	public Camera getCamera() {
 		return camera;
 	}
+	
+	public Skybox getSkybox() {
+		return sky;
+	}
+	
+	public Texture getEnvironmentMap() {
+		return environmentMap;
+	}
+	
+	public void delete() {
+		environmentMap.delete();
+	}
 }

+ 132 - 0
src/main/java/eu/tankernn/gameEngine/renderEngine/Vao.java

@@ -0,0 +1,132 @@
+package eu.tankernn.gameEngine.renderEngine;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL15;
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.opengl.GL30;
+
+public class Vao {
+	
+	private static final int BYTES_PER_FLOAT = 4;
+
+	public final int id;
+	private Vbo dataVbo;
+	private Vbo indexVbo;
+	private int indexCount;
+
+	public static Vao create() {
+		int id = GL30.glGenVertexArrays();
+		return new Vao(id);
+	}
+
+	private Vao(int id) {
+		this.id = id;
+	}
+	
+	public int getIndexCount(){
+		return indexCount;
+	}
+
+	public void bind() {
+		GL30.glBindVertexArray(id);
+	}
+	
+	public void bind(int... attributes){
+		bind();
+		for (int i : attributes) {
+			GL20.glEnableVertexAttribArray(i);
+		}
+	}
+
+	public void unbind() {
+		GL30.glBindVertexArray(0);
+	}
+	
+	public void unbind(int... attributes){
+		for (int i : attributes) {
+			GL20.glDisableVertexAttribArray(i);
+		}
+		unbind();
+	}
+	
+	public void storeData(int[] indices, int vertexCount, float[]... data){
+		bind();
+		storeData(vertexCount, data);
+		createIndexBuffer(indices);
+		unbind();
+	}
+	
+	public void delete() {
+		GL30.glDeleteVertexArrays(id);
+		dataVbo.delete();
+		indexVbo.delete();
+	}
+
+	private void createIndexBuffer(int[] indices){
+		this.indexVbo = Vbo.create(GL15.GL_ELEMENT_ARRAY_BUFFER);
+		indexVbo.bind();
+		indexVbo.storeData(indices);
+		this.indexCount = indices.length;
+	}
+	
+	private void storeData(int vertexCount, float[]... data) {
+		float[] interleavedData = interleaveFloatData(vertexCount, data);
+		int[] lengths = getAttributeLengths(data, vertexCount);
+		storeInterleavedData(interleavedData, lengths);
+	}
+	
+	private int[] getAttributeLengths(float[][] data, int vertexCount){
+		int[] lengths = new int[data.length];
+		for (int i = 0; i < data.length; i++) {
+			lengths[i] = data[i].length / vertexCount;
+		}
+		return lengths;
+	}
+
+	private void storeInterleavedData(float[] data, int... lengths) {
+		dataVbo = Vbo.create(GL15.GL_ARRAY_BUFFER);
+		dataVbo.bind();
+		dataVbo.storeData(data);
+		int bytesPerVertex = calculateBytesPerVertex(lengths);
+		linkVboDataToAttributes(lengths, bytesPerVertex);
+		dataVbo.unbind();
+	}
+	
+	private void linkVboDataToAttributes(int[] lengths, int bytesPerVertex){
+		int total = 0;
+		for (int i = 0; i < lengths.length; i++) {
+			GL20.glVertexAttribPointer(i, lengths[i], GL11.GL_FLOAT, false, bytesPerVertex, BYTES_PER_FLOAT * total);
+			total += lengths[i];
+		}
+	}
+	
+	private int calculateBytesPerVertex(int[] lengths){
+		int total = 0;
+		for (int i = 0; i < lengths.length; i++) {
+			total += lengths[i];
+		}
+		return BYTES_PER_FLOAT * total;
+	}
+
+	private float[] interleaveFloatData(int count, float[]... data) {
+		int totalSize = 0;
+		int[] lengths = new int[data.length];
+		for (int i = 0; i < data.length; i++) {
+			int elementLength = data[i].length / count;
+			lengths[i] = elementLength;
+			totalSize += data[i].length;
+		}
+		float[] interleavedBuffer = new float[totalSize];
+		int pointer = 0;
+		for (int i = 0; i < count; i++) {
+			for (int j = 0; j < data.length; j++) {
+				int elementLength = lengths[j];
+				for (int k = 0; k < elementLength; k++) {
+					interleavedBuffer[pointer++] = data[j][i * elementLength + k];
+				}
+			}
+		}
+		return interleavedBuffer;
+	}
+
+}

+ 58 - 0
src/main/java/eu/tankernn/gameEngine/renderEngine/Vbo.java

@@ -0,0 +1,58 @@
+package eu.tankernn.gameEngine.renderEngine;
+
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.GL15;
+
+public class Vbo {
+	
+	private final int vboId;
+	private final int type;
+	
+	private Vbo(int vboId, int type){
+		this.vboId = vboId;
+		this.type = type;
+	}
+	
+	public static Vbo create(int type){
+		int id = GL15.glGenBuffers();
+		return new Vbo(id, type);
+	}
+	
+	public void bind(){
+		GL15.glBindBuffer(type, vboId);
+	}
+	
+	public void unbind(){
+		GL15.glBindBuffer(type, vboId);
+	}
+	
+	public void storeData(float[] data){
+		FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
+		buffer.put(data);
+		buffer.flip();
+		storeData(buffer);
+	}
+	
+	public void storeData(FloatBuffer data){
+		GL15.glBufferData(type, data, GL15.GL_STATIC_DRAW);
+	}
+	
+	public void storeData(int[] data){
+		IntBuffer buffer = BufferUtils.createIntBuffer(data.length);
+		buffer.put(data);
+		buffer.flip();
+		storeData(buffer);
+	}
+	
+	public void storeData(IntBuffer data){
+		GL15.glBufferData(type, data, GL15.GL_STATIC_DRAW);
+	}
+	
+	public void delete(){
+		GL15.glDeleteBuffers(vboId);
+	}
+
+}

+ 126 - 0
src/main/java/eu/tankernn/gameEngine/renderEngine/entities/EntityRenderer.java

@@ -0,0 +1,126 @@
+package eu.tankernn.gameEngine.renderEngine.entities;
+
+import static eu.tankernn.gameEngine.settings.Settings.BLUE;
+import static eu.tankernn.gameEngine.settings.Settings.GREEN;
+import static eu.tankernn.gameEngine.settings.Settings.RED;
+
+import java.util.List;
+import java.util.Map;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL13;
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.opengl.GL30;
+import org.lwjgl.util.vector.Matrix4f;
+import org.lwjgl.util.vector.Vector4f;
+
+import eu.tankernn.gameEngine.entities.Entity;
+import eu.tankernn.gameEngine.entities.Light;
+import eu.tankernn.gameEngine.models.TexturedModel;
+import eu.tankernn.gameEngine.renderEngine.MasterRenderer;
+import eu.tankernn.gameEngine.textures.ModelTexture;
+import eu.tankernn.gameEngine.textures.Texture;
+import eu.tankernn.gameEngine.util.ICamera;
+import eu.tankernn.gameEngine.util.Maths;
+
+/**
+ * Renderer for entities.
+ * 
+ * @author Frans
+ *
+ */
+public class EntityRenderer {
+	private EntityShader shader;
+
+	/**
+	 * Starts shader and loads initial values.
+	 * 
+	 * @param shader
+	 *            The shader to use when rendering entities
+	 * @param projectionMatrix
+	 *            The projection matrix to use when rendering entities
+	 */
+	public EntityRenderer(Matrix4f projectionMatrix) {
+		this.shader = new EntityShader();
+		shader.start();
+		shader.projectionMatrix.loadMatrix(projectionMatrix);
+		shader.connectTextureUnits();
+		shader.stop();
+	}
+
+	/**
+	 * Renders entities to the current frame buffer.
+	 * 
+	 * @param entities
+	 *            The entities to render.
+	 * @param toShadowSpace
+	 *            Transformation matrix to shadow space. Used for applying
+	 *            shadows.
+	 */
+	public void render(Map<TexturedModel, List<Entity>> entities, Matrix4f toShadowSpace, ICamera cam,
+			Vector4f clipPlane, List<Light> lights, Texture environmentMap) {
+		shader.start();
+		shader.plane.loadVec4(clipPlane);
+		shader.skyColor.loadVec3(RED, GREEN, BLUE);
+		shader.loadLights(lights);
+		shader.viewMatrix.loadCamera(cam);
+
+		shader.toShadowMapSpace.loadMatrix(toShadowSpace);
+		shader.cameraPosition.loadVec3(cam.getPosition());
+		for (TexturedModel model : entities.keySet()) {
+			prepareTexturedModel(model, environmentMap);
+			List<Entity> batch = entities.get(model);
+			for (Entity entity : batch) {
+				prepareInstance(entity);
+				GL11.glDrawElements(GL11.GL_TRIANGLES, model.getRawModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
+			}
+			unbindTexturedModel();
+		}
+		shader.stop();
+	}
+
+	public void cleanUp() {
+		shader.cleanUp();
+	}
+
+	private void prepareTexturedModel(TexturedModel model, Texture environmentMap) {
+		GL30.glBindVertexArray(model.getRawModel().getVaoID());
+		GL20.glEnableVertexAttribArray(0);
+		GL20.glEnableVertexAttribArray(1);
+		GL20.glEnableVertexAttribArray(2);
+		ModelTexture texture = model.getTexture();
+		shader.numberOfRows.loadFloat(texture.getNumberOfRows());
+		if (texture.hasTransparency())
+			MasterRenderer.disableCulling();
+		shader.useFakeLighting.loadBoolean(texture.isUseFakeLighting());
+		shader.shineDamper.loadFloat(texture.getShineDamper());
+		shader.reflectivity.loadFloat(texture.getReflectivity());
+		GL13.glActiveTexture(GL13.GL_TEXTURE0);
+		GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getTexture().getID());
+		shader.usesSpecularMap.loadBoolean(texture.hasSpecularMap());
+		if (texture.hasSpecularMap()) {
+			GL13.glActiveTexture(GL13.GL_TEXTURE1);
+			GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture.getSpecularMap());
+		}
+		bindEnvironmentMap(environmentMap);
+	}
+
+	private void bindEnvironmentMap(Texture environmentMap) {
+		environmentMap.bindToUnit(10);
+	}
+
+	private void unbindTexturedModel() {
+		MasterRenderer.enableCulling();
+		GL20.glDisableVertexAttribArray(0);
+		GL20.glDisableVertexAttribArray(1);
+		GL20.glDisableVertexAttribArray(2);
+		GL30.glBindVertexArray(0);
+	}
+
+	private void prepareInstance(Entity entity) {
+		Matrix4f transformationMatrix = Maths.createTransformationMatrix(entity.getPosition(), entity.getRotX(),
+				entity.getRotY(), entity.getRotZ(), entity.getScale());
+		shader.transformationMatrix.loadMatrix(transformationMatrix);
+		shader.offset.loadVec2(entity.getTextureXOffset(), entity.getTextureYOffset());
+	}
+}

+ 50 - 0
src/main/java/eu/tankernn/gameEngine/renderEngine/entities/EntityShader.java

@@ -0,0 +1,50 @@
+package eu.tankernn.gameEngine.renderEngine.entities;
+
+import eu.tankernn.gameEngine.shaders.ShaderProgram;
+import eu.tankernn.gameEngine.shaders.UniformBoolean;
+import eu.tankernn.gameEngine.shaders.UniformFloat;
+import eu.tankernn.gameEngine.shaders.UniformMatrix;
+import eu.tankernn.gameEngine.shaders.UniformSampler;
+import eu.tankernn.gameEngine.shaders.UniformVec2;
+import eu.tankernn.gameEngine.shaders.UniformVec3;
+import eu.tankernn.gameEngine.shaders.UniformVec4;
+import eu.tankernn.gameEngine.shaders.UniformViewMatrix;
+
+public class EntityShader extends ShaderProgram {
+
+	private static final String VERTEX_FILE = "/eu/tankernn/gameEngine/renderEngine/entities/vertexShader.glsl";
+	private static final String FRAGMENT_FILE = "/eu/tankernn/gameEngine/renderEngine/entities/fragmentShader.glsl";
+
+	protected UniformMatrix transformationMatrix = new UniformMatrix("transformationMatrix");
+	protected UniformMatrix projectionMatrix = new UniformMatrix("projectionMatrix");
+	protected UniformViewMatrix viewMatrix = new UniformViewMatrix("viewMatrix");
+	protected UniformFloat shineDamper = new UniformFloat("shineDamper");
+	protected UniformFloat reflectivity = new UniformFloat("reflectivity");
+	protected UniformBoolean useFakeLighting = new UniformBoolean("useFakeLighting");
+	protected UniformVec3 skyColor = new UniformVec3("skyColor");
+	protected UniformFloat numberOfRows = new UniformFloat("numberOfRows");
+	protected UniformVec2 offset = new UniformVec2("offset");
+	protected UniformVec4 plane = new UniformVec4("plane");
+	protected UniformMatrix toShadowMapSpace = new UniformMatrix("toShadowMapSpace");
+	protected UniformSampler shadowMap = new UniformSampler("shadowMap");
+	protected UniformSampler specularMap = new UniformSampler("specularMap");
+	protected UniformBoolean usesSpecularMap = new UniformBoolean("usesSpecularMap");
+	protected UniformSampler modelTexture = new UniformSampler("modelTexture");
+	protected UniformVec3 cameraPosition = new UniformVec3("cameraPosition");
+	protected UniformSampler enviroMap = new UniformSampler("enviroMap");
+
+	public EntityShader() {
+		super(VERTEX_FILE, FRAGMENT_FILE, "position", "textureCoords", "normal");
+		super.getLightUniformLocations();
+		super.storeAllUniformLocations(transformationMatrix, projectionMatrix, viewMatrix, shineDamper, reflectivity,
+				useFakeLighting, skyColor, numberOfRows, offset, plane, toShadowMapSpace, shadowMap, specularMap,
+				usesSpecularMap, modelTexture, cameraPosition, enviroMap);
+	}
+
+	public void connectTextureUnits() {
+		shadowMap.loadTexUnit(5);
+		modelTexture.loadTexUnit(0);
+		specularMap.loadTexUnit(1);
+		enviroMap.loadTexUnit(10);
+	}
+}

+ 2 - 2
src/main/java/eu/tankernn/gameEngine/shaders/fragmentShader.glsl → src/main/java/eu/tankernn/gameEngine/renderEngine/entities/fragmentShader.glsl

@@ -13,7 +13,7 @@ layout (location = 0) out vec4 out_Color;
 layout (location = 1) out vec4 out_BrightColor;
 
 uniform sampler2D shadowMap;
-uniform sampler2D textureSampler;
+uniform sampler2D modelTexture;
 uniform sampler2D specularMap;
 uniform samplerCube enviroMap;
 uniform float usesSpecularMap;
@@ -60,7 +60,7 @@ void main(void){
 	
 	totalDiffuse = max(totalDiffuse * lightFactor, 0.2); //Ambient lighting 2.0
 	
-	vec4 textureColor = texture(textureSampler, pass_textureCoords);
+	vec4 textureColor = texture(modelTexture, pass_textureCoords);
 	if (textureColor.a < 0.5) {
 		discard;
 	}

+ 0 - 1
src/main/java/eu/tankernn/gameEngine/shaders/vertexShader.glsl → src/main/java/eu/tankernn/gameEngine/renderEngine/entities/vertexShader.glsl

@@ -24,7 +24,6 @@ uniform float numberOfRows;
 uniform vec2 offset;
 
 uniform mat4 toShadowMapSpace;
-uniform float shadowDistance;
 
 uniform vec3 cameraPosition;
 

+ 41 - 19
src/main/java/eu/tankernn/gameEngine/renderEngine/TerrainRenderer.java → src/main/java/eu/tankernn/gameEngine/renderEngine/terrain/TerrainRenderer.java

@@ -1,4 +1,8 @@
-package eu.tankernn.gameEngine.renderEngine;
+package eu.tankernn.gameEngine.renderEngine.terrain;
+
+import static eu.tankernn.gameEngine.settings.Settings.BLUE;
+import static eu.tankernn.gameEngine.settings.Settings.GREEN;
+import static eu.tankernn.gameEngine.settings.Settings.RED;
 
 import java.util.List;
 
@@ -8,45 +12,62 @@ import org.lwjgl.opengl.GL20;
 import org.lwjgl.opengl.GL30;
 import org.lwjgl.util.vector.Matrix4f;
 import org.lwjgl.util.vector.Vector3f;
+import org.lwjgl.util.vector.Vector4f;
 
-import eu.tankernn.gameEngine.shaders.TerrainShader;
+import eu.tankernn.gameEngine.entities.Light;
 import eu.tankernn.gameEngine.shadows.ShadowBox;
+import eu.tankernn.gameEngine.shadows.ShadowMapMasterRenderer;
 import eu.tankernn.gameEngine.terrains.Terrain;
 import eu.tankernn.gameEngine.textures.TerrainTexturePack;
+import eu.tankernn.gameEngine.util.ICamera;
 import eu.tankernn.gameEngine.util.Maths;
 
 public class TerrainRenderer {
 	private TerrainShader shader;
-	
-	public TerrainRenderer(TerrainShader shader, Matrix4f projectionMatrix) {
-		this.shader = shader;
+
+	public TerrainRenderer(Matrix4f projectionMatrix) {
+		shader = new TerrainShader();
 		shader.start();
-		shader.loadProjectionMatrix(projectionMatrix);
+		shader.projectionMatrix.loadMatrix(projectionMatrix);
 		shader.connectTextureUnits();
 		shader.stop();
 	}
-	
-	public void render(List<Terrain> terrains, Matrix4f toShadowSpace) {
-		shader.loadToShadowSpaceMatrix(toShadowSpace);
-		for (Terrain terrain: terrains) {
+
+	public void render(List<Terrain> terrains, Matrix4f toShadowSpace, ICamera camera, Vector4f clipPlane,
+			List<Light> lights) {
+		shader.start();
+		shader.plane.loadVec4(clipPlane);
+		shader.skyColor.loadVec3(RED, GREEN, BLUE);
+		shader.loadLights(lights);
+		shader.viewMatrix.loadCamera(camera);
+		shader.shadowMapSize.loadFloat(ShadowMapMasterRenderer.SHADOW_MAP_SIZE);
+
+		shader.toShadowMapSpace.loadMatrix(toShadowSpace);
+		for (Terrain terrain : terrains) {
 			prepareTerrain(terrain);
 			loadModelMatrix(terrain);
 			GL11.glDrawElements(GL11.GL_TRIANGLES, terrain.getModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
-			
+
 			unbindTexturedModel();
 		}
+		shader.stop();
 	}
-	
+
+	public void cleanUp() {
+		shader.cleanUp();
+	}
+
 	private void prepareTerrain(Terrain terrain) {
 		GL30.glBindVertexArray(terrain.getModel().getVaoID());
 		GL20.glEnableVertexAttribArray(0);
 		GL20.glEnableVertexAttribArray(1);
 		GL20.glEnableVertexAttribArray(2);
 		bindTexture(terrain);
-		shader.loadShineVariables(1, 0); // No shine
-		shader.loadShadowDistance(ShadowBox.SHADOW_DISTANCE);
+		shader.shineDamper.loadFloat(1); // No shine
+		shader.reflectivity.loadFloat(0); // No shine
+		shader.shadowDistance.loadFloat(ShadowBox.SHADOW_DISTANCE);
 	}
-	
+
 	private void bindTexture(Terrain terrain) {
 		TerrainTexturePack texturePack = terrain.getTexturePack();
 		GL13.glActiveTexture(GL13.GL_TEXTURE0);
@@ -60,16 +81,17 @@ public class TerrainRenderer {
 		GL13.glActiveTexture(GL13.GL_TEXTURE4);
 		GL11.glBindTexture(GL11.GL_TEXTURE_2D, terrain.getBlendMap().getTextureID());
 	}
-	
+
 	private void unbindTexturedModel() {
 		GL20.glDisableVertexAttribArray(0);
 		GL20.glDisableVertexAttribArray(1);
 		GL20.glDisableVertexAttribArray(2);
 		GL30.glBindVertexArray(0);
 	}
-	
+
 	private void loadModelMatrix(Terrain terrain) {
-		Matrix4f transformationMatrix = Maths.createTransformationMatrix(new Vector3f(terrain.getX(), 0, terrain.getZ()), 0, 0, 0, 1);
-		shader.loadTransformationMatrix(transformationMatrix);
+		Matrix4f transformationMatrix = Maths
+				.createTransformationMatrix(new Vector3f(terrain.getX(), 0, terrain.getZ()), 0, 0, 0, 1);
+		shader.transformationMatrix.loadMatrix(transformationMatrix);
 	}
 }

+ 49 - 0
src/main/java/eu/tankernn/gameEngine/renderEngine/terrain/TerrainShader.java

@@ -0,0 +1,49 @@
+package eu.tankernn.gameEngine.renderEngine.terrain;
+
+import eu.tankernn.gameEngine.shaders.ShaderProgram;
+import eu.tankernn.gameEngine.shaders.UniformFloat;
+import eu.tankernn.gameEngine.shaders.UniformMatrix;
+import eu.tankernn.gameEngine.shaders.UniformSampler;
+import eu.tankernn.gameEngine.shaders.UniformVec3;
+import eu.tankernn.gameEngine.shaders.UniformVec4;
+import eu.tankernn.gameEngine.shaders.UniformViewMatrix;
+
+public class TerrainShader extends ShaderProgram {
+
+	private static final String VERTEX_FILE = "/eu/tankernn/gameEngine/renderEngine/terrain/terrainVertexShader.glsl";
+	private static final String FRAGMENT_FILE = "/eu/tankernn/gameEngine/renderEngine/terrain/terrainFragmentShader.glsl";
+
+	protected UniformMatrix transformationMatrix = new UniformMatrix("transformationMatrix");
+	protected UniformMatrix projectionMatrix = new UniformMatrix("projectionMatrix");
+	protected UniformViewMatrix viewMatrix = new UniformViewMatrix("viewMatrix");
+	protected UniformFloat shineDamper = new UniformFloat("shineDamper");
+	protected UniformFloat reflectivity = new UniformFloat("reflectivity");
+	protected UniformVec3 skyColor = new UniformVec3("skyColor");
+	protected UniformSampler backgroundTexture = new UniformSampler("backgroundTexture");
+	protected UniformSampler rTexture = new UniformSampler("rTexture");
+	protected UniformSampler gTexture = new UniformSampler("gTexture");
+	protected UniformSampler bTexture = new UniformSampler("bTexture");
+	protected UniformSampler blendMap = new UniformSampler("blendMap");
+	protected UniformVec4 plane = new UniformVec4("plane");
+	protected UniformMatrix toShadowMapSpace = new UniformMatrix("toShadowMapSpace");
+	protected UniformSampler shadowMap = new UniformSampler("shadowMap");
+	protected UniformFloat shadowDistance = new UniformFloat("shadowDistance");
+	protected UniformFloat shadowMapSize = new UniformFloat("shadowMapSize");
+
+	public TerrainShader() {
+		super(VERTEX_FILE, FRAGMENT_FILE, "position", "textureCoords", "normal");
+		super.getLightUniformLocations();
+		super.storeAllUniformLocations(transformationMatrix, projectionMatrix, viewMatrix, shineDamper, reflectivity,
+				skyColor, backgroundTexture, rTexture, gTexture, bTexture, blendMap, plane, toShadowMapSpace, shadowMap,
+				shadowDistance, shadowMapSize);
+	}
+
+	public void connectTextureUnits() {
+		backgroundTexture.loadTexUnit(0);
+		rTexture.loadTexUnit(1);
+		gTexture.loadTexUnit(2);
+		bTexture.loadTexUnit(3);
+		blendMap.loadTexUnit(4);
+		shadowMap.loadTexUnit(5);
+	}
+}

+ 0 - 0
src/main/java/eu/tankernn/gameEngine/shaders/terrainFragmentShader.glsl → src/main/java/eu/tankernn/gameEngine/renderEngine/terrain/terrainFragmentShader.glsl


+ 0 - 0
src/main/java/eu/tankernn/gameEngine/shaders/terrainVertexShader.glsl → src/main/java/eu/tankernn/gameEngine/renderEngine/terrain/terrainVertexShader.glsl


+ 76 - 78
src/main/java/eu/tankernn/gameEngine/shaders/ShaderProgram.java

@@ -1,113 +1,110 @@
 package eu.tankernn.gameEngine.shaders;
 
 import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.nio.FloatBuffer;
+import java.util.List;
 
+import org.apache.commons.lang3.ArrayUtils;
 import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL20;
-import org.lwjgl.BufferUtils;
-import org.lwjgl.util.vector.Matrix4f;
-import org.lwjgl.util.vector.Vector2f;
 import org.lwjgl.util.vector.Vector3f;
-import org.lwjgl.util.vector.Vector4f;
 
-public abstract class ShaderProgram {
+import eu.tankernn.gameEngine.entities.Light;
+
+public class ShaderProgram {
+
+	public static final int MAX_LIGHTS = 4;
+
 	private int programID;
-	private int vertexShaderID;
-	private int fragmentShaderID;
-	
-	private static FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16);
-	
-	public ShaderProgram(String vertexFile, String fragmentFile) {
-		vertexShaderID = loadShader(vertexFile, GL20.GL_VERTEX_SHADER);
-		fragmentShaderID = loadShader(fragmentFile, GL20.GL_FRAGMENT_SHADER);
+
+	protected UniformVec3[] lightPosition;
+	protected UniformVec3[] lightColor;
+	protected UniformVec3[] attenuation;
+
+	public ShaderProgram(String vertexFile, String fragmentFile, String... inVariables) {
+		int vertexShaderID = loadShader(vertexFile, GL20.GL_VERTEX_SHADER);
+		int fragmentShaderID = loadShader(fragmentFile, GL20.GL_FRAGMENT_SHADER);
 		programID = GL20.glCreateProgram();
 		GL20.glAttachShader(programID, vertexShaderID);
 		GL20.glAttachShader(programID, fragmentShaderID);
-		bindAttributes();
+		bindAttributes(inVariables);
 		GL20.glLinkProgram(programID);
-		GL20.glValidateProgram(programID);
-		getAllUniformLocations();
+		GL20.glDetachShader(programID, vertexShaderID);
+		GL20.glDetachShader(programID, fragmentShaderID);
+		GL20.glDeleteShader(vertexShaderID);
+		GL20.glDeleteShader(fragmentShaderID);
 	}
-	
-	protected abstract void getAllUniformLocations();
-	
-	protected int getUniformLocation(String uniformName) {
-		return GL20.glGetUniformLocation(programID, uniformName);
+
+	protected void getLightUniformLocations() {
+		lightPosition = new UniformVec3[MAX_LIGHTS];
+		lightColor = new UniformVec3[MAX_LIGHTS];
+		attenuation = new UniformVec3[MAX_LIGHTS];
+		for (int i = 0; i < MAX_LIGHTS; i++) {
+			lightPosition[i] = new UniformVec3("lightPosition[" + i + "]");
+			lightColor[i] = new UniformVec3("lightColor[" + i + "]");
+			attenuation[i] = new UniformVec3("attenuation[" + i + "]");
+		}
+	}
+
+	public void loadLights(List<Light> lights) {
+		for (int i = 0; i < MAX_LIGHTS; i++) {
+			if (i < lights.size()) {
+				lightPosition[i].loadVec3(lights.get(i).getPosition());
+				lightColor[i].loadVec3(lights.get(i).getColor());
+				attenuation[i].loadVec3(lights.get(i).getAttenuation());
+			} else {
+				lightPosition[i].loadVec3(new Vector3f(0, 0, 0));
+				lightColor[i].loadVec3(new Vector3f(0, 0, 0));
+				attenuation[i].loadVec3(new Vector3f(1, 0, 0));
+			}
+		}
 	}
-	
+
+	protected void storeAllUniformLocations(Uniform... uniforms) {
+		if (lightPosition != null)
+			uniforms = ArrayUtils.addAll(uniforms, lightPosition);
+		if (lightColor != null)
+			uniforms = ArrayUtils.addAll(uniforms, lightColor);
+		if (attenuation != null)
+			uniforms = ArrayUtils.addAll(uniforms, attenuation);
+
+		for (Uniform uniform : uniforms) {
+			uniform.storeUniformLocation(programID);
+		}
+		GL20.glValidateProgram(programID);
+	}
+
 	public void start() {
 		GL20.glUseProgram(programID);
 	}
-	
+
 	public void stop() {
 		GL20.glUseProgram(0);
 	}
-	
+
 	public void cleanUp() {
 		stop();
-		GL20.glDetachShader(programID, vertexShaderID);
-		GL20.glDetachShader(programID, fragmentShaderID);
-		GL20.glDeleteShader(vertexShaderID);
-		GL20.glDeleteShader(fragmentShaderID);
 		GL20.glDeleteProgram(programID);
 	}
-	
-	protected abstract void bindAttributes();
-	
-	protected void bindAttribute(int attribute, String variableName) {
-		GL20.glBindAttribLocation(programID, attribute, variableName);
-	}
-	
-	protected void loadFloat(int location, float value) {
-		GL20.glUniform1f(location, value);
-	}
-	
-	protected void loadInt(int location, int value) {
-		GL20.glUniform1i(location, value);
-	}
-	
-	protected void loadVector(int location, Vector4f vector) {
-		GL20.glUniform4f(location, vector.x, vector.y, vector.z, vector.w);
-	}
-	
-	protected void loadVector(int location, Vector3f vector) {
-		GL20.glUniform3f(location, vector.x, vector.y, vector.z);
-	}
-	
-	protected void load2DVector(int location, Vector2f vector) {
-		GL20.glUniform2f(location, vector.x, vector.y);
-	}
-	
-	protected void loadBoolean(int location, boolean value) {
-		float toLoad = 0;
-		if (value)
-			toLoad = 1;
-		GL20.glUniform1f(location, toLoad);
-	}
-	
-	protected void loadMatrix(int location, Matrix4f matrix) {
-		matrix.store(matrixBuffer);
-		matrixBuffer.flip();
-		GL20.glUniformMatrix4(location, false, matrixBuffer);
+
+	private void bindAttributes(String[] inVariables) {
+		for (int i = 0; i < inVariables.length; i++) {
+			GL20.glBindAttribLocation(programID, i, inVariables[i]);
+		}
 	}
-	
-	private static int loadShader(String file, int type) {
+
+	private int loadShader(String file, int type) {
 		StringBuilder shaderSource = new StringBuilder();
-		
 		try {
-			InputStream in = ShaderProgram.class.getResourceAsStream(file);
-			BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+			BufferedReader reader = new BufferedReader(
+					new InputStreamReader(ShaderProgram.class.getResourceAsStream(file)));
 			String line;
 			while ((line = reader.readLine()) != null) {
-				shaderSource.append(line).append('\n');
+				shaderSource.append(line).append("//\n");
 			}
 			reader.close();
-		} catch (IOException | NullPointerException e) {
-			System.err.println("Could not read file: " + file);
+		} catch (Exception e) {
+			System.err.println("Could not read file.");
 			e.printStackTrace();
 			System.exit(-1);
 		}
@@ -116,9 +113,10 @@ public abstract class ShaderProgram {
 		GL20.glCompileShader(shaderID);
 		if (GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE) {
 			System.out.println(GL20.glGetShaderInfoLog(shaderID, 500));
-			System.err.println("Could not compile shader.");
+			System.err.println("Could not compile shader " + file);
 			System.exit(-1);
 		}
 		return shaderID;
 	}
+
 }

+ 0 - 159
src/main/java/eu/tankernn/gameEngine/shaders/StaticShader.java

@@ -1,159 +0,0 @@
-package eu.tankernn.gameEngine.shaders;
-
-import java.util.List;
-
-import org.lwjgl.util.vector.Matrix4f;
-import org.lwjgl.util.vector.Vector2f;
-import org.lwjgl.util.vector.Vector3f;
-import org.lwjgl.util.vector.Vector4f;
-
-import eu.tankernn.gameEngine.entities.Camera;
-import eu.tankernn.gameEngine.entities.Light;
-import eu.tankernn.gameEngine.util.Maths;
-
-public class StaticShader extends ShaderProgram {
-	
-	private static final int MAX_LIGHTS = 4;
-	
-	private static final String VERTEX_FILE = "vertexShader.glsl";
-	private static final String FRAGMENT_FILE = "fragmentShader.glsl";
-	
-	private int location_transformationMatrix;
-	private int location_projecttionMatrix;
-	private int location_viewMatrix;
-	private int[] location_lightPosition;
-	private int[] location_lightColor;
-	private int[] location_attenuation;
-	private int location_shineDamper;
-	private int location_reflectivity;
-	private int location_useFakeLighting;
-	private int location_skyColor;
-	private int location_numberOfRows;
-	private int location_offset;
-	private int location_plane;
-	private int location_toShadowMapSpace;
-	private int location_shadowMap;
-	private int location_shadowDistance;
-	private int location_specularMap;
-	private int location_usesSpecularMap;
-	private int location_modelTexture;
-	private int location_cameraPosition;
-	private int location_enviroMap;
-	
-	public StaticShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
-	}
-	
-	@Override
-	protected void bindAttributes() {
-		super.bindAttribute(0, "position");
-		super.bindAttribute(1, "textureCoords");
-		super.bindAttribute(2, "normal");
-	}
-	
-	@Override
-	protected void getAllUniformLocations() {
-		location_transformationMatrix = super.getUniformLocation("transformationMatrix");
-		location_projecttionMatrix = super.getUniformLocation("projectionMatrix");
-		location_viewMatrix = super.getUniformLocation("viewMatrix");
-		location_shineDamper = super.getUniformLocation("shineDamper");
-		location_reflectivity = super.getUniformLocation("reflectivity");
-		location_useFakeLighting = super.getUniformLocation("useFakeLighting");
-		location_skyColor = super.getUniformLocation("skyColor");
-		location_numberOfRows = super.getUniformLocation("numberOfRows");
-		location_offset = super.getUniformLocation("offset");
-		location_plane = super.getUniformLocation("plane");
-		location_toShadowMapSpace = super.getUniformLocation("toShadowMapSpace");
-		location_shadowMap = super.getUniformLocation("shadowMap");
-		location_shadowDistance = super.getUniformLocation("shadowDistance");
-		location_specularMap = super.getUniformLocation("specularMap");
-		location_usesSpecularMap = super.getUniformLocation("usesSpecularMap");
-		location_modelTexture = super.getUniformLocation("modelTexture");
-		location_cameraPosition = super.getUniformLocation("cameraPosition");
-		location_enviroMap = super.getUniformLocation("enviroMap");
-		
-		location_lightPosition = new int[MAX_LIGHTS];
-		location_lightColor = new int[MAX_LIGHTS];
-		location_attenuation = new int[MAX_LIGHTS];
-		for (int i = 0; i < MAX_LIGHTS; i++) {
-			location_lightPosition[i] = super.getUniformLocation("lightPosition[" + i + "]");
-			location_lightColor[i] = super.getUniformLocation("lightColor[" + i + "]");
-			location_attenuation[i] = super.getUniformLocation("attenuation[" + i + "]");
-		}
-	}
-	
-	public void connectTextureUnits() {
-		super.loadInt(location_shadowMap, 5);
-		super.loadInt(location_modelTexture, 0);
-		super.loadInt(location_specularMap, 1);
-		super.loadInt(location_enviroMap, 10);
-	}
-	
-	public void loadUseSpecularMap(boolean useSpecularMap) {
-		super.loadBoolean(location_usesSpecularMap, useSpecularMap);
-	}
-	
-	public void loadShadowDistance(float distance) {
-		super.loadFloat(location_shadowDistance, distance);
-	}
-	
-	public void loadToShadowSpaceMatrix(Matrix4f matrix) {
-		super.loadMatrix(location_toShadowMapSpace, matrix);
-	}
-	
-	public void loadClipPlane(Vector4f plane) {
-		super.loadVector(location_plane, plane);
-	}
-	
-	public void loadNumberOfRows(int numberOfRows) {
-		super.loadFloat(location_numberOfRows, numberOfRows);
-	}
-	
-	public void loadOffset(float x, float y) {
-		super.load2DVector(location_offset, new Vector2f(x, y));
-	}
-	
-	public void loadSkyColor(float r, float g, float b) {
-		super.loadVector(location_skyColor, new Vector3f(r, g, b));
-	}
-	
-	public void loadFakeLightingVariable(boolean useFake) {
-		super.loadBoolean(location_useFakeLighting, useFake);
-	}
-	
-	public void loadShineVariables(float damper, float reflectivity) {
-		super.loadFloat(location_shineDamper, damper);
-		super.loadFloat(location_reflectivity, reflectivity);
-	}
-	
-	public void loadTransformationMatrix(Matrix4f matrix) {
-		super.loadMatrix(location_transformationMatrix, matrix);
-	}
-	
-	public void loadCameraPosition(Vector3f vector) {
-		super.loadVector(location_cameraPosition, vector);
-	}
-	
-	public void loadLights(List<Light> lights) {
-		for (int i = 0; i < MAX_LIGHTS; i++) {
-			if (i < lights.size()) {
-				super.loadVector(location_lightPosition[i], lights.get(i).getPosition());
-				super.loadVector(location_lightColor[i], lights.get(i).getColor());
-				super.loadVector(location_attenuation[i], lights.get(i).getAttenuation());
-			} else {
-				super.loadVector(location_lightPosition[i], new Vector3f(0, 0, 0));
-				super.loadVector(location_lightColor[i], new Vector3f(0, 0, 0));
-				super.loadVector(location_attenuation[i], new Vector3f(1, 0, 0));
-			}
-		}
-	}
-	
-	public void loadViewMatrix(Camera camera) {
-		Matrix4f viewMatrix = Maths.createViewMatrix(camera);
-		super.loadMatrix(location_viewMatrix, viewMatrix);
-	}
-	
-	public void loadProjectionMatrix(Matrix4f projection) {
-		super.loadMatrix(location_projecttionMatrix, projection);
-	}
-}

+ 0 - 140
src/main/java/eu/tankernn/gameEngine/shaders/TerrainShader.java

@@ -1,140 +0,0 @@
-package eu.tankernn.gameEngine.shaders;
-
-import java.util.List;
-
-import org.lwjgl.util.vector.Matrix4f;
-import org.lwjgl.util.vector.Vector3f;
-import org.lwjgl.util.vector.Vector4f;
-
-import eu.tankernn.gameEngine.entities.Camera;
-import eu.tankernn.gameEngine.entities.Light;
-import eu.tankernn.gameEngine.util.Maths;
-
-public class TerrainShader extends ShaderProgram {
-	
-	private static final int MAX_LIGHTS = 4;
-	
-	private static final String VERTEX_FILE = "terrainVertexShader.glsl";
-	private static final String FRAGMENT_FILE = "terrainFragmentShader.glsl";
-	
-	private int location_transformationMatrix;
-	private int location_projecttionMatrix;
-	private int location_viewMatrix;
-	private int[] location_lightPosition;
-	private int[] location_lightColor;
-	private int[] location_attenuation;
-	private int location_shineDamper;
-	private int location_reflectivity;
-	private int location_skyColor;
-	private int location_backgroundTexture;
-	private int location_rTexture;
-	private int location_gTexture;
-	private int location_bTexture;
-	private int location_blendMap;
-	private int location_plane;
-	private int location_toShadowMapSpace;
-	private int location_shadowMap;
-	private int location_shadowDistance;
-	private int location_shadowMapSize;
-	
-	public TerrainShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
-	}
-
-	@Override
-	protected void bindAttributes() {
-		super.bindAttribute(0, "position");
-		super.bindAttribute(1, "textureCoords");
-		super.bindAttribute(2, "normal");
-	}
-
-	@Override
-	protected void getAllUniformLocations() {
-		location_transformationMatrix = super.getUniformLocation("transformationMatrix");
-		location_projecttionMatrix = super.getUniformLocation("projectionMatrix");
-		location_viewMatrix = super.getUniformLocation("viewMatrix");
-		location_shineDamper = super.getUniformLocation("shineDamper");
-		location_reflectivity = super.getUniformLocation("reflectivity");
-		location_skyColor = super.getUniformLocation("skyColor");
-		location_backgroundTexture = super.getUniformLocation("backgroundTexture");
-		location_rTexture = super.getUniformLocation("rTexture");
-		location_gTexture = super.getUniformLocation("gTexture");
-		location_bTexture = super.getUniformLocation("bTexture");
-		location_blendMap = super.getUniformLocation("blendMap");
-		location_plane = super.getUniformLocation("plane");
-		location_toShadowMapSpace = super.getUniformLocation("toShadowMapSpace");
-		location_shadowMap = super.getUniformLocation("shadowMap");
-		location_shadowDistance = super.getUniformLocation("shadowDistance");
-		location_shadowMapSize = super.getUniformLocation("shadowMapSize");
-		
-		location_lightPosition = new int[MAX_LIGHTS];
-		location_lightColor = new int[MAX_LIGHTS];
-		location_attenuation = new int[MAX_LIGHTS];
-		for (int i = 0; i < MAX_LIGHTS; i++) {
-			location_lightPosition[i] = super.getUniformLocation("lightPosition[" + i + "]");
-			location_lightColor[i] = super.getUniformLocation("lightColor[" + i + "]");
-			location_attenuation[i] = super.getUniformLocation("attenuation[" + i + "]");
-		}
-	}
-	
-	public void connectTextureUnits() {
-		super.loadInt(location_backgroundTexture, 0);
-		super.loadInt(location_rTexture, 1);
-		super.loadInt(location_gTexture, 2);
-		super.loadInt(location_bTexture, 3);
-		super.loadInt(location_blendMap, 4);
-		super.loadInt(location_shadowMap, 5);
-	}
-	
-	public void loadShadowMapSize(float size) {
-		super.loadFloat(location_shadowMapSize, size);
-	}
-	
-	public void loadShadowDistance(float distance) {
-		super.loadFloat(location_shadowDistance, distance);
-	}
-	
-	public void loadToShadowSpaceMatrix(Matrix4f matrix) {
-		super.loadMatrix(location_toShadowMapSpace, matrix);
-	}
-	
-	public void loadClipPlane(Vector4f plane) {
-		super.loadVector(location_plane, plane);
-	}
-	
-	public void loadSkyColor(float r, float g, float b) {
-		super.loadVector(location_skyColor, new Vector3f(r, g, b));
-	}
-	
-	public void loadShineVariables(float damper, float reflectivity) {
-		super.loadFloat(location_shineDamper, damper);
-		super.loadFloat(location_reflectivity, reflectivity);
-	}
-	
-	public void loadTransformationMatrix(Matrix4f matrix) {
-		super.loadMatrix(location_transformationMatrix, matrix);
-	}
-	
-	public void loadLights(List<Light> lights) {
-		for (int i = 0; i < MAX_LIGHTS; i++) {
-			if (i < lights.size()) {
-				super.loadVector(location_lightPosition[i], lights.get(i).getPosition());
-				super.loadVector(location_lightColor[i], lights.get(i).getColor());
-				super.loadVector(location_attenuation[i], lights.get(i).getAttenuation());
-			} else {
-				super.loadVector(location_lightPosition[i], new Vector3f(0, 0, 0));
-				super.loadVector(location_lightColor[i], new Vector3f(0, 0, 0));
-				super.loadVector(location_attenuation[i], new Vector3f(1, 0, 0));
-			}
-		}
-	}
-	
-	public void loadViewMatrix(Camera camera) {
-		Matrix4f viewMatrix = Maths.createViewMatrix(camera);
-		super.loadMatrix(location_viewMatrix, viewMatrix);
-	}
-	
-	public void loadProjectionMatrix(Matrix4f projection) {
-		super.loadMatrix(location_projecttionMatrix, projection);
-	}
-}

+ 35 - 0
src/main/java/eu/tankernn/gameEngine/shaders/Uniform.java

@@ -0,0 +1,35 @@
+package eu.tankernn.gameEngine.shaders;
+
+import org.lwjgl.opengl.GL20;
+
+public abstract class Uniform {
+	
+	private static final int NOT_FOUND = -1;
+	
+	private String name;
+	private int location;
+	protected boolean used = false;
+	
+	protected Uniform(String name){
+		this.name = name;
+	}
+	
+	protected void storeUniformLocation(int programID){
+		location = GL20.glGetUniformLocation(programID, name);
+		if(location == NOT_FOUND){
+			System.err.println("No uniform variable called " + name + " found for program " + programID + "!");
+		}
+	}
+	
+	protected int getLocation(){
+		return location;
+	}
+	
+	protected boolean isUsed() {
+		return used;
+	}
+	
+	protected String getName() {
+		return name;
+	}
+}

+ 21 - 0
src/main/java/eu/tankernn/gameEngine/shaders/UniformBoolean.java

@@ -0,0 +1,21 @@
+package eu.tankernn.gameEngine.shaders;
+
+import org.lwjgl.opengl.GL20;
+
+public class UniformBoolean extends Uniform{
+
+	private boolean currentBool;
+	
+	public UniformBoolean(String name){
+		super(name);
+	}
+	
+	public void loadBoolean(boolean bool){
+		if(!used || currentBool != bool){
+			GL20.glUniform1f(super.getLocation(), bool ? 1f : 0f);
+			used = true;
+			currentBool = bool;
+		}
+	}
+	
+}

+ 21 - 0
src/main/java/eu/tankernn/gameEngine/shaders/UniformFloat.java

@@ -0,0 +1,21 @@
+package eu.tankernn.gameEngine.shaders;
+
+import org.lwjgl.opengl.GL20;
+
+public class UniformFloat extends Uniform{
+	
+	private float currentValue;
+	
+	public UniformFloat(String name){
+		super(name);
+	}
+	
+	public void loadFloat(float value){
+		if(!used || currentValue!=value){
+			GL20.glUniform1f(super.getLocation(), value);
+			used = true;
+			currentValue = value;
+		}
+	}
+
+}

+ 24 - 0
src/main/java/eu/tankernn/gameEngine/shaders/UniformMatrix.java

@@ -0,0 +1,24 @@
+package eu.tankernn.gameEngine.shaders;
+
+import java.nio.FloatBuffer;
+
+import org.lwjgl.BufferUtils;
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.util.vector.Matrix4f;
+
+public class UniformMatrix extends Uniform{
+	
+	private static FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16);
+
+	public UniformMatrix(String name) {
+		super(name);
+	}
+	
+	public void loadMatrix(Matrix4f matrix){
+		this.used = true;
+		matrix.store(matrixBuffer);
+		matrixBuffer.flip();
+		GL20.glUniformMatrix4(super.getLocation(), false, matrixBuffer);
+	}
+
+}

+ 21 - 0
src/main/java/eu/tankernn/gameEngine/shaders/UniformSampler.java

@@ -0,0 +1,21 @@
+package eu.tankernn.gameEngine.shaders;
+
+import org.lwjgl.opengl.GL20;
+
+public class UniformSampler extends Uniform {
+
+	private int currentValue;
+
+	public UniformSampler(String name) {
+		super(name);
+	}
+
+	public void loadTexUnit(int texUnit) {
+		if (!used || currentValue != texUnit) {
+			GL20.glUniform1i(super.getLocation(), texUnit);
+			used = true;
+			currentValue = texUnit;
+		}
+	}
+
+}

+ 28 - 0
src/main/java/eu/tankernn/gameEngine/shaders/UniformVec2.java

@@ -0,0 +1,28 @@
+package eu.tankernn.gameEngine.shaders;
+
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.util.vector.Vector2f;
+
+public class UniformVec2 extends Uniform {
+
+	private float currentX;
+	private float currentY;
+
+	public UniformVec2(String name) {
+		super(name);
+	}
+
+	public void loadVec2(Vector2f vector) {
+		loadVec2(vector.x, vector.y);
+	}
+
+	public void loadVec2(float x, float y) {
+		if (!used || x != currentX || y != currentY) {
+			this.currentX = x;
+			this.currentY = y;
+			used = true;
+			GL20.glUniform2f(super.getLocation(), x, y);
+		}
+	}
+
+}

+ 29 - 0
src/main/java/eu/tankernn/gameEngine/shaders/UniformVec3.java

@@ -0,0 +1,29 @@
+package eu.tankernn.gameEngine.shaders;
+
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.util.vector.Vector3f;
+
+public class UniformVec3 extends Uniform {
+	private float currentX;
+	private float currentY;
+	private float currentZ;
+
+	public UniformVec3(String name) {
+		super(name);
+	}
+
+	public void loadVec3(Vector3f vector) {
+		loadVec3(vector.x, vector.y, vector.z);
+	}
+
+	public void loadVec3(float x, float y, float z) {
+		if (!used || x != currentX || y != currentY || z != currentZ) {
+			this.currentX = x;
+			this.currentY = y;
+			this.currentZ = z;
+			used = true;
+			GL20.glUniform3f(super.getLocation(), x, y, z);
+		}
+	}
+
+}

+ 21 - 0
src/main/java/eu/tankernn/gameEngine/shaders/UniformVec4.java

@@ -0,0 +1,21 @@
+package eu.tankernn.gameEngine.shaders;
+
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.util.vector.Vector4f;
+
+public class UniformVec4 extends Uniform {
+
+	public UniformVec4(String name) {
+		super(name);
+	}
+
+	public void loadVec4(Vector4f vector) {
+		loadVec4(vector.x, vector.y, vector.z, vector.w);
+	}
+
+	public void loadVec4(float x, float y, float z, float w) {
+		this.used = true;
+		GL20.glUniform4f(super.getLocation(), x, y, z, w);
+	}
+
+}

+ 15 - 0
src/main/java/eu/tankernn/gameEngine/shaders/UniformViewMatrix.java

@@ -0,0 +1,15 @@
+package eu.tankernn.gameEngine.shaders;
+
+import eu.tankernn.gameEngine.util.ICamera;
+
+public class UniformViewMatrix extends UniformMatrix {
+
+	public UniformViewMatrix(String name) {
+		super(name);
+	}
+	
+	public void loadCamera(ICamera camera) {
+		super.loadMatrix(camera.getViewMatrix());
+	}
+
+}

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/shadows/ShadowMapEntityRenderer.java

@@ -90,7 +90,7 @@ public class ShadowMapEntityRenderer {
 		Matrix4f modelMatrix = Maths.createTransformationMatrix(entity.getPosition(),
 				entity.getRotX(), entity.getRotY(), entity.getRotZ(), entity.getScale());
 		Matrix4f mvpMatrix = Matrix4f.mul(projectionViewMatrix, modelMatrix, null);
-		shader.loadMvpMatrix(mvpMatrix);
+		shader.mvpMatrix.loadMatrix(mvpMatrix);
 	}
 
 }

+ 4 - 20
src/main/java/eu/tankernn/gameEngine/shadows/ShadowShader.java

@@ -1,34 +1,18 @@
 package eu.tankernn.gameEngine.shadows;
 
-import org.lwjgl.util.vector.Matrix4f;
-
 import eu.tankernn.gameEngine.shaders.ShaderProgram;
+import eu.tankernn.gameEngine.shaders.UniformMatrix;
 
 public class ShadowShader extends ShaderProgram {
 	
 	private static final String VERTEX_FILE = "/eu/tankernn/gameEngine/shadows/shadowVertexShader.glsl";
 	private static final String FRAGMENT_FILE = "/eu/tankernn/gameEngine/shadows/shadowFragmentShader.glsl";
 	
-	private int location_mvpMatrix;
+	protected UniformMatrix mvpMatrix = new UniformMatrix("mvpMatrix");
 	
 	protected ShadowShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
-	}
-	
-	@Override
-	protected void getAllUniformLocations() {
-		location_mvpMatrix = super.getUniformLocation("mvpMatrix");
-		
-	}
-	
-	protected void loadMvpMatrix(Matrix4f mvpMatrix) {
-		super.loadMatrix(location_mvpMatrix, mvpMatrix);
-	}
-	
-	@Override
-	protected void bindAttributes() {
-		super.bindAttribute(0, "in_position");
-		super.bindAttribute(1, "in_textureCoords");
+		super(VERTEX_FILE, FRAGMENT_FILE, "in_position", "in_textureCoords");
+		super.storeAllUniformLocations(mvpMatrix);
 	}
 	
 }

+ 23 - 0
src/main/java/eu/tankernn/gameEngine/skybox/CubeGenerator.java

@@ -0,0 +1,23 @@
+package eu.tankernn.gameEngine.skybox;
+
+import eu.tankernn.gameEngine.renderEngine.Vao;
+
+public class CubeGenerator {
+
+	private static final int VERTEX_COUNT = 8;
+	private static final int[] INDICES = { 0, 1, 3, 1, 2, 3, 1, 5, 2, 2, 5, 6, 4, 7, 5, 5, 7, 6, 0,
+			3, 4, 4, 3, 7, 7, 3, 6, 6, 3, 2, 4, 5, 0, 0, 5, 1 };
+
+	public static Vao generateCube(float size) {
+		Vao vao = Vao.create();
+		vao.storeData(INDICES, VERTEX_COUNT, getVertexPositions(size));
+		return vao;
+	}
+
+	private static float[] getVertexPositions(float size) {
+		return new float[] { -size, size, size, size, size, size, size, -size, size, -size, -size,
+				size, -size, size, -size, size, size, -size, size, -size, -size, -size, -size,
+				-size };
+	}
+
+}

+ 0 - 70
src/main/java/eu/tankernn/gameEngine/skybox/CubeMap.java

@@ -1,70 +0,0 @@
-package eu.tankernn.gameEngine.skybox;
-
-import eu.tankernn.gameEngine.models.RawModel;
-import eu.tankernn.gameEngine.renderEngine.Loader;
-
-public class CubeMap {
-	
-	private static final float SIZE = 500f;
-	
-	private static final float[] VERTICES = {        
-	    -SIZE,  SIZE, -SIZE,
-	    -SIZE, -SIZE, -SIZE,
-	    SIZE, -SIZE, -SIZE,
-	     SIZE, -SIZE, -SIZE,
-	     SIZE,  SIZE, -SIZE,
-	    -SIZE,  SIZE, -SIZE,
-
-	    -SIZE, -SIZE,  SIZE,
-	    -SIZE, -SIZE, -SIZE,
-	    -SIZE,  SIZE, -SIZE,
-	    -SIZE,  SIZE, -SIZE,
-	    -SIZE,  SIZE,  SIZE,
-	    -SIZE, -SIZE,  SIZE,
-
-	     SIZE, -SIZE, -SIZE,
-	     SIZE, -SIZE,  SIZE,
-	     SIZE,  SIZE,  SIZE,
-	     SIZE,  SIZE,  SIZE,
-	     SIZE,  SIZE, -SIZE,
-	     SIZE, -SIZE, -SIZE,
-
-	    -SIZE, -SIZE,  SIZE,
-	    -SIZE,  SIZE,  SIZE,
-	     SIZE,  SIZE,  SIZE,
-	     SIZE,  SIZE,  SIZE,
-	     SIZE, -SIZE,  SIZE,
-	    -SIZE, -SIZE,  SIZE,
-
-	    -SIZE,  SIZE, -SIZE,
-	     SIZE,  SIZE, -SIZE,
-	     SIZE,  SIZE,  SIZE,
-	     SIZE,  SIZE,  SIZE,
-	    -SIZE,  SIZE,  SIZE,
-	    -SIZE,  SIZE, -SIZE,
-
-	    -SIZE, -SIZE, -SIZE,
-	    -SIZE, -SIZE,  SIZE,
-	     SIZE, -SIZE, -SIZE,
-	     SIZE, -SIZE, -SIZE,
-	    -SIZE, -SIZE,  SIZE,
-	     SIZE, -SIZE,  SIZE
-	};
-	
-	private RawModel cube;
-	private int texture;
-	
-	public CubeMap(String[] textureFiles, String folder, Loader loader){
-		cube = loader.loadToVAO(VERTICES);
-		texture = loader.loadCubeMap(textureFiles, folder);
-	}
-	
-	public RawModel getCube(){
-		return cube;
-	}
-	
-	public int getTexture(){
-		return texture;
-	}
-
-}

+ 34 - 0
src/main/java/eu/tankernn/gameEngine/skybox/Skybox.java

@@ -0,0 +1,34 @@
+package eu.tankernn.gameEngine.skybox;
+
+import eu.tankernn.gameEngine.renderEngine.Vao;
+import eu.tankernn.gameEngine.textures.Texture;
+
+public class Skybox {
+	
+	private Vao cube;
+	private Texture dayTexture, nightTexture;
+	
+	public Skybox(Texture dayTexture, Texture nightTexture, float size){
+		cube = CubeGenerator.generateCube(size);
+		this.dayTexture = dayTexture;
+		this.nightTexture = nightTexture;
+	}
+	
+	public Vao getCubeVao(){
+		return cube;
+	}
+	
+	public Texture getDayTexture(){
+		return dayTexture;
+	}
+	
+	public Texture getNightTexture(){
+		return nightTexture;
+	}
+	
+	public void delete(){
+		cube.delete();
+		dayTexture.delete();
+	}
+
+}

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

@@ -1,40 +1,43 @@
 package eu.tankernn.gameEngine.skybox;
 
 import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GL13;
 import org.lwjgl.opengl.GL20;
 import org.lwjgl.opengl.GL30;
 import org.lwjgl.util.vector.Matrix4f;
 
-import eu.tankernn.gameEngine.entities.Camera;
 import eu.tankernn.gameEngine.renderEngine.DisplayManager;
 import eu.tankernn.gameEngine.renderEngine.Loader;
+import eu.tankernn.gameEngine.renderEngine.Vao;
+import eu.tankernn.gameEngine.textures.Texture;
+import eu.tankernn.gameEngine.util.ICamera;
 
 public class SkyboxRenderer {
 	private static final int DAY_LENGTH = 24000;
 	
-	private CubeMap dayCube, nightCube;
+	private Skybox skybox;
 	private SkyboxShader shader;
 	private float time = 0;
 	
-	public SkyboxRenderer(Loader loader, Matrix4f projectionmatrix, String[] dayTextureFiles, String[] nightTextureFiles) {
-		dayCube = new CubeMap(dayTextureFiles, "skybox/", loader);
-		nightCube = new CubeMap(nightTextureFiles, "skybox/", loader);
+	public SkyboxRenderer(Loader loader, Matrix4f projectionmatrix, Skybox skybox) {
+		this.skybox = skybox;
 		shader = new SkyboxShader();
 		shader.start();
 		shader.connectTextureUnits();
-		shader.loadProjectionMatrix(projectionmatrix);
+		shader.projectionMatrix.loadMatrix(projectionmatrix);
 		shader.stop();
 	}
 	
-	public void render(Camera camera, float r, float g, float b) {
+	public void render(ICamera camera, float r, float g, float b) {
 		shader.start();
 		shader.loadViewMatrix(camera);
-		shader.loadFogColor(r, g, b);
-		GL30.glBindVertexArray(dayCube.getCube().getVaoID());
+		shader.fogColor.loadVec3(r, g, b);
+		skybox.getCubeVao().bind();
 		GL20.glEnableVertexAttribArray(0);
 		bindTextures();
-		GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, dayCube.getCube().getVertexCount());
+		Vao model = skybox.getCubeVao();
+		model.bind(0);
+		GL11.glDrawElements(GL11.GL_TRIANGLES, model.getIndexCount(), GL11.GL_UNSIGNED_INT, 0);
+		model.unbind(0);
 		GL20.glDisableVertexAttribArray(0);
 		GL30.glBindVertexArray(0);
 		shader.stop();
@@ -48,35 +51,29 @@ public class SkyboxRenderer {
 		int noon = (int) (DAY_LENGTH / 3);
 		int evening = (int) (DAY_LENGTH / 1.14);
 		
-		int texture1;
-		int texture2;
+		Texture texture1;
+		Texture texture2;
 		float blendFactor;
 		if (time >= 0 && time < morning) {
-			texture1 = nightCube.getTexture();
-			texture2 = nightCube.getTexture();
+			texture1 = skybox.getNightTexture();
+			texture2 = skybox.getNightTexture();
 			blendFactor = (time - 0) / (morning - 0);
 		} else if (time >= morning && time < noon) {
-			texture1 = nightCube.getTexture();
-			texture2 = dayCube.getTexture();
+			texture1 = skybox.getNightTexture();
+			texture2 = skybox.getDayTexture();
 			blendFactor = (time - morning) / (noon - morning);
 		} else if (time >= noon && time < evening) {
-			texture1 = dayCube.getTexture();
-			texture2 = dayCube.getTexture();
+			texture1 = skybox.getDayTexture();
+			texture2 = skybox.getDayTexture();
 			blendFactor = (time - noon) / (evening - noon);
 		} else {
-			texture1 = dayCube.getTexture();
-			texture2 = nightCube.getTexture();
+			texture1 = skybox.getDayTexture();
+			texture2 = skybox.getNightTexture();
 			blendFactor = (time - evening) / (DAY_LENGTH - evening);
 		}
 		
-		GL13.glActiveTexture(GL13.GL_TEXTURE0);
-		GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texture1);
-		GL13.glActiveTexture(GL13.GL_TEXTURE1);
-		GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texture2);
-		shader.loadBlendFactor(blendFactor);
-	}
-	
-	public CubeMap getCubeMap() {
-		return dayCube;
+		texture1.bindToUnit(0);
+		texture2.bindToUnit(1);
+		shader.blendFactor.loadFloat(blendFactor);
 	}
 }

+ 18 - 41
src/main/java/eu/tankernn/gameEngine/skybox/SkyboxShader.java

@@ -3,10 +3,13 @@ package eu.tankernn.gameEngine.skybox;
 import org.lwjgl.util.vector.Matrix4f;
 import org.lwjgl.util.vector.Vector3f;
 
-import eu.tankernn.gameEngine.entities.Camera;
 import eu.tankernn.gameEngine.renderEngine.DisplayManager;
 import eu.tankernn.gameEngine.shaders.ShaderProgram;
-import eu.tankernn.gameEngine.util.Maths;
+import eu.tankernn.gameEngine.shaders.UniformFloat;
+import eu.tankernn.gameEngine.shaders.UniformMatrix;
+import eu.tankernn.gameEngine.shaders.UniformSampler;
+import eu.tankernn.gameEngine.shaders.UniformVec3;
+import eu.tankernn.gameEngine.util.ICamera;
 
 public class SkyboxShader extends ShaderProgram {
 	
@@ -15,59 +18,33 @@ public class SkyboxShader extends ShaderProgram {
 	
 	private static final float ROTATE_SPEED = 1f;
 	
-	private int location_projectionMatrix;
-	private int location_viewMatrix;
-	private int location_fogColor;
-	private int location_cubeMap;
-	private int location_cubeMap2;
-	private int location_blendFactor;
+	protected UniformMatrix projectionMatrix = new UniformMatrix("projectionMatrix");
+	protected UniformMatrix viewMatrix = new UniformMatrix("viewMatrix");
+	protected UniformVec3 fogColor = new UniformVec3("fogColor");
+	protected UniformSampler cubeMap = new UniformSampler("cubeMap");
+	protected UniformSampler cubeMap2 = new UniformSampler("cubeMap2");
+	protected UniformFloat blendFactor = new UniformFloat("blendFactor");
 	
 	private float rotation = 0;
 	
 	public SkyboxShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
+		super(VERTEX_FILE, FRAGMENT_FILE, "position");
+		super.storeAllUniformLocations(projectionMatrix, viewMatrix, fogColor, cubeMap, cubeMap2, blendFactor);
 	}
 	
-	public void loadProjectionMatrix(Matrix4f matrix) {
-		super.loadMatrix(location_projectionMatrix, matrix);
-	}
-	
-	public void loadViewMatrix(Camera camera) {
-		Matrix4f matrix = Maths.createViewMatrix(camera);
+	public void loadViewMatrix(ICamera camera) {
+		Matrix4f matrix = camera.getViewMatrix();
 		matrix.m30 = 0;
 		matrix.m31 = 0;
 		matrix.m32 = 0;
 		rotation += ROTATE_SPEED * DisplayManager.getFrameTimeSeconds();
 		Matrix4f.rotate((float) Math.toRadians(rotation), new Vector3f(0, 1, 0), matrix, matrix);
-		super.loadMatrix(location_viewMatrix, matrix);
-	}
-	
-	public void loadFogColor(float r, float g, float b) {
-		super.loadVector(location_fogColor, new Vector3f(r, g, b));
+		viewMatrix.loadMatrix(matrix);
 	}
 	
 	public void connectTextureUnits() {
-		super.loadInt(location_cubeMap, 0);
-		super.loadInt(location_cubeMap2, 1);
-	}
-	
-	public void loadBlendFactor(float blend) {
-		super.loadFloat(location_blendFactor, blend);
-	}
-	
-	@Override
-	protected void getAllUniformLocations() {
-		location_projectionMatrix = super.getUniformLocation("projectionMatrix");
-		location_viewMatrix = super.getUniformLocation("viewMatrix");
-		location_fogColor = super.getUniformLocation("fogColor");
-		location_cubeMap = super.getUniformLocation("cubeMap");
-		location_cubeMap2 = super.getUniformLocation("cubeMap2");
-		location_blendFactor = super.getUniformLocation("blendFactor");
-	}
-	
-	@Override
-	protected void bindAttributes() {
-		super.bindAttribute(0, "position");
+		cubeMap.loadTexUnit(0);
+		cubeMap2.loadTexUnit(1);
 	}
 	
 }

+ 50 - 0
src/main/java/eu/tankernn/gameEngine/textures/Texture.java

@@ -0,0 +1,50 @@
+package eu.tankernn.gameEngine.textures;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL13;
+
+import eu.tankernn.gameEngine.util.MyFile;
+
+
+public class Texture {
+
+	public final int textureId;
+	public final int size;
+	private final int type;
+
+	protected Texture(int textureId, int size) {
+		this.textureId = textureId;
+		this.size = size;
+		this.type = GL11.GL_TEXTURE_2D;
+	}
+
+	protected Texture(int textureId, int type, int size) {
+		this.textureId = textureId;
+		this.size = size;
+		this.type = type;
+	}
+
+	public void bindToUnit(int unit) {
+		GL13.glActiveTexture(GL13.GL_TEXTURE0 + unit);
+		GL11.glBindTexture(type, textureId);
+	}
+
+	public void delete() {
+		GL11.glDeleteTextures(textureId);
+	}
+
+	public static TextureBuilder newTexture(MyFile textureFile) {
+		return new TextureBuilder(textureFile);
+	}
+
+	public static Texture newCubeMap(MyFile[] textureFiles, int size) {
+		int cubeMapId = TextureUtils.loadCubeMap(textureFiles);
+		return new Texture(cubeMapId, GL13.GL_TEXTURE_CUBE_MAP, size);
+	}
+	
+	public static Texture newEmptyCubeMap(int size) {
+		int cubeMapId = TextureUtils.createEmptyCubeMap(size);
+		return new Texture(cubeMapId, GL13.GL_TEXTURE_CUBE_MAP, size);
+	}
+
+}

+ 64 - 0
src/main/java/eu/tankernn/gameEngine/textures/TextureBuilder.java

@@ -0,0 +1,64 @@
+package eu.tankernn.gameEngine.textures;
+
+import eu.tankernn.gameEngine.util.MyFile;
+
+public class TextureBuilder {
+	
+	private boolean clampEdges = false;
+	private boolean mipmap = false;
+	private boolean anisotropic = true;
+	private boolean nearest = false;
+	
+	private MyFile file;
+	
+	protected TextureBuilder(MyFile textureFile){
+		this.file = textureFile;
+	}
+	
+	public Texture create(){
+		TextureData textureData = TextureUtils.decodeTextureFile(file);
+		int textureId = TextureUtils.loadTextureToOpenGL(textureData, this);
+		return new Texture(textureId, textureData.getWidth());
+	}
+	
+	public TextureBuilder clampEdges(){
+		this.clampEdges = true;
+		return this;
+	}
+	
+	public TextureBuilder normalMipMap(){
+		this.mipmap = true;
+		this.anisotropic = false;
+		return this;
+	}
+	
+	public TextureBuilder nearestFiltering(){
+		this.mipmap = false;
+		this.anisotropic = false;
+		this.nearest = true;
+		return this;
+	}
+	
+	public TextureBuilder anisotropic(){
+		this.mipmap = true;
+		this.anisotropic = true;
+		return this;
+	}
+	
+	protected boolean isClampEdges() {
+		return clampEdges;
+	}
+
+	protected boolean isMipmap() {
+		return mipmap;
+	}
+
+	protected boolean isAnisotropic() {
+		return anisotropic;
+	}
+
+	protected boolean isNearest() {
+		return nearest;
+	}
+
+}

+ 24 - 24
src/main/java/eu/tankernn/gameEngine/textures/TextureData.java

@@ -3,27 +3,27 @@ package eu.tankernn.gameEngine.textures;
 import java.nio.ByteBuffer;
 
 public class TextureData {
-     
-    private int width;
-    private int height;
-    private ByteBuffer buffer;
-     
-    public TextureData(ByteBuffer buffer, int width, int height){
-        this.buffer = buffer;
-        this.width = width;
-        this.height = height;
-    }
-     
-    public int getWidth(){
-        return width;
-    }
-     
-    public int getHeight(){
-        return height;
-    }
-     
-    public ByteBuffer getBuffer(){
-        return buffer;
-    }
- 
-}
+	
+	private int width;
+	private int height;
+	private ByteBuffer buffer;
+	
+	public TextureData(ByteBuffer buffer, int width, int height){
+		this.buffer = buffer;
+		this.width = width;
+		this.height = height;
+	}
+	
+	public int getWidth(){
+		return width;
+	}
+	
+	public int getHeight(){
+		return height;
+	}
+	
+	public ByteBuffer getBuffer(){
+		return buffer;
+	}
+
+}

+ 109 - 0
src/main/java/eu/tankernn/gameEngine/textures/TextureUtils.java

@@ -0,0 +1,109 @@
+package eu.tankernn.gameEngine.textures;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+import org.lwjgl.opengl.EXTTextureFilterAnisotropic;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL12;
+import org.lwjgl.opengl.GL13;
+import org.lwjgl.opengl.GL14;
+import org.lwjgl.opengl.GL30;
+import org.lwjgl.opengl.GLContext;
+
+import de.matthiasmann.twl.utils.PNGDecoder;
+import de.matthiasmann.twl.utils.PNGDecoder.Format;
+import eu.tankernn.gameEngine.util.MyFile;
+
+public class TextureUtils {
+
+	public static int createEmptyCubeMap(int size) {
+		int texID = GL11.glGenTextures();
+		GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texID);
+		for (int i = 0; i < 6; i++) {
+			GL11.glTexImage2D(GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL11.GL_RGBA8, size, size, 0, GL11.GL_RGBA,
+					GL11.GL_UNSIGNED_BYTE, (ByteBuffer)null);
+		}
+		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_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
+		GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
+		GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL12.GL_TEXTURE_WRAP_R, GL12.GL_CLAMP_TO_EDGE);
+		GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, 0);
+		return texID;
+	}
+
+	public static int loadCubeMap(MyFile[] textureFiles) {
+		int texID = GL11.glGenTextures();
+		GL13.glActiveTexture(GL13.GL_TEXTURE0);
+		GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texID);
+		GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
+		for (int i = 0; i < textureFiles.length; i++) {
+			TextureData data = decodeTextureFile(textureFiles[i]);
+			GL11.glTexImage2D(GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL11.GL_RGBA, data.getWidth(),
+					data.getHeight(), 0, GL12.GL_BGRA, 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_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
+		GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
+		GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, 0);
+		return texID;
+	}
+
+	protected static TextureData decodeTextureFile(MyFile file) {
+		int width = 0;
+		int height = 0;
+		ByteBuffer buffer = null;
+		try {
+			InputStream in = file.getInputStream();
+			PNGDecoder decoder = new PNGDecoder(in);
+			width = decoder.getWidth();
+			height = decoder.getHeight();
+			buffer = ByteBuffer.allocateDirect(4 * width * height);
+			decoder.decode(buffer, width * 4, Format.BGRA);
+			buffer.flip();
+			in.close();
+		} catch (Exception e) {
+			e.printStackTrace();
+			System.err.println("Tried to load texture " + file.getName() + " , didn't work");
+			System.exit(-1);
+		}
+		return new TextureData(buffer, width, height);
+	}
+
+	protected static int loadTextureToOpenGL(TextureData data, TextureBuilder builder) {
+		int texID = GL11.glGenTextures();
+		GL13.glActiveTexture(GL13.GL_TEXTURE0);
+		GL11.glBindTexture(GL11.GL_TEXTURE_2D, texID);
+		GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
+		GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, data.getWidth(), data.getHeight(), 0, GL12.GL_BGRA,
+				GL11.GL_UNSIGNED_BYTE, data.getBuffer());
+		if (builder.isMipmap()) {
+			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_MIPMAP_LINEAR);
+			if (builder.isAnisotropic() && GLContext.getCapabilities().GL_EXT_texture_filter_anisotropic) {
+				GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0);
+				GL11.glTexParameterf(GL11.GL_TEXTURE_2D, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT,
+						4.0f);
+			}
+		} else if (builder.isNearest()) {
+			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_NEAREST);
+		} else {
+			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);
+		}
+		if (builder.isClampEdges()) {
+			GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
+			GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
+		} else {
+			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);
+		}
+		GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
+		return texID;
+	}
+
+}

+ 14 - 0
src/main/java/eu/tankernn/gameEngine/util/ICamera.java

@@ -0,0 +1,14 @@
+package eu.tankernn.gameEngine.util;
+
+import org.lwjgl.util.vector.Matrix4f;
+import org.lwjgl.util.vector.Vector3f;
+
+public interface ICamera {
+	
+	public Vector3f getPosition();
+	public Matrix4f getViewMatrix();
+	public void reflect(float height);
+	public Matrix4f getProjectionMatrix();
+	public Matrix4f getProjectionViewMatrix();
+
+}

+ 2 - 2
src/main/java/eu/tankernn/gameEngine/util/MousePicker.java

@@ -37,7 +37,7 @@ public class MousePicker {
 	public MousePicker(Camera cam, Matrix4f projection, TerrainPack terrains, List<Entity> entities, List<GuiTexture> guis) {
 		camera = cam;
 		projectionMatrix = projection;
-		viewMatrix = Maths.createViewMatrix(camera);
+		viewMatrix = camera.getViewMatrix();
 		this.terrains = terrains;
 		this.entities = entities;
 		this.guis = guis;
@@ -60,7 +60,7 @@ public class MousePicker {
 	}
 	
 	public void update() {
-		viewMatrix = Maths.createViewMatrix(camera);
+		viewMatrix = camera.getViewMatrix();
 		currentRay = calculateMouseRay();
 		currentGui = calculateGuiTexture();
 		if (intersectionInRange(0, RAY_RANGE, currentRay)) {

+ 71 - 0
src/main/java/eu/tankernn/gameEngine/util/MyFile.java

@@ -0,0 +1,71 @@
+package eu.tankernn.gameEngine.util;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class MyFile {
+	
+	private static final String FILE_SEPARATOR = "/";
+
+	private String path;
+	private String name;
+
+	public MyFile(String path) {
+		this.path = FILE_SEPARATOR + path;
+		String[] dirs = path.split(FILE_SEPARATOR);
+		this.name = dirs[dirs.length - 1];
+	}
+
+	public MyFile(String... paths) {
+		this.path = "";
+		for (String part : paths) {
+			this.path += (FILE_SEPARATOR + part);
+		}
+		String[] dirs = path.split(FILE_SEPARATOR);
+		this.name = dirs[dirs.length - 1];
+	}
+
+	public MyFile(MyFile file, String subFile) {
+		this.path = file.path + FILE_SEPARATOR + subFile;
+		this.name = subFile;
+	}
+	
+	public MyFile(MyFile file, String... subFiles) {
+		this.path = file.path;
+		for (String part : subFiles) {
+			this.path += (FILE_SEPARATOR + part);
+		}
+		String[] dirs = path.split(FILE_SEPARATOR);
+		this.name = dirs[dirs.length - 1];
+	}
+
+	public String getPath() {
+		return path;
+	}
+	
+	@Override
+	public String toString(){
+		return getPath();
+	}
+
+	public InputStream getInputStream() {
+		return Class.class.getResourceAsStream(path);
+	}
+
+	public BufferedReader getReader() throws Exception {
+		try {
+			InputStreamReader isr = new InputStreamReader(getInputStream());
+			BufferedReader reader = new BufferedReader(isr);
+			return reader;
+		} catch (Exception e) {
+			System.err.println("Couldn't get reader for " + path);
+			throw e;
+		}
+	}
+
+	public String getName() {
+		return name;
+	}
+
+}

+ 3 - 2
src/main/java/eu/tankernn/gameEngine/water/WaterMaster.java

@@ -12,6 +12,7 @@ import eu.tankernn.gameEngine.entities.Light;
 import eu.tankernn.gameEngine.renderEngine.Loader;
 import eu.tankernn.gameEngine.renderEngine.MasterRenderer;
 import eu.tankernn.gameEngine.renderEngine.Scene;
+import eu.tankernn.gameEngine.util.ICamera;
 
 public class WaterMaster {
 	private WaterFrameBuffers buffers = new WaterFrameBuffers();
@@ -19,8 +20,8 @@ public class WaterMaster {
 	private List<WaterTile> waterTiles = new ArrayList<WaterTile>();
 	private WaterRenderer waterRenderer;
 	
-	public WaterMaster(Loader loader, String dudvTexture, String normalMap, MasterRenderer renderer) {
-		waterRenderer = new WaterRenderer(loader, dudvTexture, normalMap, waterShader, renderer.getProjectionMatrix(), buffers);
+	public WaterMaster(Loader loader, String dudvTexture, String normalMap, ICamera camera) {
+		waterRenderer = new WaterRenderer(loader, dudvTexture, normalMap, waterShader, camera.getProjectionMatrix(), buffers);
 	}
 	
 	public void addWaterTile(WaterTile water) {

+ 5 - 4
src/main/java/eu/tankernn/gameEngine/water/WaterRenderer.java

@@ -36,7 +36,7 @@ public class WaterRenderer {
 		this.normalMap = loader.loadTexture(normalMap);
 		shader.start();
 		shader.connectTextureUnits();
-		shader.loadProjectionMatrix(projectionMatrix);
+		shader.projectionMatrix.loadMatrix(projectionMatrix);
 		shader.stop();
 		setUpVAO(loader);
 	}
@@ -47,7 +47,7 @@ public class WaterRenderer {
 			Matrix4f modelMatrix = Maths.createTransformationMatrix(
 					new Vector3f(tile.getX(), tile.getHeight(), tile.getZ()), 0, 0, 0,
 					WaterTile.TILE_SIZE);
-			shader.loadModelMatrix(modelMatrix);
+			shader.modelMatrix.loadMatrix(modelMatrix);
 			GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, quad.getVertexCount());
 		}
 		unbind();
@@ -55,10 +55,11 @@ public class WaterRenderer {
 	
 	private void prepareRender(Camera camera, List<Light> lights){
 		shader.start();
-		shader.loadViewMatrix(camera);
+		shader.viewMatrix.loadCamera(camera);
+		shader.cameraPosition.loadVec3(camera.getPosition());
 		moveFactor += WAVE_SPEED * DisplayManager.getFrameTimeSeconds();
 		moveFactor %= 1;
-		shader.loadMoveFactor(moveFactor);
+		shader.moveFactor.loadFloat(moveFactor);
 		shader.loadLights(lights);
 		GL30.glBindVertexArray(quad.getVaoID());
 		GL20.glEnableVertexAttribArray(0);

+ 25 - 89
src/main/java/eu/tankernn/gameEngine/water/WaterShader.java

@@ -1,105 +1,41 @@
 package eu.tankernn.gameEngine.water;
 
-import java.util.List;
-
-import org.lwjgl.util.vector.Matrix4f;
-import org.lwjgl.util.vector.Vector3f;
-
-import eu.tankernn.gameEngine.entities.Camera;
-import eu.tankernn.gameEngine.entities.Light;
 import eu.tankernn.gameEngine.shaders.ShaderProgram;
-import eu.tankernn.gameEngine.util.Maths;
+import eu.tankernn.gameEngine.shaders.UniformFloat;
+import eu.tankernn.gameEngine.shaders.UniformMatrix;
+import eu.tankernn.gameEngine.shaders.UniformSampler;
+import eu.tankernn.gameEngine.shaders.UniformVec3;
+import eu.tankernn.gameEngine.shaders.UniformViewMatrix;
 
 public class WaterShader extends ShaderProgram {
 
 	private final static String VERTEX_FILE = "/eu/tankernn/gameEngine/water/waterVertex.glsl";
 	private final static String FRAGMENT_FILE = "/eu/tankernn/gameEngine/water/waterFragment.glsl";
-	private static final int MAX_LIGHTS = 4;
 
-	private int location_modelMatrix;
-	private int location_viewMatrix;
-	private int location_projectionMatrix;
-	private int location_reflectionTexture;
-	private int location_refractionTexture;
-	private int location_dudvMap;
-	private int location_moveFactor;
-	private int location_cameraPosition;
-	private int location_normalMap;
-	private int[] location_lightPosition;
-	private int[] location_lightColor;
-	private int[] location_attenuation;
-	private int location_depthMap;
-	
-	public WaterShader() {
-		super(VERTEX_FILE, FRAGMENT_FILE);
-	}
+	protected UniformMatrix modelMatrix = new UniformMatrix("modelMatrix");
+	protected UniformViewMatrix viewMatrix = new UniformViewMatrix("viewMatrix");
+	protected UniformMatrix projectionMatrix = new UniformMatrix("projectionMatrix");
+	protected UniformSampler reflectionTexture = new UniformSampler("reflectionTexture");
+	protected UniformSampler refractionTexture = new UniformSampler("refractionTexture");
+	protected UniformSampler dudvMap = new UniformSampler("dudvMap");
+	protected UniformFloat moveFactor = new UniformFloat("moveFactor");
+	protected UniformVec3 cameraPosition = new UniformVec3("cameraPosition");
+	protected UniformSampler normalMap = new UniformSampler("normalMap");
+	protected UniformSampler depthMap = new UniformSampler("depthMap");
 
-	@Override
-	protected void bindAttributes() {
-		bindAttribute(0, "position");
+	public WaterShader() {
+		super(VERTEX_FILE, FRAGMENT_FILE, "position");
+		super.getLightUniformLocations();
+		super.storeAllUniformLocations(modelMatrix, viewMatrix, projectionMatrix, reflectionTexture, refractionTexture,
+				dudvMap, moveFactor, cameraPosition, normalMap, depthMap);
 	}
 
-	@Override
-	protected void getAllUniformLocations() {
-		location_projectionMatrix = getUniformLocation("projectionMatrix");
-		location_viewMatrix = getUniformLocation("viewMatrix");
-		location_modelMatrix = getUniformLocation("modelMatrix");
-		location_reflectionTexture = getUniformLocation("reflectionTexture");
-		location_refractionTexture = getUniformLocation("refractionTexture");
-		location_dudvMap = getUniformLocation("dudvMap");
-		location_moveFactor = getUniformLocation("moveFactor");
-		location_cameraPosition = getUniformLocation("cameraPosition");
-		location_normalMap = getUniformLocation("normalMap");
-		location_depthMap = getUniformLocation("depthMap");
-		
-		location_lightPosition = new int[MAX_LIGHTS];
-		location_lightColor = new int[MAX_LIGHTS];
-		location_attenuation = new int[MAX_LIGHTS];
-		for (int i = 0; i < MAX_LIGHTS; i++) {
-			location_lightPosition[i] = super.getUniformLocation("lightPosition[" + i + "]");
-			location_lightColor[i] = super.getUniformLocation("lightColor[" + i + "]");
-			location_attenuation[i] = super.getUniformLocation("attenuation[" + i + "]");
-		}
-	}
-	
 	public void connectTextureUnits() {
-		super.loadInt(location_reflectionTexture, 0);
-		super.loadInt(location_refractionTexture, 1);
-		super.loadInt(location_dudvMap, 2);
-		super.loadInt(location_normalMap, 3);
-		super.loadInt(location_depthMap, 4);
-	}
-	
-	public void loadLights(List<Light> lights) {
-		for (int i = 0; i < MAX_LIGHTS; i++) {
-			if (i < lights.size()) {
-				super.loadVector(location_lightPosition[i], lights.get(i).getPosition());
-				super.loadVector(location_lightColor[i], lights.get(i).getColor());
-				super.loadVector(location_attenuation[i], lights.get(i).getAttenuation());
-			} else {
-				super.loadVector(location_lightPosition[i], new Vector3f(0, 0, 0));
-				super.loadVector(location_lightColor[i], new Vector3f(0, 0, 0));
-				super.loadVector(location_attenuation[i], new Vector3f(1, 0, 0));
-			}
-		}
-	}
-	
-	public void loadMoveFactor(float moveFactor) {
-		super.loadFloat(location_moveFactor, moveFactor);
-	}
-
-	public void loadProjectionMatrix(Matrix4f projection) {
-		loadMatrix(location_projectionMatrix, projection);
-	}
-	
-	public void loadViewMatrix(Camera camera){
-		Matrix4f viewMatrix = Maths.createViewMatrix(camera);
-		loadMatrix(location_viewMatrix, viewMatrix);
-		super.loadVector(location_cameraPosition, camera.getPosition());
-	}
-
-	public void loadModelMatrix(Matrix4f modelMatrix){
-		loadMatrix(location_modelMatrix, modelMatrix);
+		reflectionTexture.loadTexUnit(0);
+		refractionTexture.loadTexUnit(1);
+		dudvMap.loadTexUnit(2);
+		normalMap.loadTexUnit(3);
+		depthMap.loadTexUnit(4);
 	}
 
 }