lwjgl vertex buffer rendert nicht

Tiim

Mitglied
Erstmal hallo zusammen, ich bin neu hier und habe schon mal eine erste Frage.

Ich will ein Voxel Spiel mit LWJGL machen. Um eine hohe performance zu erreichen habe ich vor Vertexbuffers zu verwenden. Dazu habe ich mal diesen Code geschrieben:

Hauptklasse:
Java:
package ch.yourcraft.game;

import ch.yourcraft.game.entity.Chunk;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

/**
 *
 * @author Tim
 */
public class Main {

    /**
     * @param args the command line arguments
     * 
     * TODO: catch LWJGL exception.
     */
    public static void main(String[] args) throws LWJGLException {
        //Display
        Display.setDisplayMode(new DisplayMode(800, 600));
        Display.create();

        Keyboard.create();
        Chunk ch = new Chunk();
        //Init GL
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        //Test Block
        ch.set(1, 1, 1, (byte) 1);
        //Main Loop
        while (!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
            ch.render();
            Display.update();
        }
        //Cleanup
        ch.dispose();
    }
}
Chunk klasse:
Java:
package ch.yourcraft.game.entity;

import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;

/**
 *
 * @author Tim
 */
public class Chunk /*implements Disposable*/ {

    private static final int SIZE_X = 16;
    private static final int SIZE_Y = 16;
    private static final int SIZE_Z = 16;
    private static final int POINTS_PER_QUAD = 4; //3 = Triangles, 4 = Quads
    private static final int SITES_PER_QUBE = 6; //6 = Quads, 12 = Triangles
    private static final int POLYGON_MODE = GL11.GL_QUADS;
    private static final byte BLOCK_AIR = 0;
    private byte[][][] data = new byte[SIZE_X][SIZE_Y][SIZE_Z];
    int vertexBufferObject;
    int vertecies = 0;
    private boolean changed = true;

    public Chunk() {
        vertexBufferObject = GL15.glGenBuffers();
    }

    /**
     * Cleans up the data.
     */
    /*@Override*/
    public void dispose() {
        GL15.glDeleteBuffers(vertexBufferObject);
        data = null;
        changed = false;
    }

    /**
     * Returns the ID of a block
     *
     * @param x
     * @param y
     * @param z
     * @return
     */
    public byte get(int x, int y, int z) {
        try {
            return data[x][y][z];
        } catch (ArrayIndexOutOfBoundsException ex) {
            return 1;
        }
    }

    /**
     * Set the ID of a block.
     *
     * @param x
     * @param y
     * @param z
     * @param id
     */
    public void set(int x, int y, int z, byte id) {
        data[x][y][z] = id;
        changed = true;
    }

