Search code examples
opengllwjgl

GL11.glDrawElements does not work


First, i'm using LWJGL 3 and OpenGL 3.2

I'm trying to use the "indices" with the function GL11.glDrawElements but nothing rendered in the window.

Buffers generation code ( do not really useindices but I think it can still work) :

public void updateBuffers(Game game, int positionsAttrib, int texCoordsAttrib) { // positionsAttrib and texCoordsAttrib are pointer to shader program attribs

    FloatBuffer positionsBuffer = null;
    FloatBuffer texCoordsBuffer = null;

    IntBuffer indicesBuffer = null;

    try {

        this.vertexCount = this.tiles.size() * 4;

        positionsBuffer = MemoryUtil.memAllocFloat( this.tiles.size() * 3 * 4 );
        texCoordsBuffer = MemoryUtil.memAllocFloat( this.tiles.size() * 2 * 4 );
        indicesBuffer = MemoryUtil.memAllocInt( this.vertexCount );

        int i = 0;

        for ( Entry<TilePosition, Tile> tilesEntry : this.tiles.entrySet() ) {

            TilePosition tilePosition = tilesEntry.getKey();
            Tile tile = tilesEntry.getValue();
            String tileTextureIdentifier = tile.getTextureIdentifier();
            TextureDefinition tileTextureDefinition = game.getTexturesManager().getTextureDefinition("tiles");
            Rectangle tileTextureRectangle = tileTextureDefinition.getTilePosition( tileTextureIdentifier );

            if ( tileTextureRectangle == null ) continue;

            positionsBuffer.put( tilePosition.getX() ).put( tilePosition.getY() + 1 ).put( 0 );
            positionsBuffer.put( tilePosition.getX() + 1 ).put( tilePosition.getY() + 1 ).put( 0 );
            positionsBuffer.put( tilePosition.getX() + 1 ).put( tilePosition.getY() ).put( 0 );
            positionsBuffer.put( tilePosition.getX() ).put( tilePosition.getY() ).put( 0 );

            texCoordsBuffer.put( tileTextureRectangle.x ).put( tileTextureRectangle.y );
            texCoordsBuffer.put( tileTextureRectangle.x + tileTextureRectangle.width ).put( tileTextureRectangle.y );
            texCoordsBuffer.put( tileTextureRectangle.x + tileTextureRectangle.width ).put( tileTextureRectangle.y + tileTextureRectangle.height );
            texCoordsBuffer.put( tileTextureRectangle.x ).put( tileTextureRectangle.y + tileTextureRectangle.height );

            indicesBuffer.put( i ).put( i + 1 ).put( i + 2 ).put( i + 3 );

            i += 4;

        }

        positionsBuffer.flip();
        texCoordsBuffer.flip();
        indicesBuffer.flip();

        this.vao.bind(); // vbo and vao are class VertexBufferObject and VertexArrayObject which save internal id of buffers and most usefull functions

        this.positionsVbo.bind( GL15.GL_ARRAY_BUFFER );
        VertexBufferObject.uploadData( GL15.GL_ARRAY_BUFFER, positionsBuffer, GL15.GL_STATIC_DRAW );
        ShaderProgram.pointVertexAttribute( positionsAttrib, 3, 0, 0 );

        this.texCoordsVbo.bind( GL15.GL_ARRAY_BUFFER );
        VertexBufferObject.uploadData( GL15.GL_ARRAY_BUFFER, texCoordsBuffer, GL15.GL_STATIC_DRAW );
        ShaderProgram.pointVertexAttribute( texCoordsAttrib, 2, 0, 0 );

        this.indicesVbo.bind( GL15.GL_ELEMENT_ARRAY_BUFFER );
        VertexBufferObject.uploadData( GL15.GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL15.GL_STATIC_DRAW );

        VertexArrayObject.unbind();

    } finally {

        if ( positionsBuffer != null ) MemoryUtil.memFree( positionsBuffer );
        if ( texCoordsBuffer != null ) MemoryUtil.memFree( texCoordsBuffer );
        if ( indicesBuffer != null ) MemoryUtil.memFree( indicesBuffer );

    }

}

Used shader program :

// scene.vs :

#version 330 // edit : I have to change this line because of OpenGL used version

layout (location=0) in vec3 position;
layout (location=1) in vec2 texCoord;

out vec2 outTexCoord;

uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;

void main() {

    mat4 mvp = projection * view * model;
    gl_Position = mvp * vec4( position, 1.0 );

    outTexCoord = texCoord;

}

// scene.fs :

#version 330

in vec2 outTexCoord;

out vec4 fragColor;

uniform sampler2D textureSampler;

void main() {

    vec3 vertexColor = vec3( 1.0, 1.0, 1.0 );

    vec4 textureColor = texture( textureSampler, outTexCoord );
    fragColor = vec4( vertexColor, 1.0 ) * textureColor;

}

And the rendering functions :

private void beginRender(Game game, int positionsAttrib, int texCoordsAttrib) {

    Texture texture = game.getTexturesManager().getTextureDefinition("tiles").getTexture();
    GL13.glActiveTexture( GL13.GL_TEXTURE0 );
    texture.bind();

    this.vao.bind();

    ShaderProgram.enableVertexAttribute( positionsAttrib );
    ShaderProgram.enableVertexAttribute( texCoordsAttrib );

}

private void endRender(Game game, int positionsAttrib, int texCoordsAttrib) {

    ShaderProgram.disableVertexAttribute( positionsAttrib );
    ShaderProgram.disableVertexAttribute( texCoordsAttrib );

    VertexArrayObject.unbind();

    Texture.unbind();

}

// render is called by render loop between clear and swapbuffer GL functions
public void render(Game game, int positionsAttrib, int texCoordsAttrib) {

    this.beginRender( game, positionsAttrib, texCoordsAttrib );

    GL11.glDrawElements( GL11.GL_QUADS, this.vertexCount, GL11.GL_UNSIGNED_INT, 0 );

    this.endRender( game, positionsAttrib, texCoordsAttrib );

}

I'm not sure it's very clear, especially with my approximate English ..


Solution

  • You don't expicitely state it, but it looks like you're using a core profile (as you should). However, if so, GL_QUADS will be not available, and your draw call will just result in a GL_INVALID_ENUM error.

    As a side note: since you say you use OpenGL 4.5, I'd strongly recommend that you use OpenGL's debug output feature during development, it will make spotting and interpreting any GL errors much easier, and might furthermore provide useful performance hints.