LWJGL Forum

Programming => OpenGL => Topic started by: Rainer on December 11, 2007, 08:34:58

Title: Vertex Array / VBO
Post by: Rainer on December 11, 2007, 08:34:58
I need to render a lot of dynamic poligons.
After some searching i found that VBO would be the right solution to do this.
Now there are some tutorials about VBO (http://lwjgl.org/wiki/doku.php/lwjgl/tutorials/opengl/basicvbo and http://lwjgl.org/wiki/doku.php/lwjgl/tutorials/opengl/speedyvbo), but they tell me i should understand vertex arrays first.
So i googled for lwjgl vertex array, but can't find any tutorial about how to do the vertex arrays in lwjgl.
Is there somewhere a tutorial i couldn't find, or can someone give me an instruction?
Title: Re: Vertex Array / VBO
Post by: grom358 on December 11, 2007, 10:04:54
Here is an example of using vertex array to draw a Cube. With LWJGL you have to use nio buffers for the arrays.


private void initGL() {
        GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
        GL11.glShadeModel(GL11.GL_SMOOTH); // Enable Smooth Shading
        GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background
        GL11.glClearDepth(1.0); // Depth Buffer Setup
        GL11.glEnable(GL11.GL_DEPTH_TEST); // Enables Depth Testing
        GL11.glDepthFunc(GL11.GL_LEQUAL); // The Type Of Depth Testing To Do

        GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
        GL11.glLoadIdentity(); // Reset The Projection Matrix

        // Calculate The Aspect Ratio Of The Window
        GLU.gluPerspective(
          45.0f,
          (float) WINDOW_WIDTH / (float) WINDOW_HEIGHT,
          0.1f,
          100.0f);
        GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix

        // Really Nice Perspective Calculations
        GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
     
       
        vertices = BufferUtils.createFloatBuffer(3 * 4 * 6);
        vertices.put(new float[] {
        -1.0f, -1.0f, 1.0f,
        1.0f, -1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f,
       
        -1.0f, -1.0f, -1.0f,
        -1.0f, 1.0f, -1.0f,
        1.0f, 1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
       
        -1.0f, 1.0f, -1.0f,
        -1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, -1.0f,
       
        -1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, 1.0f,
        -1.0f, -1.0f, 1.0f,
       
        1.0f, -1.0f, -1.0f,
        1.0f, 1.0f, -1.0f,
        1.0f, 1.0f, 1.0f,
        1.0f, -1.0f, 1.0f,
       
        -1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, -1.0f});   
    }

/**
* Render the current frame
*/
private void render() {
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer

        GL11.glLoadIdentity(); // Reset The Current Modelview Matrix

        GL11.glTranslatef(0.0f, 0.0f, z); // Move Into The Screen 5 Units
        GL11.glRotatef(xrot, 1.0f, 0.0f, 0.0f); // Rotate On The X Axis
        GL11.glRotatef(yrot, 0.0f, 1.0f, 0.0f); // Rotate On The Y Axis
        GL11.glRotatef(zrot, 0.0f, 0.0f, 1.0f); // Rotate On The Z Axis
        GL11.glColor3f(1.0f, 1.0f, 1.0f);
       
        // Enable vertex arrays
        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        // Setup vertex array pointer
        vertices.rewind();
        GL11.glVertexPointer(3, 0, vertices);
        // Draw using vertex array
        GL11.glDrawArrays(GL11.GL_QUADS, 0, 24);
        // Disable vertex arrays
        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
}
Title: Re: Vertex Array / VBO
Post by: Rainer on December 12, 2007, 09:09:20
Thanks, this helps me :)

Next thing: how can i add normals?
Title: Re: Vertex Array / VBO
Post by: Rainer on December 12, 2007, 11:54:42
i now finished implementing the vertexarrays in my engine, it works fine on smaller arrays, but if it's a large array (lets say 150000) it crashes:

#
# An unexpected error has been detected by Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0xb7ed19ac, pid=9665, tid=2897963920
#
# Java VM: Java HotSpot(TM) Client VM (1.6.0_03-b05 mixed mode)
# Problematic frame:
# C  [libc.so.6+0x6e9ac]  memcpy+0x1c
#
# An error report file with more information is saved as hs_err_pid9665.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#

should i divide it into several smaller arrays, or doesn't this problem exist if i change it to vbo?
Title: Re: Vertex Array / VBO
Post by: Rainer on December 12, 2007, 13:20:32
I now tried to do the VBO, I followed the above mentioned tutorial.

I have a Problem at:
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ELEMENT_ARRAY_BUFFER_ARB, indexBufferID);
  GL12.glDrawRangeElements(GL11.GL_TRIANGLES, 0, maxIndex, indexBufferSize,
               GL11.GL_UNSIGNED_INT, 0);

How do i have to do the Rendering? What is the indexBudderID and where do i get it?
Title: Re: Vertex Array / VBO
Post by: grom358 on December 12, 2007, 14:11:51
indexBufferID is the texture id


public static int createVBOID() {
  if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object) {
    IntBuffer buffer = BufferUtils.createIntBuffer(1);
    ARBVertexBufferObject.glGenBuffersARB(buffer);
    return buffer.get(0);
  }
  return 0;
}

int indexBufferID = createVBOID();
Title: Re: Vertex Array / VBO
Post by: Rainer on December 12, 2007, 21:07:19
Well, now i have no errors anymore, and some nice FPS count, only problem: my landscape completly disappeared :D
Is there somewhere a complete piece of code how to create the VBO?
I can't get it to work :(
Title: Re: Vertex Array / VBO
Post by: grom358 on December 13, 2007, 08:03:54
Btw.. in my last post I meant to say its the vertex buffer object ID. Its like a texture ID. Below is working VBO example

import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.ARBVertexBufferObject;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import org.lwjgl.opengl.GLContext;
import org.lwjgl.opengl.Util;
import org.lwjgl.opengl.glu.GLU;

public class CubeDemo {
private static final String TITLE = "Cube Demo";

private static final int FRAMERATE = 60;

private static final int WINDOW_WIDTH = 640;
private static final int WINDOW_HEIGHT = 480;

private volatile boolean isPaused = false;
private volatile boolean isRunning = false;