    /**
     * Renders the chunk and updates the vbo.
     */
    public void render() {
        if (changed) {
            update();
        }
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferObject);
        GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        GL11.glDrawArrays(POLYGON_MODE, 0, vertecies);
    }

    /**
     * Updates the vertex buffer object.
     */
    private void update() {
        changed = false;
        vertecies = 0;
        IntBuffer verts = BufferUtils.createIntBuffer(SIZE_X * SIZE_Y * SIZE_Z * SITES_PER_QUBE * POINTS_PER_QUAD);
        for (int x = 0; x < SIZE_X; ++x) {
            for (int y = 0; y < SIZE_Y; ++y) {
                for (int z = 0; z < SIZE_Z; ++z) {
                    if (get(x, y, z) == BLOCK_AIR) {
                        continue;
                    }
                    //Left
                    if (get(x - 1, y, z) == BLOCK_AIR) {
                        System.out.println("Left");
                        vertecies += 4;
                        putPoint(x, y, z, verts);
                        putPoint(x, y + 1, z, verts);
                        putPoint(x, y + 1, z + 1, verts);
                        putPoint(x, y, z + 1, verts);
                    }
                    //Right
                    if (get(x + 1, y, z) == BLOCK_AIR) {
                        System.out.println("Right");
                        vertecies += 4;
                        putPoint(x + 1, y, z, verts);
                        putPoint(x + 1, y + 1, z, verts);
                        putPoint(x + 1, y + 1, z + 1, verts);
                        putPoint(x + 1, y, z + 1, verts);
                    }
                    //Behind
                    if (get(x, y, z - 1) == BLOCK_AIR) {
                        System.out.println("Behind");
                        vertecies += 4;
                        putPoint(x, y, z, verts);
                        putPoint(x, y + 1, z, verts);
                        putPoint(x + 1, y + 1, z, verts);
                        putPoint(x + 1, y, z, verts);
                    }
                    //Before
                    if (get(x, y, z + 1) == BLOCK_AIR) {
                        System.out.println("Before");
                        vertecies += 4;
                        putPoint(x, y, z + 1, verts);
                        putPoint(x + 1, y, z + 1, verts);
                        putPoint(x + 1, y + 1, z + 1, verts);
                        putPoint(x, y + 1, z + 1, verts);
                    }
                    //Under
                    if (get(x, y - 1, z) == BLOCK_AIR) {
                        System.out.println("Under");
                        vertecies += 4;
                        putPoint(x, y, z, verts);
                        putPoint(x, y, z + 1, verts);
                        putPoint(x + 1, y, z + 1, verts);
                        putPoint(x + 1, y, z, verts);
                    }
                    //Over
                    if (get(x, y + 1, z) == BLOCK_AIR) {
                        System.out.println("Over");
                        vertecies += 4;
                        putPoint(x, y + 1, z, verts);
                        putPoint(x, y + 1, z + 1, verts);
                        putPoint(x + 1, y + 1, z + 1, verts);
                        putPoint(x + 1, y + 1, z, verts);
                    }
                }
            }
        }
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferObject);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verts, GL15.GL_DYNAMIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
    }

    /**
     * Adds a vertex to a IntBuffer.
     *
     * @param x
     * @param y
     * @param z
     * @param verts the IntBuffer
     */
    private static void putPoint(int x, int y, int z, IntBuffer verts) {
        verts.put(x);
        verts.put(y);
        verts.put(z);
    }
}

Das ganze kompiliert bei mir fehlerfrei und läuft auch ohne Warnungen. Es wird jedoch kein Block gerendert. Könnte mir vieleicht jemand einen Tipp geben was ich falsch gemacht habe und/oder wie es besser gewesen wäre?

Gruss Tiim
 
Bei neueren GL-Versionen muss man IMMER, wenn man ein Vertex Buffer Object verwenden will, auch ein Vertex Array Object erstellen. Ist nicht so aufwändig, grob: Vor dem Erstellen und Binden des VBOs noch mit
glGenVertexArrays(1, vao);
glBindVertexArray(vao[0])
ein VAO erstellen und binden, und ggf. zusehen dass es vor dem Zeichnen gebunden ist. Für Details findet man z.B. 4. OpenGL 4 Vertex Array Objects (VAO) | Swiftless Tutorials oder ... Fancy postet ein KSKB 😉
 
Die Funktion
Code:
glGenVertexArrays()
ist aber in der LWJGL klasse
Code:
GL30
und somit auf meinem Computer der nur OpenGL 2.1.2 darauf hat nicht unterstützt.
Bedeutet das, dass ich auf die VertexBufferObjects verzichten muss?

Gruss Tiim
 
Huhu,

ich hab keine Ahnung wie man es am besten macht, jedoch würd ich am anfang schonmal ne steuerbare Rotation einabuen, um auch mal hinter sich zu schauen 🙂.

Zum obigen Code: du erzeugst ein IntBuffer, Zeichen willst du aber
Java:
GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L);

-> FloatBuffer erzeugen, welcher auch (wie eigentlich auch der INTBuffer) zurückgesetzt werden muss (mit .flip()) ...

Ich weiß nicht, ob man es braucht, aber gezeichnet wurde bei mir erst, als ich eine
Java:
GLU.gluPerspective(30, 800/600, 0.01f, 100);
verwendet hab ...

Java:
package bf;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
 
/**
 *
 * @author Tim
 */
public class Main {
 
    /**
     * @param args the command line arguments
     * 
     * TODO: catch LWJGL exception.
     */
    public static void main(String[] args) throws LWJGLException {
        //Display
        Display.setDisplayMode(new DisplayMode(800, 600));
        Display.create();
 
        Keyboard.create();
        Chunk ch = new Chunk();
        //Init GL
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadIdentity();
        GLU.gluPerspective(30, 800/600, 0.01f, 100);
        //Test Block
        ch.set(1, 0, 1, (byte) 1);
        //Main Loop
        while (!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
        	GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
            ch.render();
            Display.update();
        }
        //Cleanup
        ch.dispose();
    }
}

