LWJGL Binding texture to vertices

Hello, I started with lwjgl and openGL and I have problems binding a texture to a simple quad. The texture is stretched, that the whole quad has a uniform color, no matter what the texture is. I suspect that I use VAOs and VBOs incorrectly, but I don’t see my mistake:

First, the two shaders, which should be correct:
Vertex Shader:

#version 410

in vec3 position;
in vec2 textureCoords;

out vec2 pass_textureCoords;

void main(void){

    gl_Position = vec4(position,1.0);
    pass_textureCoords = textureCoords;
}

Fragment Shader:

#version 410

uniform sampler2D textureSampler;

in vec2 pass_textureCoords;

out vec4 out_Colour;

void main(void){
    out_Colour = texture(textureSampler,pass_textureCoords);
}

My vertices, indices and texture coordinates.

        float[] vertices = {
                -0.5f, 0.5f, 0f,  
                -0.5f, -0.5f, 0f,   
                0.5f, -0.5f, 0f,    
                0.5f, 0.5f, 0f     
        };

        int[] indices = {
                0, 1, 2,
                2, 3, 0
        };
        
        float[] textureCoords = {
                0,0,
                0,1,
                1,1,
                1,0
        };

How I load the texture:

    private int load(String path) {
        IntBuffer width = BufferUtils.createIntBuffer(1);
        IntBuffer height = BufferUtils.createIntBuffer(1);
        IntBuffer components = BufferUtils.createIntBuffer(1);
        ByteBuffer data = stbi_load(path,width,height,components,4);

        if (data == null)
            throw new RuntimeException("Could not load texture!");

        textureID = glGenTextures();

        this.width = width.get();
        this.height = height.get();

        glBindTexture(GL_TEXTURE_2D,textureID);

        glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
        glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);

        glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,this.width,this.height,0,GL_RGBA,GL_UNSIGNED_BYTE,data);

        stbi_image_free(data);
        
        glBindTexture(GL_TEXTURE_2D, 0);
        return textureID;
    }

How I create the VAOs and VBOs and store the indices, vertices and texture coordinates (I suppose that the error is here or/and in the renderer:)
I start by creating a VAO:

    private int createVAO(){
        int vaoID = glGenVertexArrays();
        glBindVertexArray(vaoID);
        return vaoID;
    }

I store the vertex coordinates first in a Buffer, and then in a VBO:


        FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
        buffer.put(data);
        buffer.flip(); //we finished writing, and prepare to read the data

        int vboID = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER,vboID);
        FloatBuffer buffer = storeDataInFloatBuffer(data);
        glBufferData(GL_ARRAY_BUFFER,buffer,GL_STATIC_DRAW); //static data, we won't edit it
        glVertexAttribPointer(0,3, GL_FLOAT,false,0,0);
        glBindBuffer(GL_ARRAY_BUFFER,0);//unbind VBO
        glBindVertexArray(0);

I store the indices:

        int vboIndicesID = glGenBuffers();
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,vboIndicesID);
        IntBuffer buffer = storeDataInIntBuffer(indices); //the same as the FloatBuffer above
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,buffer,GL_STATIC_DRAW);
        glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);

and finally, I store my texture coordinates, with the same method as I use for the vertex coordinates, except for one line:


        glVertexAttribPointer(1,2, GL_FLOAT,false,0,0);

I finish by unbinding the VAO:

        glBindVertexArray(0);

The rendering part:
I bind the texture, I bind the VAO, I enable the VAO (although I’m not completely sure what this step does in the code), I then bind the VBO of the vertices and draw them using drawElements. At the end, I unbind everything:

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D,texturedModel.getTexture().getTextureID());

        // Bind to the VAO that has all the information about the vertices
        glBindVertexArray(model.getVaoID());
        glEnableVertexAttribArray(0);

        // Bind to the index VBO that has all the information about the order of the vertices
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model.getVboIndicesID());
        
        // Draw the vertices
        glDrawElements(GL_TRIANGLES, model.getVertexCount(), GL11.GL_UNSIGNED_INT, 0);

        // Put everything back to default (deselect)
        glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
        glDisableVertexAttribArray(0);

        glBindVertexArray(0);

Can anybody help me out here, what is wrong with this setup of storing data in VBOs and VAOs, as well as loading a texture? Thank you!

You did not enable the vertex attribute 1, which holds your texture coordinates.
Enable it via: [icode]glEnableVertexAttribArray(1);[/icode]
You also only need to enable both vertex attributes once inside your setup code in the VAO.
The vertex attribute enablings are remembered as part of the VAO, as is the bound element array buffer, which you also don’t need to repeatedly bind.

When I enable the attribute 1 in the render loop with

glEnableVertexAttribArray(1);

I get the error code “1282” and I simply get the window with the default colour, and no quad is being rendered.

I’m not sure where I should enable both vertex attributes.

If I understand you correctly, I don’t need to manually enable the vertex attributes and bind the VBO in the render loop, because this is done internally, when I bind the VAO?

Please read chapter 10 of the OpenGL 4.5 Core Specification.
You can only call glEnableVertexAttribArray() when a VAO is currently bound.

EDIT: You can also have a look at this demo to see a working example.

Hello,
Thank you, the example helped me! My problem was that I unbound the VAO after I stored the vertex information (the now commented line), instead of keeping the VAO bound until I put in all the data in, and unbind it at the end. Additionally, I now understand what you meant by

[quote]You also only need to enable both vertex attributes once inside your setup code in the VAO.
[/quote]

        int vboID = glGenBuffers();
        vbos.add(vboID);
        glBindBuffer(GL_ARRAY_BUFFER,vboID);
        FloatBuffer buffer = storeDataInFloatBuffer(data);
        glBufferData(GL_ARRAY_BUFFER,buffer,GL_STATIC_DRAW); //static data, we won't edit it
        glVertexAttribPointer(attributeNumber,coordSize, GL_FLOAT,false,0,0);
        glBindBuffer(GL_ARRAY_BUFFER,0);//unbind VBO
        //glBindVertexArray(0); //VAO was unbound after storing a single VBO...

Thank you!