    private float xrot = 0f;       // X Rotation
    private float yrot = 0f;       // Y Rotation
    private float zrot = 0f;       // Z Rotation
    private float xspeed = 0.3f;   // X Rotation Speed
    private float yspeed = 0.2f;   // Y Rotation Speed
    private float zspeed = 0.4f;   // Z Rotation Speed
    private float z = -5.0f;       // Depth Into The Screen

/**
* Application init
*
* @param args
*            Commandline arguments
*/
public static void main(String[] args) {
CubeDemo animation = null;
try {
animation = new CubeDemo();
animation.run();
} catch (Exception e) {
e.printStackTrace(System.err);
Sys.alert(TITLE, "An error occured and the game will exit.");
} finally {
if(animation != null) animation.cleanup();
}

System.exit(0);
}

/**
* Determine an available display that matches the specified paramaters.
*
* @param width
*            The desired width of the screen
* @param height
*            The desired height of the screen
* @param bpp
*            The desired colour depth (bits per pixel) of the screen
* @return The display mode matching the requirements or null if none could
*         be found
* @throws LWJGLException
*             Indicates a failure interacting with the LWJGL library.
*/
private static DisplayMode findDisplayMode(int width, int height, int bpp)
throws LWJGLException {
DisplayMode[] modes = Display.getAvailableDisplayModes();
DisplayMode mode = null;

for (int i = 0; i < modes.length; i++) {
if ((modes[i].getBitsPerPixel() == bpp) || (mode == null)) {
if ((modes[i].getWidth() == width)
&& (modes[i].getHeight() == height)) {
mode = modes[i];
}
}
}

return mode;
}

/**
* Initialise the animation
*
* @throws Exception
*             if init fails
*/
public CubeDemo() throws Exception {
// find out what the current bits per pixel of the desktop is
int currentBpp = Display.getDisplayMode().getBitsPerPixel();
// find a display mode at 800x600
DisplayMode mode = findDisplayMode(WINDOW_WIDTH, WINDOW_HEIGHT, currentBpp);

// if can't find a mode, notify the user the give up
if (mode == null) {
Sys.alert("Error", WINDOW_WIDTH + "x" + WINDOW_HEIGHT + "x" + currentBpp
+ " display mode unavailable");
return;
}

Display.setTitle(TITLE);
Display.setDisplayMode(mode);
Display.setFullscreen(false);

// Enable vsync if we can
Display.setVSyncEnabled(true);

Display.create();

initGL();
}

/** The time since the last record of fps */
private long lastFpsTime = 0;

/** The recorded fps */
private int fps = 0;

/**
* Runs the animation (the "main loop")
*/
private void run() {
long lastLoopTime, delta;

Thread.currentThread().setPriority(Thread.MAX_PRIORITY);

isRunning = true;
lastLoopTime = System.nanoTime();

while (isRunning) {
delta = System.nanoTime() - lastLoopTime;
lastLoopTime = System.nanoTime();

lastFpsTime += delta;
fps++;

// update our FPS counter if a second has passed
if (lastFpsTime >= 1000000000L) {
Display.setTitle(TITLE +" (FPS: " + fps + ")");
lastFpsTime = 0;
fps = 0;
}

// Always call Display.update(), all the time
Display.update();

if (Display.isCloseRequested()) {
// Check for O/S close requests
isRunning = false;
} else if (Display.isActive()) {
// The window is in the foreground, so we should play the game
logic(delta);
render();
Display.sync(FRAMERATE);
} else {
// The window is not in the foreground, so we can allow other
// stuff to run and
// infrequently update
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
logic(delta);
if (Display.isVisible() || Display.isDirty()) {
// Only bother rendering if the window is visible or dirty
render();
}
}
}
}

private boolean pausePressed = false;
private boolean resetPressed = false;

/**
* Do all calculations, handle input, etc.
*/
private void logic(long delta) {
if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
isRunning = false;
}
if (Keyboard.isKeyDown(Keyboard.KEY_P) && !pausePressed) {
pausePressed = true;
isPaused = !isPaused;
}
if (!Keyboard.isKeyDown(Keyboard.KEY_P)) {
pausePressed = false;
}

if (isPaused) return;

if (Keyboard.isKeyDown(Keyboard.KEY_R) && !resetPressed) {
resetPressed = true;
// Reset speeds
xspeed = 0.3f;
    yspeed = 0.2f;
    zspeed = 0.4f;
}
if (!Keyboard.isKeyDown(Keyboard.KEY_R)) {
resetPressed = false;
}