Java:
package bf;
import static org.lwjgl.opengl.GL11.GL_POINTS;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glDisable;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glPointSize;
import static org.lwjgl.opengl.GL11.glVertex3f;

import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
 
/**
 *
 * @author Tim
 */
public class Chunk /*implements Disposable*/ {
 
    private static final int SIZE_X = 16;
    private static final int SIZE_Y = 16;
    private static final int SIZE_Z = 16;
    private static final int POINTS_PER_QUAD = 4; //3 = Triangles, 4 = Quads
    private static final int SITES_PER_QUBE = 6; //6 = Quads, 12 = Triangles
    private static final int POLYGON_MODE = GL11.GL_QUADS;
    private static final byte BLOCK_AIR = 0;
    private byte[][][] data = new byte[SIZE_X][SIZE_Y][SIZE_Z];
    int vertexBufferObject;
    int vertecies = 0;
    private boolean changed = true;
 
    public Chunk() {
        vertexBufferObject = GL15.glGenBuffers();
    }
 
    /**
     * Cleans up the data.
     */
    /*@Override*/
    public void dispose() {
        GL15.glDeleteBuffers(vertexBufferObject);
        data = null;
        changed = false;
    }
 
    /**
     * Returns the ID of a block
     *
     * @param x
     * @param y
     * @param z
     * @return
     */
    public byte get(int x, int y, int z) {
        try {
            return data[x][y][z];
        } catch (ArrayIndexOutOfBoundsException ex) {
            return 1;
        }
    }
 
    /**
     * Set the ID of a block.
     *
     * @param x
     * @param y
     * @param z
     * @param id
     */
    public void set(int x, int y, int z, byte id) {
        data[x][y][z] = id;
        changed = true;
    }
 
    /**
     * Renders the chunk and updates the vbo.
     */
    float r;
    public void render() {
    	 if (changed) {
             update();
             Mouse.setGrabbed(true);
         }
         
         glPointSize(10);
         glBegin(GL_POINTS);
          GL11.glColor3f(1,0,0);
         glVertex3f(0,0,-2);
         GL11.glColor3f(1,0,0);
         glVertex3f(0,0,2);
         
         GL11.glColor3f(0,1,0);
         glVertex3f(-2,0,0);
         GL11.glColor3f(0,1,0);
         glVertex3f(2,0,0);
         glEnd();
        r+=Mouse.getDX()/100000.0f;
        GL11.glRotatef(r,0,1,0);
        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferObject);
        GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        
        GL11.glDrawArrays(POLYGON_MODE, 0, vertecies);
    }
 
    /**
     * Updates the vertex buffer object.
     */
    private void update() {
        changed = false;
        vertecies = 0;
        FloatBuffer verts = BufferUtils.createFloatBuffer(SIZE_X * SIZE_Y * SIZE_Z * SITES_PER_QUBE * POINTS_PER_QUAD);
        for (int x = 0; x < SIZE_X; ++x) {
            for (int y = 0; y < SIZE_Y; ++y) {
                for (int z = 0; z < SIZE_Z; ++z) {
                    if (get(x, y, z) == BLOCK_AIR) {
                        continue;
                    }
                    //Left
                    if (get(x - 1, y, z) == BLOCK_AIR) {
                        System.out.println("Left");
                        vertecies += 4;
                        putPoint(x, y, z, verts);
                        putPoint(x, y + 1, z, verts);
                        putPoint(x, y + 1, z + 1, verts);
                        putPoint(x, y, z + 1, verts);
                    }
                    //Right
                    if (get(x + 1, y, z) == BLOCK_AIR) {
                        System.out.println("Right");
                        vertecies += 4;
                        putPoint(x + 1, y, z, verts);
                        putPoint(x + 1, y + 1, z, verts);
                        putPoint(x + 1, y + 1, z + 1, verts);
                        putPoint(x + 1, y, z + 1, verts);
                    }
                    //Behind
                    if (get(x, y, z - 1) == BLOCK_AIR) {
                        System.out.println("Behind");
                        vertecies += 4;
                        putPoint(x, y, z, verts);
                        putPoint(x, y + 1, z, verts);
                        putPoint(x + 1, y + 1, z, verts);
                        putPoint(x + 1, y, z, verts);
                    }
                    //Before
                    if (get(x, y, z + 1) == BLOCK_AIR) {
                        System.out.println("Before");
                        vertecies += 4;
                        putPoint(x, y, z + 1, verts);
                        putPoint(x + 1, y, z + 1, verts);
                        putPoint(x + 1, y + 1, z + 1, verts);
                        putPoint(x, y + 1, z + 1, verts);
                    }
                    //Under
                    if (get(x, y - 1, z) == BLOCK_AIR) {
                        System.out.println("Under");
                        vertecies += 4;
                        putPoint(x, y, z, verts);
                        putPoint(x, y, z + 1, verts);
                        putPoint(x + 1, y, z + 1, verts);
                        putPoint(x + 1, y, z, verts);
                    }
                    //Over
                    if (get(x, y + 1, z) == BLOCK_AIR) {
                        System.out.println("Over");
                        vertecies += 4;
                        putPoint(x, y + 1, z, verts);
                        putPoint(x, y + 1, z + 1, verts);
                        putPoint(x + 1, y + 1, z + 1, verts);
                        putPoint(x + 1, y + 1, z, verts);
                    }
                }
            }
        }
        verts.flip();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferObject);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verts, GL15.GL_DYNAMIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
    }
 
    /**
     * Adds a vertex to a IntBuffer.
     *
     * @param x
     * @param y
     * @param z
     * @param verts the IntBuffer
     */
    private static void putPoint(int x, int y, int z, FloatBuffer verts) {
        verts.put(x);
        verts.put(y);
        verts.put(z);
    }
}

