How to use VBO?

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

How to use VBO?

Chaz
Hello. I have to display large amount of quads, and for more performance I decide to use VBO for that task. But something goes wrong, and I got a batch of exceptions on
gl.glBufferData(targetsBuffer.get(0), fBuff.capacity(),fBuff,gl.GL_STATIC_DRAW);
Here is class which I use for creating and using VBO

public class Terrain implements IShape {
    private ObjectArrayList<Vector3f> vectors;
    private GL2 gl;
    private FloatBuffer fBuff;
    private IntBuffer targetsBuffer;

    public Terrain(GL2 gl) throws Exception
    {
        this.gl=gl;
        vectors=new ObjectArrayList<Vector3f>();
           Import(".//data.exp");
    }

    private void Import(String path) throws Exception
    {
        byte[] bytes = Files.readAllBytes(Paths.get(path)); // import files with heights
        int resolution = (int)Math.sqrt(bytes.length/4); // define resolution
        float[] floats=new float[resolution*resolution];
        ByteBuffer.wrap(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer().get(floats);
        float step = 100/(resolution-1.0f);

        fBuff = FloatBuffer.allocate(resolution*resolution*3*4); // create buffer with vertices

        for(int i =0; i<resolution-1; i++)
        {
            for(int j =0; j<resolution-1; j++) // here I create a grid, 4 vertices for each quad
            {
                float x1=i,y1=floats[i*resolution+j]*600,z1=j;
                vectors.add(new Vector3f(x1,y1,z1));  // physics engine needs it for create a collider
                float x2=i+1,y2=floats[(i+1)*resolution+j]*600,z2=j;
                vectors.add(new Vector3f(x2,y2,z2));
                float x3=i+1,y3=floats[(i+1)*resolution+(j+1)]*600,z3=j+1;
                vectors.add(new Vector3f(x3,y3,z3));
                float x4=i,y4=floats[i*resolution+(j+1)]*600,z4=j+1;
                vectors.add(new Vector3f(x4,y4,z4));

                fBuff.put(x1); // add vertices to buffer
                fBuff.put(y1);
                fBuff.put(z1);

                fBuff.put(x2);
                fBuff.put(y2);
                fBuff.put(z2);

                fBuff.put(x3);
                fBuff.put(y3);
                fBuff.put(z3);

                fBuff.put(x4);
                fBuff.put(y4);
                fBuff.put(z4);
            }
        }
        float max=Float.MIN_VALUE,min=Float.MAX_VALUE;
        for(float f : floats)
        {
            if(f>max)max=f;
            if(f<min)min=f;
        }

        System.out.println(floats[0]+" : "+floats[floats.length-1]);

        System.out.println("Max: "+max+"\nMin: "+min);
    }

    public ObjectArrayList<Vector3f> GetVertexes()
    {
        return vectors;
    }

    public void CreateBuffer(GL2 gl)
    {
        this.gl=gl;
        targetsBuffer = IntBuffer.allocate(1);
        gl.glGenBuffers(1,targetsBuffer);
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER,targetsBuffer.get(0));
        gl.glBufferData(targetsBuffer.get(0), fBuff.capacity(),fBuff,gl.GL_STATIC_DRAW);
    }

    @Override
    public void Draw() {
        gl.glEnableClientState(gl.GL_VERTEX_ARRAY);
        gl.glBindVertexArray(targetsBuffer.get(0));
        gl.glDrawArrays(gl.GL_QUADS,0,fBuff.capacity());
        gl.glDisableClientState(gl.GL_VERTEX_ARRAY);
    }
}

In Main class I have initialize this class

terrain=new Terrain();

And then call methods from init and render methods

 @Override
    public void init(GLAutoDrawable glAutoDrawable) {
        glu=GLU.createGLU(glAutoDrawable.getGL().getGL2());
        glut=new GLUT();
        gl=glAutoDrawable.getGL().getGL2();
        //gl.glPolygonMode(gl.GL_FRONT_AND_BACK,gl.GL_LINE);

        terrain.CreateBuffer(gl);
        System.out.println(gl.isExtensionAvailable("GL_ARB_vertex_buffer_object"));
    }

 private void render(GLAutoDrawable drawable)
    {
        gl.glEnable(gl.GL_DEPTH_TEST);
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
        gl.glClearColor(0.2f, 0.4f, 0.7f, 0);
        gl.glMatrixMode(gl.GL_MODELVIEW);
        gl.glLoadIdentity();
        glu.gluLookAt(cameraPos.x, cameraPos.y, cameraPos.z, pointOfInterest.x, pointOfInterest.y, pointOfInterest.z, 0, 1, 0);

        gl.glPushMatrix();

        int x=0;
        for(RigidBody ball : balls)
        {
            gl.glPushMatrix();
            {
                float[] buff = new float[16];
                ball.getWorldTransform(new Transform()).getOpenGLMatrix(buff);
                gl.glMultMatrixf(FloatBuffer.wrap(buff));
                gl.glColor3f(0, 1, 0);
                glut.glutSolidSphere(1,10,10);
            }
            gl.glPopMatrix();

            x++;
        }

        gl.glColor3f(0.5f,0,0);
        gl.glPopMatrix();
        terrain.Draw();
    }


