Search code examples
javaopengltextureslwjglvbo

Simple Texturing with LWJGL and VBOs does not work


I wrote a little 3D program with VBO, but failed with the textures. Loading them is fine but they just are not displayed. So I wrinte a tiny texture renderer for VBO textures and also took what was in this topic: VBO with texture in LWJGL. But there is still just nothing rendered. Help me just to make this code show a Texture ;)

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;

import java.io.IOException;
import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;

public class VBOTextureDemo {

private static Texture texture;

public static void main(String[] args) {
    try {
        Display.setDisplayMode(new DisplayMode(500, 500));
        Display.setTitle("Texture");
        Display.create();
    } catch (LWJGLException e) {
        e.printStackTrace();
        Display.destroy();
        System.exit(1);
    }

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(1, -1, 1, -1, 1, 1);
    glMatrixMode(GL_MODELVIEW);
    glEnable(GL_TEXTURE_2D);
    glLoadIdentity();


    try {
        texture = TextureLoader.getTexture("PNG",
                ResourceLoader.getResourceAsStream("res/images/grass.png"));
    } catch (IOException e) {
        e.printStackTrace();
    }

    final int amountOfVertices = 6;
    final int vertexSize = 3;
    final int texSize = 2;

    FloatBuffer vertexData = BufferUtils.createFloatBuffer(amountOfVertices
            * vertexSize);
    vertexData.put(new float[] { -10f, 10f, 0f, }); // Vertex
    vertexData.put(new float[] { 10f, 10f, 0f, }); // Vertex
    vertexData.put(new float[] { -10f, -10f, 0f, }); // Vertex

    vertexData.put(new float[] { 10f, -10f, 0f, }); // Vertex
    vertexData.put(new float[] { -10f, -10f, 0f, }); // Vertex
    vertexData.put(new float[] { 10f, 10f, 0f, }); // Vertex;
    vertexData.flip();

    FloatBuffer textureData = BufferUtils
            .createFloatBuffer(amountOfVertices * texSize);
    textureData.put(new float[] { 0f, 1f, }); // Texture Coordinate
    textureData.put(new float[] { 1f, 1f, }); // Texture Coordinate
    textureData.put(new float[] { 0f, 0f, }); // Texture Coordinate

    textureData.put(new float[] { 1f, 0f, }); // Texture Coordinate
    textureData.put(new float[] { 0f, 0f, }); // Texture Coordinate
    textureData.put(new float[] { 1f, 1f, }); // Texture Coordinate
    textureData.flip();

    glBindTexture(GL_TEXTURE_2D, texture.getTextureID());

    texture.bind();

    int vboVertexHandle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
    glBufferData(GL_ARRAY_BUFFER, vertexData, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);


    int vboTexCoordHandle = texture.getTextureID();
    glBindBuffer(GL_ARRAY_BUFFER, vboTexCoordHandle);
    glBufferData(GL_ARRAY_BUFFER, textureData, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    glClearColor(0.5f, 0.1f, 0f, 1f);



    while (!Display.isCloseRequested()) {
        glClear(GL_COLOR_BUFFER_BIT);

        glBindBuffer(GL_ARRAY_BUFFER, vboVertexHandle);
        glVertexPointer(vertexSize, GL_FLOAT, 0, 0L);

        glBindBuffer(GL_ARRAY_BUFFER, vboTexCoordHandle);
        glTexCoordPointer(2, GL_FLOAT, 0, 0);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glDrawArrays(GL_TRIANGLES, 0, amountOfVertices);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glDisableClientState(GL_VERTEX_ARRAY);

        Display.update();
        Display.sync(60);
    }

    glDeleteBuffers(vboVertexHandle);
    glDeleteBuffers(vboTexCoordHandle);
    texture.release();


    Display.destroy();
    System.exit(0);
}

}


Solution

  • I didn't test your code, but there is 2 things I guess that might be bugging!

    1. The vertices are in the wrong order!
    2. The Texture doesn't get loaded, and thereby when calling the bind, nothing gets bound!

    Simple Texture Test