Nun wird neben den kleinen Orientierungspunkten auch ein großes Rechteck gezeichnet ... wie gesagt, ist wohl noch einiges zu tun und ich weiß auch nicht wie man es am besten macht, aber zumindest "funktioniert" das VBO nun.
 
Moin,

das mit den VAOs gilt eigentlich nur in den Core Profilen. Wenn man nichts angibt, wird normalerweise ein Compatibility Context erzeugt, welcher auch mit VBOs ohne VAOs klarkommt.

Oben im Code sind (mindestens) 3 Sachen nicht ganz korrekt:

1. Die Projektionsmatrix ist ein wenig dürftig und stellt so nur den halben Einheitswürfel dar. Der Beispiel-Chunk liegt aber schon außerhalb und wird deshalb gar nicht dargestellt.
2. verts ist vom Typ IntBuffer, glVertexPointer erwartet aber floats
3. Nach dem füllen von verts fehlt ein verts.rewind();


Edit: JCODA hat ja jetzt schon scheinbar lauffähigen Code gezeigt, schön! 😉


Viele Grüße,
Fancy
 
So, vielen dank erstmal. Ich hab den Code jetzt etwas erweitert, und will jetzt den Würfel mit einer Textur bekleben, die ich, mit mehreren anderen Texturen in einem 1024*1024 Png Bild habe. Nun wollte ich die Textur Koordinaten auch in einem VBO haben. Leider wird der Würfel ganz normal, ohne Textur angezeigt.

Hier mal mein Code:

Java:
package ch.yourcraft.game;

import ch.yourcraft.data.Loader;
import ch.yourcraft.game.entity.Chunk;
import java.io.IOException;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;
 
/**
 *
 * @author Tim
 */
public class Main {
 
    /**
     * @param args the command line arguments
     * 
     * TODO: catch LWJGL and IO exception.
     */
    public static void main(String[] args) throws LWJGLException, IOException {
        //Display
        Display.setDisplayMode(new DisplayMode(800, 600));
        Display.create();
 
        Keyboard.create();
        Mouse.setGrabbed(true);
        Chunk ch = new Chunk();
        //Init GL
        GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadIdentity();
        GLU.gluPerspective(30, 800/600, 0.01f, 100);
        GL11.glTranslatef(0, 0, -15);
        
        //Test Block
        ch.set(1, 1, 1, (byte) 1);
        //Load Asset
        Loader.loadAll();
        //Main Loop
        while (!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            ch.render();
            Display.update();
        }
        //Cleanup
        ch.dispose();
    }
}
Java:
package ch.yourcraft.game.entity;

import ch.yourcraft.data.ImageLoader;
import java.nio.FloatBuffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.newdawn.slick.opengl.Texture;

/**
 *
 * @author Tim
 */
public class Chunk implements Disposable {