But I have exception which appears in this method
     public void CreateBuffer(GL2 gl)  
on call
    gl.glBufferData(targetsBuffer.get(0), fBuff.capacity(),fBuff,gl.GL_STATIC_DRAW);

So what I did wrong?
Reply | Threaded
Open this post in threaded view
|

Re: How to use VBO?

gouessej
Administrator
Hi

Please read the "man" of glBufferData:
https://www.opengl.org/sdk/docs/man/html/glBufferData.xhtml

You should rather write:
fBuff = Buffers.newDirectFloatBuffer(resolution*resolution*3*4);

gl.glBufferData(targetsBuffer.get(0), Buffers.SIZEOF_FLOAT*fBuff.capacity(),fBuff,GL.GL_STATIC_DRAW);

targetsBuffer = Buffers.newDirectIntBuffer(1);

Call fBuff.rewind() at the end of your import method.

Please post your exceptions. How can we help you if you don't show us what's wrong? (even though your code helps)
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: How to use VBO?

Chaz
Ok, i have changed the code. But exceptions still are.

Exception in thread "AWT-EventQueue-0" javax.media.opengl.GLException: Caught GLException: GL_INVALID_ENUM​: Invalid binding target 0x1 on thread AWT-EventQueue-0
        at javax.media.opengl.GLException.newGLException(GLException.java:75)
        at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1311)
        at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1131)
        at javax.media.opengl.awt.GLCanvas$11.run(GLCanvas.java:1394)
        at javax.media.opengl.Threading.invoke(Threading.java:223)
        at javax.media.opengl.awt.GLCanvas.display(GLCanvas.java:525)
        at javax.media.opengl.awt.GLCanvas.paint(GLCanvas.java:579)
        at sun.awt.RepaintArea.paintComponent(RepaintArea.java:264)
        at sun.awt.RepaintArea.paint(RepaintArea.java:240)
        at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:347)
        at java.awt.Component.dispatchEventImpl(Component.java:4937)
        at java.awt.Component.dispatchEvent(Component.java:4687)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
        at java.awt.EventQueue.access$200(EventQueue.java:103)
        at java.awt.EventQueue$3.run(EventQueue.java:694)
        at java.awt.EventQueue$3.run(EventQueue.java:692)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
        at java.awt.EventQueue$4.run(EventQueue.java:708)
        at java.awt.EventQueue$4.run(EventQueue.java:706)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
Caused by: javax.media.opengl.GLException: GL_INVALID_ENUM​: Invalid binding target 0x1
        at jogamp.opengl.GLBufferStateTracker.getQueryName(GLBufferStateTracker.java:151)
        at jogamp.opengl.GLBufferStateTracker.getBoundBufferObject(GLBufferStateTracker.java:225)
        at jogamp.opengl.GLBufferObjectTracker.createBufferStorage(GLBufferObjectTracker.java:156)
        at jogamp.opengl.gl4.GL4bcImpl.glBufferData(GL4bcImpl.java:37383)
        at Terrain.CreateBuffer(Terrain.java:98)
        at Main.init(Main.java:329)
        at jogamp.opengl.GLDrawableHelper.init(GLDrawableHelper.java:640)
        at jogamp.opengl.GLDrawableHelper.init(GLDrawableHelper.java:662)
        at javax.media.opengl.awt.GLCanvas$9.run(GLCanvas.java:1366)
        at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1275)
        ... 28 more
Reply | Threaded
Open this post in threaded view
|

Re: How to use VBO?

gouessej
Administrator
Rather write:
gl.glBufferData(GL.GL_ARRAY_BUFFER, Buffers.SIZEOF_FLOAT*fBuff.capacity(),fBuff,GL.GL_STATIC_DRAW);

You passed a buffer identifier instead of a buffer target.

It was explained in the documentation:

target

    Specifies the target to which the buffer object is bound for glBufferData, which must be one of the buffer binding targets in the following table:

Please read the documentation carefully, it will prevent you from doing tons of mistakes.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: How to use VBO?

