2
votes

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.

1
What does the implementation of this Texture class look like, and why are you binding it before you set the active Texture Image Unit? I would expect to see tex object bound at the same time as glBindTexture (...), in fact I suspect they do the same thing. - Andon M. Coleman
I'm using the Slick Util library's Texture class. I removed tex.bind(), but it didn't make a difference. - Spaxxy
I didn't think it would, but the stray bind seemed odd. Also, your createVBO (...) 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 call glDrawArrays (...). That state does not affect anything else. Likewise, there is no harm in keeping the VBO bound to GL_ARRAY_BUFFER. Binding 0 is unnecessary unless you use non-VBO based vertex arrays. - Andon M. Coleman
I looked at the code, and haven't spotted the problem. We can try to narrow down the problem it that works for you. First experiment: Output a fixed color from the fragment shader. Change the code line in the shader to color = vec3(1.0, 1.0, 0.0);. Do you see a yellow triangle? If yes, change it to color = 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
The second time didn't work! For some reason, it seems that the UV coordinates aren't reaching the shader. - Spaxxy

1 Answers

-2
votes

Maybe addingglEnable(GL_TEXTURE_2D); might solve the problem