    //Static
    private static final int SIZE_X = 16;
    private static final int SIZE_Y = 16;
    private static final int SIZE_Z = 16;
    private static final byte BLOCK_AIR = 0;
    private static Texture terrain;
    //Member
    private byte[][][] data = new byte[SIZE_X][SIZE_Y][SIZE_Z];
    int vertexVBO;
    int texVBO;
    int vertecies = 0;
    private boolean changed = true;

    public Chunk() {
        vertexVBO = GL15.glGenBuffers();
        texVBO = GL15.glGenBuffers();
    }

    /**
     * Cleans up the data.
     */
    @Override
    public void dispose() {
        GL15.glDeleteBuffers(vertexVBO);
        GL15.glDeleteBuffers(texVBO);
        data = null;
        changed = false;
    }

    /**
     * Returns the ID of a block
     *
     * @param x
     * @param y
     * @param z
     * @return
     */
    public byte get(int x, int y, int z) {
        try {
            return data[x][y][z];
        } catch (ArrayIndexOutOfBoundsException ex) {
            return -1;
            //TODO This is a dirty hack.
        }
    }

    /**
     * Set the ID of a block.
     *
     * @param x
     * @param y
     * @param z
     * @param id
     */
    public void set(int x, int y, int z, byte id) {
        data[x][y][z] = id;
        changed = true;
    }

    /**
     * Renders the chunk and updates the vbo.
     */
    public void render() {
        if (terrain == null && (terrain = ImageLoader.getInstance().getTerrain()) == null) {
            throw new IllegalStateException("Terrain must be initialized first.");
        }
        if (changed) {
            update();
        }

        debugPoints();
        {
            float dx = Mouse.getDX() / 10.0f;
            float dy = Mouse.getDY() / 10.0f;
            GL11.glRotatef(dx, 0, 1, 0);
            GL11.glRotatef(-dy, 1, 0, 0);
        }
        
        terrain.bind();
        //Buffers
        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexVBO);
        GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L);

        //Tex
        GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, texVBO);
        GL11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0L);

        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

        GL11.glDrawArrays(GL11.GL_QUADS, 0, vertecies);
    }

    /**
     * Updates the vertex buffer object.
     */
    private void update() {
        changed = false;
        vertecies = 0;
        FloatBuffer verts = BufferUtils.createFloatBuffer(SIZE_X * SIZE_Y * SIZE_Z * 6 * 4);
        FloatBuffer tex = BufferUtils.createFloatBuffer(SIZE_X * SIZE_Y * SIZE_Z * 6 * 4);
        for (int x = 0; x < SIZE_X; ++x) {
            for (int y = 0; y < SIZE_Y; ++y) {
                for (int z = 0; z < SIZE_Z; ++z) {
                    if (get(x, y, z) == BLOCK_AIR) {
                        continue;
                    }
                    //Left
                    if (get(x - 1, y, z) == BLOCK_AIR) {
                        System.out.println("Left");
                        putPoint(x, y, z, verts);
                        putPoint(x, y + 1, z, verts);
                        putPoint(x, y + 1, z + 1, verts);
                        putPoint(x, y, z + 1, verts);
                        putTexture(1 / 16, 1 / 16, tex);
                    }
                    //Right
                    if (get(x + 1, y, z) == BLOCK_AIR) {
                        System.out.println("Right");
                        putPoint(x + 1, y, z, verts);
                        putPoint(x + 1, y + 1, z, verts);
                        putPoint(x + 1, y + 1, z + 1, verts);
                        putPoint(x + 1, y, z + 1, verts);
                        putTexture(1 / 16, 1 / 16, tex);
                    }
                    //Behind
                    if (get(x, y, z - 1) == BLOCK_AIR) {
                        System.out.println("Behind");
                        putPoint(x, y, z, verts);
                        putPoint(x, y + 1, z, verts);
                        putPoint(x + 1, y + 1, z, verts);
                        putPoint(x + 1, y, z, verts);
                        putTexture(1 / 16, 1 / 16, tex);
                    }
                    //Before
                    if (get(x, y, z + 1) == BLOCK_AIR) {
                        System.out.println("Before");
                        putPoint(x, y, z + 1, verts);
                        putPoint(x + 1, y, z + 1, verts);
                        putPoint(x + 1, y + 1, z + 1, verts);
                        putPoint(x, y + 1, z + 1, verts);
                        putTexture(1 / 16, 1 / 16, tex);
                    }
                    //Under
                    if (get(x, y - 1, z) == BLOCK_AIR) {
                        System.out.println("Under");
                        putPoint(x, y, z, verts);
                        putPoint(x, y, z + 1, verts);
                        putPoint(x + 1, y, z + 1, verts);
                        putPoint(x + 1, y, z, verts);
                        putTexture(1 / 16, 1 / 16, tex);
                    }
                    //Over
                    if (get(x, y + 1, z) == BLOCK_AIR) {
                        System.out.println("Over");
                        putPoint(x, y + 1, z, verts);
                        putPoint(x, y + 1, z + 1, verts);
                        putPoint(x + 1, y + 1, z + 1, verts);
                        putPoint(x + 1, y + 1, z, verts);
                        putTexture(1 / 16, 1 / 16, tex);
                    }
                }
            }
        }
        vertecies = verts.position() / 3;
        System.out.println("Vertecies: " + vertecies);

        verts.flip();
        tex.flip();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexVBO);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verts, GL15.GL_DYNAMIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, texVBO);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, tex, GL15.GL_DYNAMIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

    }

    /**
     * Adds a vertex to a IntBuffer.
     *
     * @param x
     * @param y
     * @param z
     * @param verts the IntBuffer
     */
    private static void putPoint(int x, int y, int z, FloatBuffer verts) {
        verts.put(x);
        verts.put(y);
        verts.put(z);
    }

    private static void putTexture(float x, float y, FloatBuffer verts) {
        putPoint(0, 0, verts);
        putPoint(x, 0, verts);
        putPoint(x, y, verts);
        putPoint(0, y, verts);
    }

    private static void putPoint(float x, float y, FloatBuffer verts) {
        verts.put(x);
        verts.put(y);
    }

    private void debugPoints() {
        GL11.glPointSize(3);
        GL11.glBegin(GL11.GL_POINTS);
        {
            GL11.glColor3f(1, 0, 0);
            GL11.glVertex3f(0, 0, -2);
            GL11.glColor3f(1, 0, 0);
            GL11.glVertex3f(0, 0, 2);

            GL11.glColor3f(0, 1, 0);
            GL11.glVertex3f(-2, 0, 0);
            GL11.glColor3f(0, 1, 0);
            GL11.glVertex3f(2, 0, 0);
            GL11.glColor3f(0, 0, 1);
            GL11.glVertex3f(0, 0, 0);
        }
        GL11.glEnd();
    }
}
Java:
package ch.yourcraft.data;

