Browse Source

More sensible approach to texture altases

Tankernn 8 years ago
parent
commit
a0f4167a7e

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

@@ -26,7 +26,7 @@ public class EnvironmentMapRenderer {
 		GL11.glViewport(0, 0, cubeMap.getWidth(), cubeMap.getHeight());
 		
 		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);
+			GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cubeMap.atlas.textureId, 0);
 			
 			camera.switchToFace(i);
 			

+ 11 - 10
src/main/java/eu/tankernn/gameEngine/loader/Loader.java

@@ -25,6 +25,7 @@ import eu.tankernn.gameEngine.loader.models.obj.ModelData;
 import eu.tankernn.gameEngine.loader.models.obj.ObjLoader;
 import eu.tankernn.gameEngine.loader.textures.ModelTexture;
 import eu.tankernn.gameEngine.loader.textures.Texture;
+import eu.tankernn.gameEngine.loader.textures.TextureAtlas;
 import eu.tankernn.gameEngine.renderEngine.Vao;
 import eu.tankernn.gameEngine.util.InternalFile;
 
@@ -37,7 +38,7 @@ public class Loader {
 	public static final int MAX_WEIGHTS = 3;
 	
 	private List<Vao> vaos = new ArrayList<>();
-	private List<Texture> textures = new ArrayList<>();
+	private List<TextureAtlas> textures = new ArrayList<>();
 	private Map<Integer, TexturedModel> models = new HashMap<>();
 	private Map<Integer, AABB> boundingBoxes = new HashMap<>();
 	
@@ -98,14 +99,14 @@ public class Loader {
 	 * @return The texture ID
 	 * @throws FileNotFoundException
 	 */
-	public Texture loadTexture(InternalFile file) {
-		Texture texture = Texture.newTexture(file).create();
+	public TextureAtlas loadTextureAtlas(InternalFile file) {
+		TextureAtlas texture = Texture.newTexture(file).create();
 		textures.add(texture);
 		return texture;
 	}
-	
-	public Texture loadTexture(String filename) throws FileNotFoundException {
-		return loadTexture(new InternalFile(filename));
+
+	public Texture loadTexture(InternalFile file) {
+		return new Texture(loadTextureAtlas(file));
 	}
 	
 	/**
@@ -119,7 +120,7 @@ public class Loader {
 	
 	public Texture loadCubeMap(InternalFile[] textureFiles) {
 		Texture cubeMap = Texture.newCubeMap(textureFiles, 500);
-		textures.add(cubeMap);
+		textures.add(cubeMap.atlas);
 		return cubeMap;
 	}
 	
@@ -141,7 +142,7 @@ public class Loader {
 	
 	@Override
 	public void finalize() {
-		for (Texture tex: textures)
+		for (TextureAtlas tex: textures)
 			tex.delete();
 		for (Vao model: vaos)
 			model.finalize();
@@ -157,7 +158,7 @@ public class Loader {
 	/**
 	 * Creates an AnimatedEntity from the data in an entity file. It loads up
 	 * the collada model data, stores the extracted data in a VAO, sets up the
-	 * joint heirarchy, and loads up the entity's texture.
+	 * joint hierarchy, and loads up the entity's texture.
 	 * 
 	 * @param entityFile - the file containing the data for the entity.
 	 * @return The animated entity (no animation applied though)
@@ -201,7 +202,7 @@ public class Loader {
 					if (cachedTextures.containsKey(f)) {
 						return cachedTextures.get(f);
 					} else {
-						Texture t = loadTexture(f.getPath());
+						Texture t = loadTexture(f);
 						cachedTextures.put(f, t);
 						return t;
 					}

+ 4 - 4
src/main/java/eu/tankernn/gameEngine/loader/font/FontFamily.java

@@ -1,6 +1,6 @@
 package eu.tankernn.gameEngine.loader.font;
 
-import eu.tankernn.gameEngine.loader.textures.Texture;
+import eu.tankernn.gameEngine.loader.textures.TextureAtlas;
 import eu.tankernn.gameEngine.util.InternalFile;
 
 /**
@@ -12,7 +12,7 @@ import eu.tankernn.gameEngine.util.InternalFile;
  */
 public class FontFamily {
 
-	private Texture textureAtlas;
+	private TextureAtlas textureAtlas;
 	private TextMeshCreator loader;
 
 	/**
@@ -25,7 +25,7 @@ public class FontFamily {
 	 *            - the font file containing information about each character in
 	 *            the texture atlas.
 	 */
-	public FontFamily(Texture texture, InternalFile fontFile) {
+	public FontFamily(TextureAtlas texture, InternalFile fontFile) {
 		this.textureAtlas = texture;
 		this.loader = new TextMeshCreator(fontFile);
 	}
@@ -33,7 +33,7 @@ public class FontFamily {
 	/**
 	 * @return The font texture atlas.
 	 */
-	public Texture getTextureAtlas() {
+	public TextureAtlas getTextureAtlas() {
 		return textureAtlas;
 	}
 

+ 0 - 17
src/main/java/eu/tankernn/gameEngine/loader/models/TexturedModel.java

@@ -7,27 +7,10 @@ public class TexturedModel {
 	private Vao rawModel;
 	private ModelTexture texture;
 	
-	private int textureIndex = 0;
-	
 	public TexturedModel(Vao rawModel, ModelTexture texture) {
 		this.rawModel = rawModel;
 		this.texture = texture;
 	}
-	
-	public TexturedModel(Vao rawModel, ModelTexture texture, int textureIndex) {
-		this(rawModel, texture);
-		this.textureIndex = textureIndex;
-	}
-	
-	public float getTextureXOffset() {
-		int column = textureIndex % texture.getNumberOfRows();
-		return (float) column / (float) texture.getNumberOfRows();
-	}
-	
-	public float getTextureYOffset() {
-		int row = textureIndex / texture.getNumberOfRows();
-		return (float) row / (float) texture.getNumberOfRows();
-	}
 
 	public Vao getModel() {
 		return rawModel;

+ 32 - 23
src/main/java/eu/tankernn/gameEngine/loader/textures/Texture.java

@@ -1,34 +1,34 @@
 package eu.tankernn.gameEngine.loader.textures;
 
-import org.lwjgl.opengl.GL11;
 import org.lwjgl.opengl.GL13;
 import org.lwjgl.util.vector.Vector2f;
 
 import eu.tankernn.gameEngine.util.InternalFile;
 
 public class Texture {
-
-	public final int textureId;
-	public final Vector2f dimensions;
-	private final int type;
-
+	
+	public final TextureAtlas atlas;
+	public final int index;
+	
 	protected Texture(int textureId, int width, int height) {
-		this(textureId, GL11.GL_TEXTURE_2D, width, height);
+		this(new TextureAtlas(textureId, width, height));
 	}
-
-	protected Texture(int textureId, int type, int width, int height) {
-		this.textureId = textureId;
-		this.dimensions = new Vector2f(width, height);
-		this.type = type;
+	
+	public Texture(TextureAtlas atlas) {
+		this(atlas, 0);
 	}
-
+	
+	public Texture(TextureAtlas atlas, int index) {
+		this.atlas = atlas;
+		this.index = index;
+	}
+	
 	public void bindToUnit(int unit) {
-		GL13.glActiveTexture(GL13.GL_TEXTURE0 + unit);
-		GL11.glBindTexture(type, textureId);
+		atlas.bindToUnit(unit);
 	}
 
 	public void delete() {
-		GL11.glDeleteTextures(textureId);
+		atlas.delete();
 	}
 
 	public static TextureBuilder newTexture(InternalFile textureFile) {
@@ -37,28 +37,37 @@ public class Texture {
 
 	public static Texture newCubeMap(InternalFile[] textureFiles, int size) {
 		int cubeMapId = TextureUtils.loadCubeMap(textureFiles);
-		return new Texture(cubeMapId, GL13.GL_TEXTURE_CUBE_MAP, size);
+		return new Texture(new TextureAtlas(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);
+		return new Texture(new TextureAtlas(cubeMapId, GL13.GL_TEXTURE_CUBE_MAP, size));
 	}
 
 	public int getWidth() {
-		return (int) (dimensions.x);
+		return (int) (atlas.dimensions.x / atlas.rows);
 	}
 	
 	public int getHeight() {
-		return (int) (dimensions.y);
+		return (int) (atlas.dimensions.y / atlas.rows);
 	}
 	
 	public int getSize() {
-		return (int) (dimensions.x * dimensions.y);
+		return getWidth() * getHeight();
 	}
 	
 	public Vector2f getRatio() {
-		return (Vector2f) new Vector2f(dimensions).normalise();
+		return (Vector2f) new Vector2f(getWidth(), getHeight()).normalise();
+	}
+	
+	public float getXOffset() {
+		int column = index % atlas.rows;
+		return (float) column / (float) atlas.rows;
+	}
+	
+	public float getYOffset() {
+		int row = index / atlas.rows;
+		return (float) row / (float) atlas.rows;
 	}
-
 }

+ 33 - 0
src/main/java/eu/tankernn/gameEngine/loader/textures/TextureAtlas.java

@@ -0,0 +1,33 @@
+package eu.tankernn.gameEngine.loader.textures;
+
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL13;
+import org.lwjgl.util.vector.Vector2f;
+
+public class TextureAtlas {
+
+	public final int textureId;
+	private final int type;
+	public final Vector2f dimensions;
+	public final int rows;
+	
+	protected TextureAtlas(int textureId, int width, int height) {
+		this(textureId, GL11.GL_TEXTURE_2D, width, height, 1);
+	}
+	
+	protected TextureAtlas(int textureId, int type, int width, int height, int rows) {
+		this.textureId = textureId;
+		this.dimensions = new Vector2f(width, height);
+		this.type = type;
+		this.rows = rows;
+	}
+	
+	public void bindToUnit(int unit) {
+		GL13.glActiveTexture(GL13.GL_TEXTURE0 + unit);
+		GL11.glBindTexture(type, textureId);
+	}
+
+	public void delete() {
+		GL11.glDeleteTextures(textureId);
+	}
+}

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

@@ -1,64 +1,64 @@
-package eu.tankernn.gameEngine.loader.textures;
-
-import eu.tankernn.gameEngine.util.InternalFile;
-
-public class TextureBuilder {
-	
-	private boolean clampEdges = false;
-	private boolean mipmap = false;
-	private boolean anisotropic = true;
-	private boolean nearest = false;
-	
-	private InternalFile file;
-	
-	protected TextureBuilder(InternalFile textureFile){
-		this.file = textureFile;
-	}
-	
-	public Texture create(){
-		TextureData textureData = TextureUtils.decodeTextureFile(file);
-		int textureId = TextureUtils.loadTextureToOpenGL(textureData, this);
-		return new Texture(textureId, textureData.getWidth(), textureData.getHeight());
-	}
-	
-	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;
-	}
-
-}
+package eu.tankernn.gameEngine.loader.textures;
+
+import eu.tankernn.gameEngine.util.InternalFile;
+
+public class TextureBuilder {
+	
+	private boolean clampEdges = false;
+	private boolean mipmap = false;
+	private boolean anisotropic = true;
+	private boolean nearest = false;
+	
+	private InternalFile file;
+	
+	protected TextureBuilder(InternalFile textureFile){
+		this.file = textureFile;
+	}
+	
+	public TextureAtlas create(){
+		TextureData textureData = TextureUtils.decodeTextureFile(file);
+		int textureId = TextureUtils.loadTextureToOpenGL(textureData, this);
+		return new TextureAtlas(textureId, textureData.getWidth(), textureData.getHeight());
+	}
+	
+	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;
+	}
+
+}

+ 152 - 152
src/main/java/eu/tankernn/gameEngine/loader/textures/TextureUtils.java

@@ -1,152 +1,152 @@
-package eu.tankernn.gameEngine.loader.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.GL32;
-import org.lwjgl.opengl.GLContext;
-
-import de.matthiasmann.twl.utils.PNGDecoder;
-import de.matthiasmann.twl.utils.PNGDecoder.Format;
-import eu.tankernn.gameEngine.util.InternalFile;
-
-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(InternalFile[] 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(InternalFile 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;
-	}
-
-	public static Texture createTextureAttachment(int width, int height) {
-		int texture = GL11.glGenTextures();
-		GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
-		GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, width, height, 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE,
-				(ByteBuffer) null);
-		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);
-		GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, texture, 0);
-		return new Texture(texture, width, height);
-	}
-
-	/**
-	 * Creates a depth buffer texture attachment.
-	 * 
-	 * @param width
-	 *            - the width of the texture.
-	 * @param height
-	 *            - the height of the texture.
-	 * @return The depth texture object.
-	 */
-	public static Texture createDepthTextureAttachment(int width, int height) {
-		int texture = GL11.glGenTextures();
-		GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
-		GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL14.GL_DEPTH_COMPONENT32, width, height, 0, GL11.GL_DEPTH_COMPONENT,
-				GL11.GL_FLOAT, (ByteBuffer) null);
-		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);
-		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);
-		GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, texture, 0);
-		return new Texture(texture, width, height);
-	}
-
-	public static int createDepthBufferAttachment(int width, int height) {
-		int depthBuffer = GL30.glGenRenderbuffers();
-		GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBuffer);
-		GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL11.GL_DEPTH_COMPONENT, width, height);
-		GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL30.GL_RENDERBUFFER,
-				depthBuffer);
-		return depthBuffer;
-	}
-
-}
+package eu.tankernn.gameEngine.loader.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.GL32;
+import org.lwjgl.opengl.GLContext;
+
+import de.matthiasmann.twl.utils.PNGDecoder;
+import de.matthiasmann.twl.utils.PNGDecoder.Format;
+import eu.tankernn.gameEngine.util.InternalFile;
+
+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(InternalFile[] 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(InternalFile 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;
+	}
+
+	public static Texture createTextureAttachment(int width, int height) {
+		int texture = GL11.glGenTextures();
+		GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
+		GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, width, height, 0, GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE,
+				(ByteBuffer) null);
+		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);
+		GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, texture, 0);
+		return new Texture(texture, width, height);
+	}
+
+	/**
+	 * Creates a depth buffer texture attachment.
+	 * 
+	 * @param width
+	 *            - the width of the texture.
+	 * @param height
+	 *            - the height of the texture.
+	 * @return The depth texture object.
+	 */
+	public static Texture createDepthTextureAttachment(int width, int height) {
+		int texture = GL11.glGenTextures();
+		GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
+		GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL14.GL_DEPTH_COMPONENT32, width, height, 0, GL11.GL_DEPTH_COMPONENT,
+				GL11.GL_FLOAT, (ByteBuffer) null);
+		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);
+		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);
+		GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, texture, 0);
+		return new Texture(texture, width, height);
+	}
+
+	public static int createDepthBufferAttachment(int width, int height) {
+		int depthBuffer = GL30.glGenRenderbuffers();
+		GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBuffer);
+		GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL11.GL_DEPTH_COMPONENT, width, height);
+		GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL30.GL_RENDERBUFFER,
+				depthBuffer);
+		return depthBuffer;
+	}
+
+}