        if (Keyboard.isKeyDown(Keyboard.KEY_PRIOR)) {
            z -= 0.02f;
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_NEXT)) {
            z += 0.02f;
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
            xspeed -= 0.01f;
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
            xspeed += 0.01f;
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
            yspeed += 0.01f;
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
            yspeed -= 0.01f;
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
        zspeed -= 0.01f;
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_Z)) {
        zspeed += 0.01f;
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_COMMA)) {
        xspeed -= 0.01f;
        yspeed -= 0.01f;
        zspeed -= 0.01f;
        }
        if (Keyboard.isKeyDown(Keyboard.KEY_PERIOD)) {
        xspeed += 0.01f;
        yspeed += 0.01f;
        zspeed += 0.01f;
        }

        xrot += xspeed; // X Axis Rotation
        yrot += yspeed; // Y Axis Rotation
        zrot += zspeed; // Z Axis Rotation
}

    private void initGL() {
        GL11.glEnable(GL11.GL_TEXTURE_2D); // Enable Texture Mapping
        GL11.glShadeModel(GL11.GL_SMOOTH); // Enable Smooth Shading
        GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black Background
        GL11.glClearDepth(1.0); // Depth Buffer Setup
        GL11.glEnable(GL11.GL_DEPTH_TEST); // Enables Depth Testing
        GL11.glDepthFunc(GL11.GL_LEQUAL); // The Type Of Depth Testing To Do

        GL11.glMatrixMode(GL11.GL_PROJECTION); // Select The Projection Matrix
        GL11.glLoadIdentity(); // Reset The Projection Matrix

        // Calculate The Aspect Ratio Of The Window
        GLU.gluPerspective(
          45.0f,
          (float) WINDOW_WIDTH / (float) WINDOW_HEIGHT,
          0.1f,
          100.0f);
        GL11.glMatrixMode(GL11.GL_MODELVIEW); // Select The Modelview Matrix

        // Really Nice Perspective Calculations
        GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
     
       
        vertices = BufferUtils.createFloatBuffer(3 * 4 * 6);
        vertices.put(new float[] {
        -1.0f, -1.0f, 1.0f,
        1.0f, -1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f,
       
        -1.0f, -1.0f, -1.0f,
        -1.0f, 1.0f, -1.0f,
        1.0f, 1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
       
        -1.0f, 1.0f, -1.0f,
        -1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, -1.0f,
       
        -1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, 1.0f,
        -1.0f, -1.0f, 1.0f,
       
        1.0f, -1.0f, -1.0f,
        1.0f, 1.0f, -1.0f,
        1.0f, 1.0f, 1.0f,
        1.0f, -1.0f, 1.0f,
       
        -1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f, 1.0f,
        -1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, -1.0f});
        vertices.rewind();
       
        vertexBufferID = createVBOID();
        bufferData(vertexBufferID, vertices);
    }
   
    private int vertexBufferID;
    private FloatBuffer vertices;
   
    public static int createVBOID() {
if (GLContext.getCapabilities().GL_ARB_vertex_buffer_object) {
IntBuffer buffer = BufferUtils.createIntBuffer(1);
ARBVertexBufferObject.glGenBuffersARB(buffer);
return buffer.get(0);
}
return 0;
}
   
    public static void bufferData(int id, FloatBuffer buffer) {
ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, id);
ARBVertexBufferObject.glBufferDataARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, buffer, ARBVertexBufferObject.GL_STATIC_DRAW_ARB);
}   

/**
* Render the current frame
*/
private void render() {
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer

        GL11.glLoadIdentity(); // Reset The Current Modelview Matrix

        GL11.glTranslatef(0.0f, 0.0f, z); // Move Into The Screen 5 Units
        GL11.glRotatef(xrot, 1.0f, 0.0f, 0.0f); // Rotate On The X Axis
        GL11.glRotatef(yrot, 0.0f, 1.0f, 0.0f); // Rotate On The Y Axis
        GL11.glRotatef(zrot, 0.0f, 0.0f, 1.0f); // Rotate On The Z Axis
        GL11.glColor3f(1.0f, 1.0f, 1.0f);
       
        vertices.rewind();
       
        GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
        ARBVertexBufferObject.glBindBufferARB(ARBVertexBufferObject.GL_ARRAY_BUFFER_ARB, vertexBufferID);
        GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
        GL11.glDrawArrays(GL11.GL_QUADS, 0, 24);
        GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
}

/**
* Do any animation-specific cleanup
*/
private void cleanup() {
// Close the window
Display.destroy();
}
}
Title: Re: Vertex Array / VBO
Post by: Rainer on December 14, 2007, 07:21:32
Thanks :)
Got it to work now, at similar speeds as the DisplayList before.
Now the next thing todo is to add the array with the normals...
Title: Re: Vertex Array / VBO
Post by: Rainer on December 20, 2007, 10:04:11
Everything is working now :)
Here's what i did: http://xphase.nerds-paradise.de/files/download_now.pl?version=latest
Title: Re: Vertex Array / VBO
Post by: Larssen on September 05, 2008, 20:07:20
Hi there :)

Thanks for your post, it helped me much to learn the glDrawArrays thing

Cheers