import java.io.IOException;

public abstract class Loader {

    private static final Loader[] instances = new Loader[]{
        ImageLoader.getInstance(),
    };

    public Loader() {

    }
    
    public static void loadAll() throws IOException {
        System.out.println("Load All:");
        for (Loader l : instances) {
            System.out.println("Load " + l.getClass());
            l.load();
        }
    }

    public abstract void load() throws IOException;
}
Java:
package ch.yourcraft.data;

import ch.yourcraft.data.Loader;
import java.io.IOException;
import java.io.InputStream;
import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;
import org.newdawn.slick.util.ResourceLoader;

/**
 *
 * @author Tim
 */
public class ImageLoader extends Loader {

    private static final ImageLoader INSTANCE = new ImageLoader();
    private static final String FORMAT = "PNG";
    private static Texture terrain;

    ImageLoader() {
        super();
    }

    @Override
    public void load() throws IOException {
        terrain = loadTex("ch/yourcraft/data/textures/blocks/terrain.png");
    }

    private static Texture loadTex(String path) throws IOException {
        System.out.println(" - Load " + path);
        return TextureLoader.getTexture(FORMAT, srcAsStr(path));
    }

    private static InputStream srcAsStr(String src) {
        return ResourceLoader.getResourceAsStream(src);
    }

    public static ImageLoader getInstance() {
        return INSTANCE;
    }

    public Texture getTerrain() {
        return terrain;
    }
}
Könnt ihr irgendwelche Tipps geben, oder seht ihr den Fehler vieleicht?
Gruss Tiim

[EDIT] Artefakt von sinnlosem ausprobieren entfernt. [/EDIT]
 
Zuletzt bearbeitet:
ohne auf weitere Fehler zu achten:

Java:
 putTexture(1f / 16, 1f / 16, tex);


1/16 = 0, da hier nur mit Integern gerechnet wird.

=>
Java:
 putTexture(1.0f / 16, 1.0f / 16, tex);
 