Chaz
i thought that target it is buffer id xD
Now all exceptions disappeared! But i have this thing

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000000ee5fe93, pid=5408, tid=7308
#
# JRE version: Java(TM) SE Runtime Environment (7.0_51-b13) (build 1.7.0_51-b13)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (24.51-b03 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  0x000000000ee5fe93
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# D:\IdeaProjects\Java3D\hs_err_pid5408.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
Reply | Threaded
Open this post in threaded view
|

Re: How to use VBO?

gouessej
Administrator
Replace:
gl.glBindVertexArray(targetsBuffer.get(0));
by
gl.glBindBuffer(gl.GL_ARRAY_BUFFER,targetsBuffer.get(0));

glBindVertexArray is used for VAOs, not for VBOs. Please ensure that you call fBuff.rewind() to avoid to ask OpenGL to read beyond the size of the buffer.

If you really want to use VAOs, look at this example:
http://jogamp.org/git/?p=jogl-demos.git;a=blob;f=src/demos/es2/RawGL2ES2demo.java;hb=HEAD

Always look at the documentation when you're not sure of what to pass to an OpenGL method.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: How to use VBO?

Chaz
Thanks! Additional to your advice i replaced all VERTEX ARRAY to ARRAY BUFFER and now have this code

public void CreateBuffer(GL2 gl)
    {
        this.gl=gl;
        targetsBuffer = Buffers.newDirectIntBuffer(1);
        gl.glGenBuffers(1,targetsBuffer);
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER,targetsBuffer.get(0));
        gl.glBufferData(GL.GL_ARRAY_BUFFER, Buffers.SIZEOF_FLOAT*fBuff.capacity(),fBuff,GL.GL_STATIC_DRAW);
    }

    @Override
    public void Draw() {
        gl.glEnableClientState(gl.GL_ARRAY_BUFFER);
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER,targetsBuffer.get(0));
        gl.glDrawBuffer(targetsBuffer.get(0));
        gl.glDisableClientState(gl.GL_ARRAY_BUFFER);
    }

Now it compiles and runs good - but i don't see any mesh in my window =(
Reply | Threaded
Open this post in threaded view
|

Re: How to use VBO?

gouessej
Administrator
This post was updated on .
Sorry but your change is wrong, you broke something that was correct, rather write that:
gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
...
gl.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);

Look at the documentation:
https://www.opengl.org/sdk/docs/man2/xhtml/glEnableClientState.xml

No you don't have to call glDrawBuffer, you should call glDrawArrays, it was correct:
gl.glDrawArrays(GL2GL3.GL_QUADS,0,fBuff.capacity()/3);

You should really spend some time in reading the example I quoted because you seem to make some changes without understanding how the API works.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: How to use VBO?

Chaz
Jesus Christ! Hallelujah! LOL
Actually i watched examples but all they was different.
This code is works!

public void CreateBuffer(GL2 gl)
    {
        this.gl=gl;
        BufferOffset=Buffers.newDirectIntBuffer(4);
        targetsBuffer = Buffers.newDirectIntBuffer(1);
        gl.glGenBuffers(1, targetsBuffer);
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER, targetsBuffer.get(0));
        gl.glEnableClientState(gl.GL_VERTEX_ARRAY);

        gl.glBufferData(GL.GL_ARRAY_BUFFER, fBuff.capacity()*4, fBuff, GL.GL_STATIC_DRAW);

        gl.glDisableClientState(gl.GL_VERTEX_ARRAY);
    }

    @Override
    public void Draw(){
        gl.glBindBuffer(GL.GL_ARRAY_BUFFER,targetsBuffer.get(0));
        gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);

        gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0 );
        gl.glDrawArrays(GL2.GL_QUADS,0,fBuff.capacity()*4);

        gl.glBindBuffer(GL.GL_ARRAY_BUFFER,0);
        gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);
    }
Reply | Threaded
Open this post in threaded view
|

Re: How to use VBO?

gouessej
Administrator
You seem not to understand the examples that you looked, you give the impression to tinker without understanding what you do. Buffers.SIZEOF_FLOAT = 4, therefore fBuff.capacity()*4 should be rewritten by using Buffers.SIZEOF_FLOAT as I suggested, it's more readable, it's better than using a magic number. BufferOffset seems to be useless. gl.glEnableClientState(gl.GL_VERTEX_ARRAY) is the equivalent of gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY) but as the constant is static, there is no need of using "gl". gl.glDrawArrays(GL2.GL_QUADS,0,fBuff.capacity()*4) is still wrong because the last parameter is the count of vertices or indices to render and your vertices have 3 coordinates (x, y, z) then you should write gl.glDrawArrays(GL2GL3.GL_QUADS,0,fBuff.capacity()/3). Yes I forgot to tell you that you had forgotten glVertexPointer but your code was full of mistakes, I did my best.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: How to use VBO?

Chaz
ok, I have fixed it all now, ty