[DEV] tutorial 6 'texturing' implementation

This commit is contained in:
Edouard DUPIN 2020-04-18 14:56:23 +02:00
parent 7c1f3508c4
commit e5467419ec
13 changed files with 188 additions and 47 deletions

View File

@ -805,5 +805,10 @@
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="lib" path="lib/pngdecoder.jar">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>

BIN
lib/pngdecoder.jar Normal file

Binary file not shown.

BIN
res/tree_sample.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View File

@ -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();
}
});

View File

@ -1,4 +1,4 @@
package renderEngine;
package models;
/**
* Represents a loaded model. It contains the ID of the VAO that contains the

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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<Integer> vaos = new ArrayList<Integer>();
private List<Integer> vbos = new ArrayList<Integer>();
private List<Integer> textures = new ArrayList<Integer>();
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);
}

View File

@ -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);
}
}

View File

@ -11,6 +11,7 @@ public class StaticShader extends ShaderProgram {
@Override
protected void bindAttributes() {
super.bindAttribute(0, "position");
super.bindAttribute(1, "textureCoords");
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -0,0 +1,15 @@
package textures;
public class ModelTexture {
private int textureID;
public ModelTexture(int id) {
this.textureID = id;
}
public int getTexturedID() {
return textureID;
}
}