    Just for testing try using the deprecated methods

    • glBegin(GL_TRIANGLES);
    • glVertex3f(x, y, z);
    • glTexCoord2f(u, v);

    Remember to bind the texture of course, but if rendering the triangles using the deprecated methods works, then it's certainly not a texturing problem. Though if nothing appears it might be a texturing program (or the vertices are in the wrong order).

    Simple Texture Test Rendering | Code

    texture.bind();
    
    glBegin(GL_TRIANGLES);
    
        glTexCoord2f(0f, 1f);
        glVertex3f(-1f, 1f, 0f);
        glTexCoord2f(1f, 1f);
        glVertex3f(1f, 1f, 0f);
        glTexCoord2f(0f, 0f);
        glVertex3f(-1f, -1f, 0f);
    
        glTexCoord2f(1f, 0f);
        glVertex3f(1f, -1f, 0f);
        glTexCoord2f(0f, 0f);
        glVertex3f(-1f, -1f, 0f);
        glTexCoord2f(1f, 1f);
        glVertex3f(1f, 1f, 0f);
    
    glEnd();
    
    texture.unbind();
    

    VBO Test

    So if the reason it isn't showing is because of the vertices are in the wrong order, then try using the following code, for creating and rendering a Textured VBO.

    Creating the VBO | Code

    int vertices = 6;
    
    int vertex_size = 3; // X, Y, Z,
    int texture_size = 2; // U, V,
    
    FloatBuffer vertex_data = BufferUtils.createFloatBuffer(vertices * vertex_size);
    vertex_data.put(new float[] { -1f, 1f, 0f, }); // Vertex
    vertex_data.put(new float[] { 1f, 1f, 0f, }); // Vertex
    vertex_data.put(new float[] { -1f, -1f, 0f, }); // Vertex
    
    vertex_data.put(new float[] { 1f, -1f, 0f, }); // Vertex
    vertex_data.put(new float[] { -1f, -1f, 0f, }); // Vertex
    vertex_data.put(new float[] { 1f, 1f, 0f, }); // Vertex
    
    FloatBuffer texture_data = BufferUtils.createFloatBuffer(vertices * texture_size);
    texture_data.put(new float[] { 0f, 1f, }); // Texture Coordinate
    texture_data.put(new float[] { 1f, 1f, }); // Texture Coordinate
    texture_data.put(new float[] { 0f, 0f, }); // Texture Coordinate
    
    texture_data.put(new float[] { 1f, 0f, }); // Texture Coordinate
    texture_data.put(new float[] { 0f, 0f, }); // Texture Coordinate
    texture_data.put(new float[] { 1f, 1f, }); // Texture Coordinate
    
    vertex_data.flip();
    texture_data.flip();
    
    int vbo_vertex_handle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
    glBufferData(GL_ARRAY_BUFFER, vertex_data, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    int vbo_texture_handle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vbo_texture_handle);
    glBufferData(GL_ARRAY_BUFFER, texture_data, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    

    Rendering the VBO | Code

    Also try actually binding and unbinding the texture! That could actually in some weird way be the problem too.

    texture.bind();
    
    glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
    glVertexPointer(vertex_size, GL_FLOAT, 0, 0l);
    
    glBindBuffer(GL_ARRAY_BUFFER, vbo_texture_handle);
    glTexCoordPointer(texture_size, GL_FLOAT, 0, 0l);
    
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
    glDrawArrays(GL_TRIANGLES, 0, vertices); // The vertices is of course the max vertices count, in this case 6
    
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    texture.unbind();
    

    Of course when working with textures, remember to call glEnable(GL_TEXTURE_2D);

    Edit

    I found the error in the code, you actually say.

    int vboTexCoordHandle = texture.getTextureID();
    glBindBuffer(GL_ARRAY_BUFFER, vboTexCoordHandle);
    glBufferData(GL_ARRAY_BUFFER, textureData, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    

    But you need to say.

    int vboTexCoordHandle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vboTexCoordHandle);
    glBufferData(GL_ARRAY_BUFFER, textureData, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);