Vielen Dank, das hatte ich gar nicht bemerkt..
Leider wird der Würfel immer noch ohne Textur, und in der Farbe des zuletzt gezeichneten Punktes gezeichnet. 🙁
 
Etwa so:

Java:
package ch.yourcraft.game;

import java.io.IOException;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;

/**
 *
 * @author Tim
 */
public class Main {

    /**
     * @param args the command line arguments
     * 
     * TODO: catch LWJGL and IO exception.
     */
    public static void main(final String[] args) throws LWJGLException, IOException {
        //Display
        Display.setDisplayMode(new DisplayMode(800, 600));
        Display.create();

        Keyboard.create();
        Mouse.setGrabbed(true);
        final Chunk ch = new Chunk();
        //Init GL
        GL11.glEnable(GL11.GL_DEPTH_TEST);
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        GL11.glTexEnvi(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_REPLACE);
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GLU.gluPerspective(30, 800 / 600, 0.01f, 100);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadIdentity();
        GL11.glTranslatef(0, 0, -15);

        //Test Block
        ch.set(1, 1, 1, (byte) 1);
        //Load Asset
        Loader.loadAll();
        //Main Loop
        while (!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
            ch.render();
            Display.update();
        }
        //Cleanup
        ch.dispose();
    }
}

Java:
package ch.yourcraft.game;

import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.newdawn.slick.opengl.Texture;

/**
 *
 * @author Tim
 */
public class Chunk implements Disposable {

    //Static
    private static final int SIZE_X = 16;
    private static final int SIZE_Y = 16;
    private static final int SIZE_Z = 16;
    private static final byte BLOCK_AIR = 0;
    private static Texture terrain;
    //Member
    private byte[][][] data = new byte[SIZE_X][SIZE_Y][SIZE_Z];
    int vertexVBO;
    int texVBO;
    int vertecies = 0;
    private boolean changed = true;

    public Chunk() {
        vertexVBO = GL15.glGenBuffers();
        texVBO = GL15.glGenBuffers();
    }

    /**
     * Cleans up the data.
     */
    @Override
    public void dispose() {
        GL15.glDeleteBuffers(vertexVBO);
        GL15.glDeleteBuffers(texVBO);
        data = null;
        changed = false;
    }

    /**
     * Returns the ID of a block
     *
     * @param x
     * @param y
     * @param z
     * @return
     */
    public byte get(final int x, final int y, final int z) {
        try {
            return data[x][y][z];
        } catch (final ArrayIndexOutOfBoundsException ex) {
            return -1;
            //TODO This is a dirty hack.
        }
    }

    /**
     * Set the ID of a block.
     *
     * @param x
     * @param y
     * @param z
     * @param id
     */
    public void set(final int x, final int y, final int z, final byte id) {
        data[x][y][z] = id;
        changed = true;
    }

