For some reason, when I try to render textures using LWJGL, the texture only renders as a solid color. I don't think that it's a problem with the texture loading (I'm using the Slick Util library) because the color that the texture is seems to be the dominant color in the image.
Model class:
public class Model {
private FloatBuffer vertices, uvValues;
private int vertexID, uvID;
private int vertexAttrib, uvAttrib;
private Texture tex;
private ByteBuffer texData;
private int textureID;
private int textureLocation;
private Matrix4f modelMatrix;
private FloatBuffer modelBuffer;
private int modelMatrixLocation;
public Model(float[] verts, float[] uvs, int modelLocation, String texPath, int texLocation){
vertices = createBuffer(verts);
vertexAttrib = 0;
vertexID = createVBO(vertices, vertexAttrib, 3);
tex = TextureUtils.loadTexturePNG(texPath);
texData = createBuffer(tex);
textureID = bindTextureData(tex, texData);
textureLocation = texLocation;
uvValues = createBuffer(uvs);
uvAttrib = 1;
uvID = createVBO(uvValues, uvAttrib, 2);
modelMatrix = new Matrix4f();
modelMatrixLocation = modelLocation;
modelBuffer = createBuffer(modelMatrix);
}
private static FloatBuffer createBuffer(float[] vals){
FloatBuffer buffer = BufferUtils.createFloatBuffer(vals.length);
buffer.put(vals);
buffer.flip();
return buffer;
}
private static FloatBuffer createBuffer(Matrix4f mat){
FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
mat.store(buffer);
buffer.flip();
return buffer;
}
private static ByteBuffer createBuffer(Texture tex){
ByteBuffer buffer = BufferUtils.createByteBuffer(tex.getTextureData().length);
buffer.put(tex.getTextureData());
buffer.flip();
return buffer;
}
private static int bindTextureData(Texture tex, ByteBuffer data){
int id = glGenTextures();
glBindTexture(GL_TEXTURE_2D, id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, (int) tex.getWidth(), (int) tex.getHeight(), 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
return id;
}
private static int createVBO(FloatBuffer buffer, int location, int vectorSize){
int id = glGenBuffers();
glEnableVertexAttribArray(location);
glBindBuffer(GL_ARRAY_BUFFER, id);
glBufferData(GL_ARRAY_BUFFER, buffer, GL_STATIC_DRAW);
glVertexAttribPointer(location, vectorSize, GL_FLOAT, false, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(location);
return id;
}
private void bind(){
glUniformMatrix4(modelMatrixLocation, false, modelBuffer);
tex.bind();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
glUniform1i(textureLocation, 0);
glEnableVertexAttribArray(vertexAttrib);
glBindBuffer(GL_ARRAY_BUFFER, vertexID);
glVertexAttribPointer(vertexAttrib, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(uvAttrib);
glBindBuffer(GL_ARRAY_BUFFER, uvID);
glVertexAttribPointer(uvAttrib, 2, GL_FLOAT, false, 0, 0);
}
private void unbind(){
glDisableVertexAttribArray(uvAttrib);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(vertexAttrib);
glBindTexture(GL_TEXTURE_2D, 0);
}
public void render(){
bind();
glDrawArrays(GL_TRIANGLES, 0, vertices.capacity() / 3);
unbind();
}
}
Model initialization code:
model = new Model(new float[]{
-1, -1, -3,
1, -1, -3,
1, 1, -3
}, new float[]{
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f
}, program.getUniformLocation("model_matrix"), "res/tex/testTex.png", program.getUniformLocation("texture_sampler"));
Vertex shader:
#version 330 core
layout(location = 0) in vec3 position_modelspace;
layout(location = 1) in vec2 vertex_UV;
uniform mat4 model_matrix;
uniform mat4 view_matrix;
uniform mat4 projection_matrix;
out vec2 UV;
void main(){
vec4 vertex_MVP = projection_matrix * view_matrix * model_matrix * vec4(position_modelspace, 1.0);
gl_Position = vertex_MVP;
UV = vertex_UV;
}
Fragment shader:
#version 330 core
uniform sampler2D texture_sampler;
in vec2 UV;
out vec3 color;
void main(){
color = texture(texture_sampler, UV).rgb;
}
I'm not really sure what the problem is. The texture loads without any problem, and I've looked at a lot of other questions with similar problems, but I haven't yet found one that solves this.
Textureclass look like, and why are you binding it before you set the active Texture Image Unit? I would expect to seetexobject bound at the same time asglBindTexture (...), in fact I suspect they do the same thing. - Andon M. ColemancreateVBO (...)method does some superfluous things such as enabling an immediately disabling attribute pointers. Whether a pointer is enabled or disabled only really matters at the time you callglDrawArrays (...). That state does not affect anything else. Likewise, there is no harm in keeping the VBO bound toGL_ARRAY_BUFFER. Binding 0 is unnecessary unless you use non-VBO based vertex arrays. - Andon M. Colemancolor = vec3(1.0, 1.0, 0.0);. Do you see a yellow triangle? If yes, change it tocolor = vec3(UV, 0.0);. Does the triangle now display a red/green/yellow gradient? This will tell us if the geometry is rendered correctly, and the texture coordinates reach the fragment shader successfully. - Reto Koradi