diff --git a/client/res/textures/test_texture.png b/client/res/textures/test_texture.png new file mode 100644 index 0000000..25f8a24 Binary files /dev/null and b/client/res/textures/test_texture.png differ diff --git a/client/src/main/java/core/engine/Engine.java b/client/src/main/java/core/engine/Engine.java index dbe6708..691dd29 100644 --- a/client/src/main/java/core/engine/Engine.java +++ b/client/src/main/java/core/engine/Engine.java @@ -1,7 +1,9 @@ package core.engine; import core.engine.model.RawModel; +import core.engine.model.TexturedModel; import core.engine.shader.StaticShader; +import core.engine.textures.ModelTexture; import org.lwjgl.Version; import org.lwjgl.glfw.GLFWErrorCallback; import org.lwjgl.glfw.GLFWVidMode; @@ -114,13 +116,23 @@ public class Engine { 0,1,3, 3,1,2 }; - RawModel model = loader.loadToVAO(vertices, indices); + + float[] textureCoords = { + 0,0, // V0 + 0,1, // V1 + 1,1, // V2 + 1,0 // V3 + + }; + RawModel model = loader.loadToVAO(vertices,textureCoords, indices); + ModelTexture modelTexture = new ModelTexture(loader.loadTexture("test_texture")); + TexturedModel texturedModel = new TexturedModel(model, modelTexture); // Run the rendering loop until the user has attempted to close // the window or has pressed the ESCAPE key. while ( !glfwWindowShouldClose(window) ) { renderer.prepare(); shader.start(); - renderer.render(model); + renderer.render(texturedModel); shader.stop(); glfwSwapBuffers(window); // swap the color buffers diff --git a/client/src/main/java/core/engine/Loader.java b/client/src/main/java/core/engine/Loader.java index 8e2eff3..607fa3c 100644 --- a/client/src/main/java/core/engine/Loader.java +++ b/client/src/main/java/core/engine/Loader.java @@ -1,6 +1,7 @@ package core.engine; import core.engine.model.RawModel; +import core.engine.textures.Texture; import org.lwjgl.BufferUtils; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL15; @@ -16,16 +17,24 @@ public class Loader { private List vaos = new ArrayList<>(); private List vbos = new ArrayList<>(); + private List textureIDs = new ArrayList<>(); - public RawModel loadToVAO(float[] positions, int[] indices) { + public RawModel loadToVAO(float[] positions, float[] textureCoords, int[] indices) { int vaoID = createVAO(); bindIndicesBuffer(indices); - storeDataInAttributeList(0, positions); - + storeDataInAttributeList(0, 3,positions); + storeDataInAttributeList(1, 2, textureCoords); unbindVAO(); return new RawModel(vaoID, indices.length); } + public int loadTexture(String fileName) { + Texture texture = new Texture("res/textures/" + fileName + ".png"); + int textureID = texture.getTextureID(); + this.textureIDs.add(textureID); + return textureID; + } + private int createVAO() { int vao = GL30.glGenVertexArrays(); vaos.add(vao); @@ -33,13 +42,13 @@ public class Loader { return vao; } - 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 floatBuffer = storeInFloatBuffer(data); GL15.glBufferData(GL15.GL_ARRAY_BUFFER, floatBuffer, 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); } @@ -80,5 +89,9 @@ public class Loader { for(int vbo: vbos) { GL15.glDeleteBuffers(vbo); } + + for(int textureID: textureIDs) { + GL11.glDeleteTextures(textureID); + } } } diff --git a/client/src/main/java/core/engine/Renderer.java b/client/src/main/java/core/engine/Renderer.java index 7a0b85a..b21d561 100644 --- a/client/src/main/java/core/engine/Renderer.java +++ b/client/src/main/java/core/engine/Renderer.java @@ -1,7 +1,9 @@ package core.engine; import core.engine.model.RawModel; +import core.engine.model.TexturedModel; import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL30; @@ -14,11 +16,16 @@ public class Renderer { GL11.glClearColor(1,0,0,1); } - public void render(RawModel rawModel) { + public void render(TexturedModel texturedModel) { + RawModel rawModel = texturedModel.getRawModel(); GL30.glBindVertexArray(rawModel.getVaoID()); GL20.glEnableVertexAttribArray(0); + GL20.glEnableVertexAttribArray(1); + GL13.glActiveTexture(GL13.GL_TEXTURE0); + GL11.glBindTexture(GL11.GL_TEXTURE_2D, texturedModel.getModelTexture().getTextureID()); GL11.glDrawElements(GL11.GL_TRIANGLES, rawModel.getVertexCount(), GL11.GL_UNSIGNED_INT, 0); GL20.glDisableVertexAttribArray(0); + GL20.glDisableVertexAttribArray(1); GL30.glBindVertexArray(0); } } diff --git a/client/src/main/java/core/engine/model/TexturedModel.java b/client/src/main/java/core/engine/model/TexturedModel.java new file mode 100644 index 0000000..1477882 --- /dev/null +++ b/client/src/main/java/core/engine/model/TexturedModel.java @@ -0,0 +1,22 @@ +package core.engine.model; + +import core.engine.textures.ModelTexture; + +public class TexturedModel { + + private RawModel rawModel; + private ModelTexture modelTexture; + + public TexturedModel(RawModel rawModel, ModelTexture modelTexture) { + this.rawModel = rawModel; + this.modelTexture = modelTexture; + } + + public RawModel getRawModel() { + return rawModel; + } + + public ModelTexture getModelTexture() { + return modelTexture; + } +} diff --git a/client/src/main/java/core/engine/shader/StaticShader.java b/client/src/main/java/core/engine/shader/StaticShader.java index a0cd6b0..5770517 100644 --- a/client/src/main/java/core/engine/shader/StaticShader.java +++ b/client/src/main/java/core/engine/shader/StaticShader.java @@ -11,5 +11,6 @@ public class StaticShader extends ShaderProgram{ @Override protected void bindAttributes() { super.bindAttribute(0, "position"); + super.bindAttribute(1, "textureCoords"); } } diff --git a/client/src/main/java/core/engine/shader/fragmentShader.glsl b/client/src/main/java/core/engine/shader/fragmentShader.glsl index 379ee65..34dab1e 100644 --- a/client/src/main/java/core/engine/shader/fragmentShader.glsl +++ b/client/src/main/java/core/engine/shader/fragmentShader.glsl @@ -1,9 +1,11 @@ #version 400 core -in vec3 color; +in vec2 pass_textureCoords; out vec4 out_Color; +uniform sampler2D textureSampler; + void main(void) { - out_Color = vec4(color, 1.0); + out_Color = texture(textureSampler, pass_textureCoords); } \ No newline at end of file diff --git a/client/src/main/java/core/engine/shader/vertexShader.glsl b/client/src/main/java/core/engine/shader/vertexShader.glsl index b572537..bf9cd42 100644 --- a/client/src/main/java/core/engine/shader/vertexShader.glsl +++ b/client/src/main/java/core/engine/shader/vertexShader.glsl @@ -1,11 +1,11 @@ #version 400 core in vec3 position; +in vec2 textureCoords; -out vec3 color; +out vec2 pass_textureCoords; void main(void) { gl_Position = vec4(position, 1.0); - color = vec3(position.x+0.5, 1.0, position.y+0.5); - + pass_textureCoords = textureCoords; } \ No newline at end of file diff --git a/client/src/main/java/core/engine/textures/ModelTexture.java b/client/src/main/java/core/engine/textures/ModelTexture.java new file mode 100644 index 0000000..4e7fa46 --- /dev/null +++ b/client/src/main/java/core/engine/textures/ModelTexture.java @@ -0,0 +1,14 @@ +package core.engine.textures; + +public class ModelTexture { + + private int textureID; + + public ModelTexture(int textureID) { + this.textureID = textureID; + } + + public int getTextureID() { + return textureID; + } +} diff --git a/client/src/main/java/core/engine/textures/Texture.java b/client/src/main/java/core/engine/textures/Texture.java new file mode 100644 index 0000000..b46a04c --- /dev/null +++ b/client/src/main/java/core/engine/textures/Texture.java @@ -0,0 +1,70 @@ +package core.engine.textures; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.IntBuffer; + +import static org.lwjgl.opengl.GL11.*; + +public class Texture { + + private int width, height; + private int texture; + + public Texture(String path) { + texture = load(path); + } + + private int load(String path) { + int[] pixels = null; + try { + BufferedImage image = ImageIO.read(new FileInputStream(path)); + width = image.getWidth(); + height = image.getHeight(); + pixels = new int[width * height]; + image.getRGB(0, 0, width, height, pixels, 0, width); + } catch (IOException e) { + e.printStackTrace(); + } + + int[] data = new int[width * height]; + for (int i = 0; i < width * height; i++) { + int a = (pixels[i] & 0xff000000) >> 24; + int r = (pixels[i] & 0xff0000) >> 16; + int g = (pixels[i] & 0xff00) >> 8; + int b = (pixels[i] & 0xff); + + data[i] = a << 24 | b << 16 | g << 8 | r; + } + + int result = glGenTextures(); + glBindTexture(GL_TEXTURE_2D, result); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + IntBuffer buffer = ByteBuffer.allocateDirect(data.length << 2) + .order(ByteOrder.nativeOrder()).asIntBuffer(); + buffer.put(data).flip(); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, buffer); + glBindTexture(GL_TEXTURE_2D, 0); + return result; + } + + public void bind() { + glBindTexture(GL_TEXTURE_2D, texture); + } + + public void unbind() { + glBindTexture(GL_TEXTURE_2D, 0); + } + + public int getTextureID() { + return texture; + } +}