    /**
     * Renders the chunk and updates the vbo.
     */
    public void render() {
        if (terrain == null && (terrain = ImageLoader.getInstance().getTerrain()) == null)
            throw new IllegalStateException("Terrain must be initialized first.");
        if (changed)
            update();

        debugPoints();
        {
            final float dx = Mouse.getDX() / 10.0f;
            final float dy = Mouse.getDY() / 10.0f;
            GL11.glRotatef(dx, 0, 1, 0);
            GL11.glRotatef(-dy, 1, 0, 0);
        }

        terrain.bind();

        //Buffers
        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexVBO);
        GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0L);

        //Tex
        GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, texVBO);
        GL11.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0L);

        GL11.glDrawArrays(GL11.GL_QUADS, 0, vertecies);
    }

    /**
     * Updates the vertex buffer object.
     */
    private void update() {
        changed = false;
        vertecies = 0;
        final FloatBuffer verts = BufferUtils.createFloatBuffer(SIZE_X * SIZE_Y * SIZE_Z * 6 * 4);
        final FloatBuffer tex = BufferUtils.createFloatBuffer(SIZE_X * SIZE_Y * SIZE_Z * 6 * 4);
        for (int x = 0; x < SIZE_X; ++x)
            for (int y = 0; y < SIZE_Y; ++y)
                for (int z = 0; z < SIZE_Z; ++z) {
                    if (get(x, y, z) == BLOCK_AIR)
                        continue;
                    //Left
                    if (get(x - 1, y, z) == BLOCK_AIR) {
                        System.out.println("Left");
                        putPoint(x, y, z, verts);
                        putPoint(x, y + 1, z, verts);
                        putPoint(x, y + 1, z + 1, verts);
                        putPoint(x, y, z + 1, verts);
                        putTexture(1 / 16.0f, 1 / 16.0f, tex);
                    }
                    //Right
                    if (get(x + 1, y, z) == BLOCK_AIR) {
                        System.out.println("Right");
                        putPoint(x + 1, y, z, verts);
                        putPoint(x + 1, y + 1, z, verts);
                        putPoint(x + 1, y + 1, z + 1, verts);
                        putPoint(x + 1, y, z + 1, verts);
                        putTexture(1 / 16.0f, 1 / 16.0f, tex);
                    }
                    //Behind
                    if (get(x, y, z - 1) == BLOCK_AIR) {
                        System.out.println("Behind");
                        putPoint(x, y, z, verts);
                        putPoint(x, y + 1, z, verts);
                        putPoint(x + 1, y + 1, z, verts);
                        putPoint(x + 1, y, z, verts);
                        putTexture(1 / 16.0f, 1 / 16.0f, tex);
                    }
                    //Before
                    if (get(x, y, z + 1) == BLOCK_AIR) {
                        System.out.println("Before");
                        putPoint(x, y, z + 1, verts);
                        putPoint(x + 1, y, z + 1, verts);
                        putPoint(x + 1, y + 1, z + 1, verts);
                        putPoint(x, y + 1, z + 1, verts);
                        putTexture(1 / 16.0f, 1 / 16.0f, tex);
                    }
                    //Under
                    if (get(x, y - 1, z) == BLOCK_AIR) {
                        System.out.println("Under");
                        putPoint(x, y, z, verts);
                        putPoint(x, y, z + 1, verts);
                        putPoint(x + 1, y, z + 1, verts);
                        putPoint(x + 1, y, z, verts);
                        putTexture(1 / 16.0f, 1 / 16.0f, tex);
                    }
                    //Over
                    if (get(x, y + 1, z) == BLOCK_AIR) {
                        System.out.println("Over");
                        putPoint(x, y + 1, z, verts);
                        putPoint(x, y + 1, z + 1, verts);
                        putPoint(x + 1, y + 1, z + 1, verts);
                        putPoint(x + 1, y + 1, z, verts);
                        putTexture(1 / 16.0f, 1 / 16.0f, tex);
                    }
                }
        vertecies = verts.position() / 3;
        System.out.println("Vertecies: " + vertecies);

        verts.flip();
        tex.flip();
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexVBO);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verts, GL15.GL_DYNAMIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, texVBO);
        GL15.glBufferData(GL15.GL_ARRAY_BUFFER, tex, GL15.GL_DYNAMIC_DRAW);
        GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);

    }

    /**
     * Adds a vertex to a IntBuffer.
     *
     * @param x
     * @param y
     * @param z
     * @param verts the IntBuffer
     */
    private static void putPoint(final int x, final int y, final int z, final FloatBuffer verts) {
        verts.put(x);
        verts.put(y);
        verts.put(z);
    }

    private static void putTexture(final float x, final float y, final FloatBuffer verts) {
        putPoint(0, 0, verts);
        putPoint(x, 0, verts);
        putPoint(x, y, verts);
        putPoint(0, y, verts);
    }

    private static void putPoint(final float x, final float y, final FloatBuffer verts) {
        verts.put(x);
        verts.put(y);
    }

    private void debugPoints() {
        GL11.glPointSize(3);
        GL11.glDisable(GL11.GL_TEXTURE_2D);
        GL11.glBegin(GL11.GL_POINTS);
        {

            GL11.glColor3f(1, 0, 0);
            GL11.glVertex3f(0, 0, -2);
            GL11.glColor3f(1, 0, 0);
            GL11.glVertex3f(0, 0, 2);

            GL11.glColor3f(0, 1, 0);
            GL11.glVertex3f(-2, 0, 0);
            GL11.glColor3f(0, 1, 0);
            GL11.glVertex3f(2, 0, 0);
            GL11.glColor3f(0, 0, 1);
            GL11.glVertex3f(0, 0, 0);

        }
        GL11.glEnd();
        GL11.glEnable(GL11.GL_TEXTURE_2D);
    }
}

Vielleicht ist das für Dich auch noch lesenswert: Vertex Specification Best Practices

Viele Grüße,
Fancy
 

Zurück
Oben