diff --git a/.classpath b/.classpath
index bfd5adc..f580185 100644
--- a/.classpath
+++ b/.classpath
@@ -805,5 +805,10 @@
+
+
+
+
+
diff --git a/lib/pngdecoder.jar b/lib/pngdecoder.jar
new file mode 100644
index 0000000..fc39e9b
Binary files /dev/null and b/lib/pngdecoder.jar differ
diff --git a/res/tree_sample.png b/res/tree_sample.png
new file mode 100644
index 0000000..eab9219
Binary files /dev/null and b/res/tree_sample.png differ
diff --git a/src/engineTester/MainGameLoop.java b/src/engineTester/MainGameLoop.java
index ccc34b2..770aa38 100644
--- a/src/engineTester/MainGameLoop.java
+++ b/src/engineTester/MainGameLoop.java
@@ -1,12 +1,14 @@
package engineTester;
+import models.RawModel;
+import models.TexturedModel;
import renderEngine.DisplayManager;
import renderEngine.DisplayManagerDraw;
import renderEngine.Loader;
-import renderEngine.RawModel;
import renderEngine.Renderer;
import shaders.StaticShader;
+import textures.ModelTexture;
/**
* This class contains the main method and is used to test the engine.
@@ -30,27 +32,35 @@ public class MainGameLoop {
Renderer renderer = new Renderer();
manager.init();
StaticShader shader = new StaticShader();
-
+
float[] vertices = {
-0.5f, 0.5f, 0f,//v0
-0.5f, -0.5f, 0f,//v1
0.5f, -0.5f, 0f,//v2
0.5f, 0.5f, 0f,//v3
};
+ float[] textureCoords = {
+ 0.0f, 0.0f,//v0
+ 0.0f, 1.0f,//v1
+ 1.0f, 1.0f,//v2
+ 1.0f, 0.0f,//v3
+ };
int[] indices = {
0,1,3,//top left triangle (v0, v1, v3)
3,1,2//bottom right triangle (v3, v1, v2)
};
- RawModel model = loader.loadToVAO(vertices, indices);
+ RawModel model = loader.loadToVAO(vertices, textureCoords, indices);
+ ModelTexture texture = new ModelTexture(loader.loadTexture("tree_sample"));
+ TexturedModel texturedModel = new TexturedModel(model, texture);
manager.setDrawer(new DisplayManagerDraw() {
@Override
public void draw() {
renderer.prepare();
shader.start();
- renderer.render(model);
+ renderer.render(texturedModel);
shader.stop();
}
});
diff --git a/src/renderEngine/RawModel.java b/src/models/RawModel.java
similarity index 91%
rename from src/renderEngine/RawModel.java
rename to src/models/RawModel.java
index c36485d..9db98f2 100644
--- a/src/renderEngine/RawModel.java
+++ b/src/models/RawModel.java
@@ -1,4 +1,4 @@
-package renderEngine;
+package models;
/**
* Represents a loaded model. It contains the ID of the VAO that contains the
diff --git a/src/models/TexturedModel.java b/src/models/TexturedModel.java
new file mode 100644
index 0000000..caf9d5b
--- /dev/null
+++ b/src/models/TexturedModel.java
@@ -0,0 +1,31 @@
+package models;
+
+import textures.ModelTexture;
+
+public class TexturedModel {
+
+ private RawModel rawModel;
+ private ModelTexture texture;
+
+ public TexturedModel(RawModel model, ModelTexture texture) {
+ this.rawModel = model;
+ this.texture = texture;
+ }
+
+ public RawModel getRawModel() {
+ return rawModel;
+ }
+
+ public void setRawModel(RawModel rawModel) {
+ this.rawModel = rawModel;
+ }
+
+ public ModelTexture getTexture() {
+ return texture;
+ }
+
+ public void setTexture(ModelTexture texture) {
+ this.texture = texture;
+ }
+
+}
diff --git a/src/module-info.java b/src/module-info.java
index 99a8c51..613a246 100644
--- a/src/module-info.java
+++ b/src/module-info.java
@@ -17,5 +17,8 @@ open module Tutorial {
requires transitive org.lwjgl.stb.natives;
requires transitive org.lwjgl.opengl;
requires transitive org.lwjgl.opengl.natives;
+ requires org.lwjgl.openvr;
+ requires java.desktop;
+ requires pngdecoder;
}
diff --git a/src/renderEngine/Loader.java b/src/renderEngine/Loader.java
index 9a68c82..9b6c8a6 100644
--- a/src/renderEngine/Loader.java
+++ b/src/renderEngine/Loader.java
@@ -1,5 +1,9 @@
package renderEngine;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.ArrayList;
@@ -7,9 +11,15 @@ import java.util.List;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
+import org.lwjgl.openvr.Texture;
+
+import de.matthiasmann.twl.utils.PNGDecoder;
+import de.matthiasmann.twl.utils.PNGDecoder.Format;
+import models.RawModel;
/**
* Handles the loading of geometry data into VAOs. It also keeps track of all
@@ -23,7 +33,20 @@ public class Loader {
private List vaos = new ArrayList();
private List vbos = new ArrayList();
-
+ private List textures = new ArrayList();
+
+ private void exitOnGLError(String errorMessage) {
+ int errorValue = GL11.glGetError();
+
+ if (errorValue != GL11.GL_NO_ERROR) {
+ System.err.println("ERROR - " + errorMessage + ": ???" );
+// String errorString = GLU.gluErrorString(errorValue);
+// System.err.println("ERROR - " + errorMessage + ": " + errorString);
+//
+// if (Display.isCreated()) Display.destroy();
+ System.exit(-1);
+ }
+ }
/**
* Creates a VAO and stores the position data of the vertices into attribute
* 0 of the VAO. The indices are stored in an index buffer and bound to the
@@ -42,11 +65,75 @@ public class Loader {
public RawModel loadToVAO(float[] positions, int[] indices) {
int vaoID = createVAO();
bindIndicesBuffer(indices);
- storeDataInAttributeList(0, positions);
+ storeDataInAttributeList(0, 3, positions);
unbindVAO();
return new RawModel(vaoID, indices.length);
}
-
+ public RawModel loadToVAO(float[] positions, float[] textureCoordinates, int[] indices) {
+ int vaoID = createVAO();
+ bindIndicesBuffer(indices);
+ storeDataInAttributeList(0, 3, positions);
+ storeDataInAttributeList(1, 2, textureCoordinates);
+ unbindVAO();
+ return new RawModel(vaoID, indices.length);
+ }
+
+ public int loadTexture(String filename) {
+ int textureId = loadPNGTexture("res/" + filename + ".png", GL13.GL_TEXTURE0);
+ this.textures.add(textureId);
+ return textureId;
+ }
+
+ private int loadPNGTexture(String filename, int textureUnit) {
+ ByteBuffer buf = null;
+ int tWidth = 0;
+ int tHeight = 0;
+ try {
+ // Open the PNG file as an InputStream
+ InputStream in = new FileInputStream(filename);
+ // Link the PNG decoder to this stream
+ PNGDecoder decoder = new PNGDecoder(in);
+ // Get the width and height of the texture
+ tWidth = decoder.getWidth();
+ tHeight = decoder.getHeight();
+ // Decode the PNG file in a ByteBuffer
+ buf = ByteBuffer.allocateDirect(
+ 4 * decoder.getWidth() * decoder.getHeight());
+ decoder.decode(buf, decoder.getWidth() * 4, Format.RGBA);
+ buf.flip();
+ in.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.exit(-1);
+ }
+
+ // Create a new texture object in memory and bind it
+ int texId = GL11.glGenTextures();
+ GL13.glActiveTexture(textureUnit);
+ GL11.glBindTexture(GL11.GL_TEXTURE_2D, texId);
+
+ // All RGB bytes are aligned to each other and each component is 1 byte
+ GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
+
+ // Upload the texture data and generate mip maps (for scaling)
+ GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGB, tWidth, tHeight, 0,
+ GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buf);
+ GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
+
+ // Setup the ST coordinate system
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
+
+ // Setup what to do when the texture has to be scaled
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER,
+ GL11.GL_NEAREST);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER,
+ GL11.GL_LINEAR_MIPMAP_LINEAR);
+
+ this.exitOnGLError("loadPNGTexture");
+
+ return texId;
+ }
/**
* Deletes all the VAOs and VBOs when the game is closed. VAOs and VBOs are
* located in video memory.
@@ -58,6 +145,9 @@ public class Loader {
for (int vbo : vbos) {
GL15.glDeleteBuffers(vbo);
}
+ for (int texture : textures) {
+ GL11.glDeleteTextures(texture);
+ }
}
/**
@@ -80,46 +170,13 @@ public class Loader {
return vaoID;
}
- /**
- * Stores the position data of the vertices into attribute 0 of the VAO. To
- * do this the positions must first be stored in a VBO. You can simply think
- * of a VBO as an array of data that is stored in memory on the GPU for easy
- * access during rendering.
- *
- * Just like with the VAO, we create a new VBO using a "gen" method, and
- * make it the active VBO (so that we do stuff to it) by binding it.
- *
- * We then store the positions data in the active VBO by using the
- * glBufferData method. We also indicate using GL_STATIC_DRAW that this data
- * won't need to be changed. If we wanted to edit the positions every frame
- * (perhaps to animate the quad) then we would use GL_DYNAMIC_DRAW instead.
- *
- * We the connect the VBO to the VAO using the glVertexAttribPointer()
- * method. This needs to know the attribute number of the VAO where we want
- * to put the data, the number of floats used for each vertex (3 floats in
- * this case, because each vertex has a 3D position, an x, y, and z value),
- * the type of data (in this case we used floats) and then some other more
- * complicated stuff for storing the data in more fancy ways. Don't worry
- * about the last 3 parameters for now, we don't need them here.
- *
- * Now that we've finished using the VBO we can unbind it. This isn't
- * totally necessary, but I think it's good practice to unbind the VBO when
- * you're done using it.
- *
- * @param attributeNumber
- * - The number of the attribute of the VAO where the data is to
- * be stored.
- * @param data
- * - The geometry data to be stored in the VAO, in this case the
- * positions of the vertices.
- */
- private void storeDataInAttributeList(int attributeNumber, float[] data) {
+ private void storeDataInAttributeList(int attributeNumber, int coordinateSize, float[] data) {
int vboID = GL15.glGenBuffers();
vbos.add(vboID);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
FloatBuffer buffer = storeDataInFloatBuffer(data);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
- GL20.glVertexAttribPointer(attributeNumber, 3, GL11.GL_FLOAT, false, 0, 0);
+ GL20.glVertexAttribPointer(attributeNumber, coordinateSize, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
diff --git a/src/renderEngine/Renderer.java b/src/renderEngine/Renderer.java
index e7e67fb..1b08d0e 100644
--- a/src/renderEngine/Renderer.java
+++ b/src/renderEngine/Renderer.java
@@ -1,9 +1,13 @@
package renderEngine;
import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
+import models.RawModel;
+import models.TexturedModel;
+
/**
* Handles the rendering of a model to the screen.
*
@@ -54,5 +58,17 @@ public class Renderer {
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
+ public void render(TexturedModel texturedModel) {
+ RawModel model = texturedModel.getRawModel();
+ GL30.glBindVertexArray(model.getVaoID());
+ GL20.glEnableVertexAttribArray(0);
+ GL20.glEnableVertexAttribArray(1);
+ GL13.glActiveTexture(GL13.GL_TEXTURE0);
+ GL11.glBindTexture(GL11.GL_TEXTURE_2D, texturedModel.getTexture().getTexturedID());
+ GL11.glDrawElements(GL11.GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
+ GL20.glDisableVertexAttribArray(0);
+ GL20.glDisableVertexAttribArray(1);
+ GL30.glBindVertexArray(0);
+ }
}
diff --git a/src/shaders/StaticShader.java b/src/shaders/StaticShader.java
index f6ab20c..ae6d9f9 100644
--- a/src/shaders/StaticShader.java
+++ b/src/shaders/StaticShader.java
@@ -11,6 +11,7 @@ public class StaticShader extends ShaderProgram {
@Override
protected void bindAttributes() {
super.bindAttribute(0, "position");
+ super.bindAttribute(1, "textureCoords");
}
}
diff --git a/src/shaders/fragmentShader.txt b/src/shaders/fragmentShader.txt
index 3920269..d253531 100644
--- a/src/shaders/fragmentShader.txt
+++ b/src/shaders/fragmentShader.txt
@@ -1,10 +1,12 @@
#version 400 core
-in vec3 colour;
+in vec2 pass_textureCoords;
out vec4 out_Color;
+uniform sampler2D textureSampler;
+
void main(void) {
- out_Color = vec4(colour, 1.0);
+ out_Color = texture(textureSampler,pass_textureCoords);
}
diff --git a/src/shaders/vertexShader.txt b/src/shaders/vertexShader.txt
index 8399bc2..ee4b5e1 100644
--- a/src/shaders/vertexShader.txt
+++ b/src/shaders/vertexShader.txt
@@ -1,12 +1,13 @@
#version 400 core
in vec3 position;
+in vec2 textureCoords;
-out vec3 colour;
+out vec2 pass_textureCoords;
void main(void) {
gl_Position = vec4(position, 1.0);
- colour = vec3(position.x+0.5, 1.0, position.y+0.5);
+ pass_textureCoords = textureCoords;
}
diff --git a/src/textures/ModelTexture.java b/src/textures/ModelTexture.java
new file mode 100644
index 0000000..eb3520d
--- /dev/null
+++ b/src/textures/ModelTexture.java
@@ -0,0 +1,15 @@
+package textures;
+
+public class ModelTexture {
+
+ private int textureID;
+
+ public ModelTexture(int id) {
+ this.textureID = id;
+ }
+
+ public int getTexturedID() {
+ return textureID;
+ }
+
+}