Search code examples
javatextureslwjglvbo

Texture Not Rendering Properly LWJGL


I am using a VBO to render all of my cubes for my game (since there will be a lot of them) and I want them all to be textured. When I run my code the cube is not textured (instead it looks slightly red because my texture is a brick wall) and only when I am extremely close to the cube the texture shows up (and in the wrong position and much smaller than the cube itself) and yes, the texture is a power of 2 (64x64), so that's not the problem.

Render Class

package engine;

import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.GL_DEPTH_TEST;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER;
import static org.lwjgl.opengl.GL15.GL_STATIC_DRAW;
import static org.lwjgl.opengl.GL15.glBindBuffer;
import static org.lwjgl.opengl.GL15.glBufferData;
import static org.lwjgl.opengl.GL15.glGenBuffers;

import java.io.File;
import java.io.FileInputStream;
import java.nio.FloatBuffer;
import java.util.ArrayList;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Vector3f;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;

public class Render {

    private int amountOfVerts;
    private int vertexSize = 3;
    private int colorSize = 3;
    private int textureSize = 2;
    private FloatBuffer vertData, colorData, textureData;
    private int handle, colorHandle, textureHandle;
    private ArrayList<Cube> cubes = new ArrayList<Cube>();
    private Texture brick;

    public Render() {
        try{
            brick = TextureLoader.getTexture("BMP", new FileInputStream(new File("brick.bmp")));
        }
        catch (Exception e){
            e.printStackTrace();
        }
        glEnable(GL11.GL_TEXTURE_2D);
        glEnable(GL_DEPTH_TEST);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        addCube(new Cube(new Vector3f(0, 0, 0)));

        amountOfVerts = cubes.size() * 24;
        vertData = BufferUtils.createFloatBuffer(amountOfVerts * vertexSize);
        createCubeArray();
        vertData.flip();

        /*
         * colorData = BufferUtils.createFloatBuffer(amountOfVerts *
         * colorSize); float[] color = new float[amountOfVerts *
         * colorSize]; Arrays.fill(color, 1f); colorData.put(color);
         * colorData.flip();
         */

        textureData = BufferUtils.createFloatBuffer(amountOfVerts * textureSize);
        createTextureArray();;
        textureData.flip();

        handle = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, handle); // sets the current
        glBufferData(GL_ARRAY_BUFFER, vertData, GL_STATIC_DRAW); // fills
        glBindBuffer(GL_ARRAY_BUFFER, 0); // unbinds

        /*
        colorHandle = glGenBuffers();
        glBindBuffer(GL_ARRAY_BUFFER, colorHandle); // sets the current
        glBufferData(GL_ARRAY_BUFFER, colorData, GL_STATIC_DRAW); // fills
        glBindBuffer(GL_ARRAY_BUFFER, 0); // unbinds
        */

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

        GL11.glBindTexture(GL11.GL_TEXTURE_2D, brick.getTextureID());
    }

    public void createCubeArray() {
        for (int i = 0; i < cubes.size(); i++) {
            Cube c = cubes.get(i);
            storeVertexData(c.getData());
        }
    }

    public void createTextureArray(){
        for (int i = 0; i < cubes.size(); i++) {
            Cube c = cubes.get(i);
            storeTextureData(c.getTextureData());
        }
    }

    public void storeVertexData(float[] data) {
        vertData.put(data);
    }

    public void storeTextureData(float[] data) {
        textureData.put(data);
    }

public void render() {
        glEnable(GL_DEPTH_TEST);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glBindBuffer(GL_ARRAY_BUFFER, handle);
        GL11.glVertexPointer(vertexSize, GL11.GL_FLOAT, 0, 0L);

        /*
        glBindBuffer(GL_ARRAY_BUFFER, colorHandle);
        GL11.glColorPointer(colorSize, GL11.GL_FLOAT, 0, 0L);
        */

        glBindBuffer(GL_ARRAY_BUFFER, textureHandle);
        GL11.glTexCoordPointer(textureSize, GL11.GL_FLOAT, 0, 0L);

        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
        GL11.glDrawArrays(GL11.GL_QUADS, 0, amountOfVerts);
        GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);



}

Cube Class

    package engine;

import org.lwjgl.util.vector.Vector3f;

public class Cube {

    private Vector3f pos = null;
    private float cubeSize = 100f;

    public Cube(Vector3f pos) {
        this.pos = pos;
    }

    public float[] getData(){
        return new float[] {    pos.x,pos.y,pos.z,
                    pos.x + cubeSize,pos.y,pos.z,
                    pos.x + cubeSize,pos.y + cubeSize,pos.z,
                    pos.x,pos.y + cubeSize,pos.z,

                    pos.x,pos.y,pos.z + cubeSize,
                    pos.x + cubeSize,pos.y,pos.z + cubeSize,
                    pos.x + cubeSize,pos.y + cubeSize,pos.z + cubeSize,
                    pos.x,pos.y + cubeSize,pos.z + cubeSize,

                    pos.x,pos.y,pos.z,
                    pos.x,pos.y,pos.z + cubeSize,
                    pos.x,pos.y + cubeSize,pos.z + cubeSize,
                    pos.x,pos.y + cubeSize,pos.z,

                    pos.x + cubeSize,pos.y,pos.z,
                    pos.x + cubeSize,pos.y,pos.z + cubeSize,
                    pos.x + cubeSize,pos.y + cubeSize,pos.z + cubeSize,
                    pos.x + cubeSize,pos.y + cubeSize,pos.z,

                    pos.x,pos.y,pos.z,
                    pos.x,pos.y,pos.z + cubeSize,
                    pos.x + cubeSize,pos.y,pos.z + cubeSize,
                    pos.x + cubeSize,pos.y,pos.z,

                    pos.x,pos.y + cubeSize,pos.z,
                    pos.x,pos.y + cubeSize,pos.z + cubeSize,
                    pos.x + cubeSize,pos.y + cubeSize,pos.z + cubeSize,
                    pos.x + cubeSize,pos.y + cubeSize,pos.z,
                };
    }

    public float[] getTextureData(){
        return new float[]{0,0, 1,0, 1,1, 0,1};
    }

}

Solution

  • You don't have nearly enough texture coordinates. Since you use 24 vertices per cube, you also need 24 sets of texture coordinates. With 2 floats per set of texture coordinates, getTextureData() needs to return an array of 48 floats. In the code you posted, it returns an array of only 8 floats.

    When using vertex arrays/buffers to render geometry, you always need the same count for all attributes. In this case, 24 positions, 24 sets of texture coordinates, 24 colors (if you want to use colors), etc.