+ 96 - 97
src/main/java/eu/tankernn/gameEngine/particles/ParticleMaster.java

@@ -1,97 +1,96 @@
-package eu.tankernn.gameEngine.particles;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.lwjgl.util.vector.Matrix4f;
-import org.lwjgl.util.vector.Vector2f;
-import org.lwjgl.util.vector.Vector3f;
-
-import eu.tankernn.gameEngine.entities.Camera;
-import eu.tankernn.gameEngine.loader.Loader;
-import eu.tankernn.gameEngine.loader.font.Font;
-import eu.tankernn.gameEngine.loader.font.GUIText;
-import eu.tankernn.gameEngine.renderEngine.Fbo;
-import eu.tankernn.gameEngine.renderEngine.font.FontRenderer;
-import eu.tankernn.gameEngine.util.DistanceSorter;
-
-public class ParticleMaster {
-	private Loader loader;
-
-	private Map<ParticleTexture, List<Particle>> particles = new HashMap<>();
-	private List<ParticleSystem> systems = new ArrayList<>();
-	private ParticleRenderer renderer;
-	private FontRenderer fontRenderer = new FontRenderer();
-
-	public ParticleMaster(Loader loader, Matrix4f projectionMatrix) {
-		this.loader = loader;
-		renderer = new ParticleRenderer(loader, projectionMatrix);
-	}
-
-	public void update(Camera camera) {
-		for (ParticleSystem sys : systems) {
-			for (Particle particle : sys.generateParticles()) {
-				addParticle(particle);
-			}
-		}
-
-		Iterator<Entry<ParticleTexture, List<Particle>>> mapIterator = particles.entrySet().iterator();
-		while (mapIterator.hasNext()) {
-			Entry<ParticleTexture, List<Particle>> entry = mapIterator.next();
-			List<Particle> list = entry.getValue();
-			Iterator<Particle> iterator = list.iterator();
-			while (iterator.hasNext()) {
-				Particle p = iterator.next();
-				boolean stillAlive = p.update(camera);
-				if (!stillAlive) {
-					iterator.remove();
-					if (list.isEmpty()) {
-						mapIterator.remove();
-					}
-				}
-			}
-			if (!entry.getKey().usesAdditiveBlending())
-				DistanceSorter.sort(list, camera);
-		}
-
-		systems.removeIf(ParticleSystem::isDead);
-	}
-
-	public void renderParticles(Camera camera) {
-		renderer.render(particles, camera);
-	}
-
-	@Override
-	public void finalize() {
-		renderer.finalize();
-	}
-
-	public void addTextParticle(String text, Font font, Vector3f position) {
-
-		GUIText guiText = new GUIText(text, font, new Vector2f(0, 0), 1.0f, false);
-		guiText.update(loader);
-		Fbo fbo = new Fbo((int) (100 * font.size), (int) (100 * font.size), 0);
-		fbo.bindFrameBuffer();
-		fontRenderer.render(guiText);
-		fbo.unbindFrameBuffer();
-		addParticle(new Particle(new ParticleTexture(fbo.getColourTexture(), 1, true), position, new Vector3f(0, 0, 0),
-				0.1f, 4, 0, font.size));
-	}
-
-	public void addParticle(Particle particle) {
-		List<Particle> list = particles.get(particle.getTexture());
-		if (list == null) {
-			list = new ArrayList<Particle>();
-			particles.put(particle.getTexture(), list);
-		}
-		list.add(particle);
-	}
-
-	public void addSystem(ParticleSystem system) {
-		this.systems.add(system);
-	}
-}
+package eu.tankernn.gameEngine.particles;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.lwjgl.util.vector.Matrix4f;
+import org.lwjgl.util.vector.Vector2f;
+import org.lwjgl.util.vector.Vector3f;
+
+import eu.tankernn.gameEngine.entities.Camera;
+import eu.tankernn.gameEngine.loader.Loader;
+import eu.tankernn.gameEngine.loader.font.Font;
+import eu.tankernn.gameEngine.loader.font.GUIText;
+import eu.tankernn.gameEngine.renderEngine.Fbo;
+import eu.tankernn.gameEngine.renderEngine.font.FontRenderer;
+import eu.tankernn.gameEngine.util.DistanceSorter;
+
+public class ParticleMaster {
+	private Loader loader;
+
+	private Map<ParticleTexture, List<Particle>> particles = new HashMap<>();
+	private List<ParticleSystem> systems = new ArrayList<>();
+	private ParticleRenderer renderer;
+	private FontRenderer fontRenderer = new FontRenderer();
+
+	public ParticleMaster(Loader loader, Matrix4f projectionMatrix) {
+		this.loader = loader;
+		renderer = new ParticleRenderer(loader, projectionMatrix);
+	}
+
+	public void update(Camera camera) {
+		for (ParticleSystem sys : systems) {
+			for (Particle particle : sys.generateParticles()) {
+				addParticle(particle);
+			}
+		}
+
+		Iterator<Entry<ParticleTexture, List<Particle>>> mapIterator = particles.entrySet().iterator();
+		while (mapIterator.hasNext()) {
+			Entry<ParticleTexture, List<Particle>> entry = mapIterator.next();
+			List<Particle> list = entry.getValue();
+			Iterator<Particle> iterator = list.iterator();
+			while (iterator.hasNext()) {
+				Particle p = iterator.next();
+				boolean stillAlive = p.update(camera);
+				if (!stillAlive) {
+					iterator.remove();
+					if (list.isEmpty()) {
+						mapIterator.remove();
+					}
+				}
+			}
+			if (!entry.getKey().usesAdditiveBlending())
+				DistanceSorter.sort(list, camera);
+		}
+
+		systems.removeIf(ParticleSystem::isDead);
+	}
+
+	public void renderParticles(Camera camera) {
+		renderer.render(particles, camera);
+	}
+
+	@Override
+	public void finalize() {
+		renderer.finalize();
+	}
+
+	public void addTextParticle(String text, Font font, Vector3f position) {
+		GUIText guiText = new GUIText(text, font, new Vector2f(0, 0), 1.0f, false);
+		guiText.update(loader);
+		Fbo fbo = new Fbo((int) (100 * font.size), (int) (100 * font.size), 0);
+		fbo.bindFrameBuffer();
+		fontRenderer.render(guiText);
+		fbo.unbindFrameBuffer();
+		addParticle(new Particle(new ParticleTexture(fbo.getColourTexture(), 1, true), position, new Vector3f(0, 0, 0),
+				0.1f, 4, 0, font.size));
+	}
+
+	public void addParticle(Particle particle) {
+		List<Particle> list = particles.get(particle.getTexture());
+		if (list == null) {
+			list = new ArrayList<Particle>();
+			particles.put(particle.getTexture(), list);
+		}
+		list.add(particle);
+	}
+
+	public void addSystem(ParticleSystem system) {
+		this.systems.add(system);
+	}
+}

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

@@ -129,6 +129,6 @@ public class EntityRenderer<S extends EntityShader> {
 	protected void prepareInstance(Entity3D entity, TexturedModel model) {
 		Matrix4f transformationMatrix = Maths.createTransformationMatrix(entity.getPosition(), entity.getRotation(), entity.getScale());
 		shader.transformationMatrix.loadMatrix(transformationMatrix);
-		shader.offset.loadVec2(model.getTextureXOffset(), model.getTextureYOffset());
+		shader.offset.loadVec2(model.getTexture().getTexture().getXOffset(), model.getTexture().getTexture().getYOffset());
 	}
 }

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

@@ -25,7 +25,7 @@ public class GuiTexture {
 	}
 
 	public Vector2f getSize() {
-		return (Vector2f) new Vector2f(texture.dimensions).scale(scale);
+		return (Vector2f) new Vector2f(texture.getRatio()).scale(scale);
 	}
 
 	public void setPosition(Vector2f position) {