Add texture loading.
This commit is contained in:
parent
34b9ac0d05
commit
c5972b9dd2
10 changed files with 122 additions and 11 deletions
|
@ -6,7 +6,10 @@ import org.lwjgl.opengl.GL11;
|
||||||
import org.lwjgl.opengl.GL15;
|
import org.lwjgl.opengl.GL15;
|
||||||
import org.lwjgl.opengl.GL20;
|
import org.lwjgl.opengl.GL20;
|
||||||
import org.lwjgl.opengl.GL30;
|
import org.lwjgl.opengl.GL30;
|
||||||
|
import org.lwjgl.stb.STBImage;
|
||||||
|
import org.lwjgl.system.MemoryStack;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.FloatBuffer;
|
import java.nio.FloatBuffer;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -15,14 +18,45 @@ import java.util.List;
|
||||||
public class ObjectLoader {
|
public class ObjectLoader {
|
||||||
private List<Integer> vaos = new ArrayList<>();
|
private List<Integer> vaos = new ArrayList<>();
|
||||||
private List<Integer> vbos = new ArrayList<>();
|
private List<Integer> vbos = new ArrayList<>();
|
||||||
|
private List<Integer> textures = new ArrayList<>();
|
||||||
|
|
||||||
public Model loadModel(float[] vertices, int[] indices) {
|
public Model loadModel(float[] vertices, float[] textureCoordinates, int[] indices) {
|
||||||
int id = createVAO();
|
int id = createVAO();
|
||||||
storeIndicesBuffer(indices);
|
storeIndicesBuffer(indices);
|
||||||
storeDataInAttributeList(0, 3, vertices);
|
storeDataInAttributeList(0, 3, vertices);
|
||||||
|
storeDataInAttributeList(1, 2, textureCoordinates);
|
||||||
unbind();
|
unbind();
|
||||||
|
|
||||||
return new Model(id, vertices.length / 3);
|
return new Model(id, indices.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int loadTexture(String filename) throws Exception {
|
||||||
|
int width, height;
|
||||||
|
ByteBuffer buffer;
|
||||||
|
|
||||||
|
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||||
|
IntBuffer w = stack.mallocInt(1);
|
||||||
|
IntBuffer h = stack.mallocInt(1);
|
||||||
|
IntBuffer c = stack.mallocInt(1);
|
||||||
|
|
||||||
|
buffer = STBImage.stbi_load(filename, w, h, c, 4);
|
||||||
|
if (buffer == null)
|
||||||
|
throw new Exception("Image File " + filename + " not loaded " + STBImage.stbi_failure_reason());
|
||||||
|
|
||||||
|
width = w.get();
|
||||||
|
height = h.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = GL11.glGenTextures();
|
||||||
|
|
||||||
|
textures.add(id);
|
||||||
|
GL11.glBindTexture(GL11.GL_TEXTURE_2D, id);
|
||||||
|
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
|
||||||
|
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
|
||||||
|
STBImage.stbi_image_free(buffer);
|
||||||
|
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int createVAO() {
|
private int createVAO() {
|
||||||
|
@ -67,5 +101,7 @@ public class ObjectLoader {
|
||||||
GL30.glDeleteVertexArrays(vao);
|
GL30.glDeleteVertexArrays(vao);
|
||||||
for (int vbo : vbos)
|
for (int vbo : vbos)
|
||||||
GL30.glDeleteBuffers(vbo);
|
GL30.glDeleteBuffers(vbo);
|
||||||
|
for (int texture : textures)
|
||||||
|
GL11.glDeleteTextures(texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.okseby.core;
|
||||||
import com.okseby.core.entity.Model;
|
import com.okseby.core.entity.Model;
|
||||||
import com.okseby.core.utils.Utils;
|
import com.okseby.core.utils.Utils;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
import org.lwjgl.opengl.GL13;
|
||||||
import org.lwjgl.opengl.GL20;
|
import org.lwjgl.opengl.GL20;
|
||||||
import org.lwjgl.opengl.GL30;
|
import org.lwjgl.opengl.GL30;
|
||||||
|
|
||||||
|
@ -21,18 +22,25 @@ public class RenderManager {
|
||||||
shader.createFragmentShader(Utils.loadResource("/shaders/fragment.fs"));
|
shader.createFragmentShader(Utils.loadResource("/shaders/fragment.fs"));
|
||||||
|
|
||||||
shader.link();
|
shader.link();
|
||||||
|
shader.createUniform("textureSampler");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(Model model) {
|
public void render(Model model) {
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
shader.bind();
|
shader.bind();
|
||||||
|
shader.setUniform("textureSampler", 0);
|
||||||
|
|
||||||
GL30.glBindVertexArray(model.getId());
|
GL30.glBindVertexArray(model.getId());
|
||||||
GL20.glEnableVertexAttribArray(0);
|
GL20.glEnableVertexAttribArray(0);
|
||||||
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, model.getVertexCount());
|
GL20.glEnableVertexAttribArray(1);
|
||||||
|
GL13.glActiveTexture(GL13.GL_TEXTURE0);
|
||||||
|
GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getTexture().getId());
|
||||||
|
GL11.glDrawElements(GL11.GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
GL20.glDisableVertexAttribArray(0);
|
GL20.glDisableVertexAttribArray(0);
|
||||||
|
GL20.glDisableVertexAttribArray(1);
|
||||||
|
|
||||||
GL30.glBindVertexArray(0);
|
GL30.glBindVertexArray(0);
|
||||||
|
|
||||||
shader.unbind();
|
shader.unbind();
|
||||||
|
|
|
@ -1,15 +1,42 @@
|
||||||
package com.okseby.core;
|
package com.okseby.core;
|
||||||
|
|
||||||
|
import org.joml.Matrix4f;
|
||||||
import org.lwjgl.opengl.GL20;
|
import org.lwjgl.opengl.GL20;
|
||||||
|
import org.lwjgl.system.MemoryStack;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class ShaderManager {
|
public class ShaderManager {
|
||||||
private final int programID;
|
private final int programID;
|
||||||
private int vertexShaderID, fragmentShaderID;
|
private int vertexShaderID, fragmentShaderID;
|
||||||
|
|
||||||
|
private final Map<String, Integer> uniforms;
|
||||||
|
|
||||||
public ShaderManager() throws Exception {
|
public ShaderManager() throws Exception {
|
||||||
programID = GL20.glCreateProgram();
|
programID = GL20.glCreateProgram();
|
||||||
if (programID == 0)
|
if (programID == 0)
|
||||||
throw new Exception("Could not create shader");
|
throw new Exception("Could not create shader");
|
||||||
|
|
||||||
|
uniforms = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createUniform(String uniformName) throws Exception {
|
||||||
|
int uniformLocation = GL20.glGetUniformLocation(programID, uniformName);
|
||||||
|
if (uniformLocation < 0)
|
||||||
|
throw new Exception("Could not find uniform " + uniformName);
|
||||||
|
|
||||||
|
uniforms.put(uniformName, uniformLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUniform(String uniformName, Matrix4f value) {
|
||||||
|
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||||
|
GL20.glUniformMatrix4fv(uniforms.get(uniformName), false, value.get(stack.mallocFloat(16)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUniform(String uniformName, int value) {
|
||||||
|
GL20.glUniform1i(uniforms.get(uniformName), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createVertexShader(String shaderCode) throws Exception {
|
public void createVertexShader(String shaderCode) throws Exception {
|
||||||
|
|
|
@ -17,9 +17,10 @@ public class WindowManager {
|
||||||
|
|
||||||
@Getter private long window;
|
@Getter private long window;
|
||||||
@Getter private int width, height;
|
@Getter private int width, height;
|
||||||
|
@Getter private final Matrix4f projectionMatrix;
|
||||||
|
|
||||||
@Getter @Setter private String title;
|
@Getter @Setter private String title;
|
||||||
@Getter @Setter private boolean resizeable, vsync;
|
@Getter @Setter private boolean resizeable, vsync;
|
||||||
@Getter private final Matrix4f projectionMatrix;
|
|
||||||
|
|
||||||
public WindowManager(String title, int width, int height, boolean vsync) {
|
public WindowManager(String title, int width, int height, boolean vsync) {
|
||||||
this.title = title;
|
this.title = title;
|
||||||
|
|
|
@ -1,13 +1,28 @@
|
||||||
package com.okseby.core.entity;
|
package com.okseby.core.entity;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
public class Model {
|
public class Model {
|
||||||
@Getter private int id;
|
@Getter private int id;
|
||||||
@Getter private int vertexCount;
|
@Getter private int vertexCount;
|
||||||
|
|
||||||
|
@Getter @Setter private Texture texture;
|
||||||
|
|
||||||
public Model(int id, int vertexCount) {
|
public Model(int id, int vertexCount) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.vertexCount = vertexCount;
|
this.vertexCount = vertexCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Model(int id, int vertexCount, Texture texture) {
|
||||||
|
this.id = id;
|
||||||
|
this.vertexCount = vertexCount;
|
||||||
|
this.texture = texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Model(Model model, Texture texture) {
|
||||||
|
this.id = model.getId();
|
||||||
|
this.vertexCount = model.getVertexCount();
|
||||||
|
this.texture = texture;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
14
src/main/java/com/okseby/core/entity/Texture.java
Normal file
14
src/main/java/com/okseby/core/entity/Texture.java
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package com.okseby.core.entity;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
public class Texture {
|
||||||
|
|
||||||
|
@Getter private final int id;
|
||||||
|
|
||||||
|
public Texture(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package com.okseby.core.test;
|
||||||
|
|
||||||
import com.okseby.core.*;
|
import com.okseby.core.*;
|
||||||
import com.okseby.core.entity.Model;
|
import com.okseby.core.entity.Model;
|
||||||
|
import com.okseby.core.entity.Texture;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
@ -29,9 +30,7 @@ public class TestGame implements ILogic {
|
||||||
-0.5f, 0.5f, 0f,
|
-0.5f, 0.5f, 0f,
|
||||||
-0.5f, -0.5f, 0f,
|
-0.5f, -0.5f, 0f,
|
||||||
0.5f, -0.5f, 0f,
|
0.5f, -0.5f, 0f,
|
||||||
0.5f, -0.5f, 0f,
|
|
||||||
0.5f, 0.5f, 0f,
|
0.5f, 0.5f, 0f,
|
||||||
-0.5f, 0.5f, 0f
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int[] indices = {
|
int[] indices = {
|
||||||
|
@ -39,7 +38,15 @@ public class TestGame implements ILogic {
|
||||||
3, 1, 2
|
3, 1, 2
|
||||||
};
|
};
|
||||||
|
|
||||||
model = loader.loadModel(vertices, indices);
|
float[] textureCoordinates = {
|
||||||
|
0, 0,
|
||||||
|
0, 1,
|
||||||
|
1, 1,
|
||||||
|
1, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
model = loader.loadModel(vertices, textureCoordinates, indices);
|
||||||
|
model.setTexture(new Texture(loader.loadTexture("textures/grassblock.png")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#version 400 core
|
#version 400 core
|
||||||
|
|
||||||
in vec3 color;
|
in vec2 fragmentTextureCoordinates;
|
||||||
|
|
||||||
out vec4 fragmentColor;
|
out vec4 fragmentColor;
|
||||||
|
|
||||||
|
uniform sampler2D textureSampler;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
fragmentColor = vec4(color, 1.0);
|
fragmentColor = texture(textureSampler, fragmentTextureCoordinates);
|
||||||
}
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
#version 400 core
|
#version 400 core
|
||||||
|
|
||||||
in vec3 position;
|
in vec3 position;
|
||||||
|
in vec2 textureCoordinates;
|
||||||
|
|
||||||
out vec3 color;
|
out vec2 fragmentTextureCoordinates;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(position, 1.0);
|
gl_Position = vec4(position, 1.0);
|
||||||
color = vec3(position.x + 0.25, 0.17, position.y + 0.25);
|
fragmentTextureCoordinates = textureCoordinates;
|
||||||
}
|
}
|
BIN
textures/grassblock.png
Normal file
BIN
textures/grassblock.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.1 MiB |
Loading…
Add table
Add a link
Reference in a new issue