how to use glDraw*Instanced()

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

how to use glDraw*Instanced()

toruwest
I am trying to port The OpenGL Programming Guide 8th Edition, chapter 3, ch03_instancing.cpp and related files to JOGL.

My full source code is https://github.com/toruwest/jogl-instanced 

The important part of the source code is shown below.

Environment: Mac Book Air with Marvericks (OS X 10.9.5), Intel HD Graphics 4000
Java 8 (build 1.8.0_20-b26), JOGL 2.2.1    

This program throws the following exception (see bottom of this message)

My question is
(1)How to fix this problem. glVertexAttribPointer() method appears at the following location in my code.
  (a)VMBObject.java : loadFromVBM() (line 74) This is the most suspicious one.
  (b)InstancedRenderer1.java : init() (line 104)
  (c)InstancedRenderer1.java : init() (line 114)
 
(2)I don't use GLSL shader variable "mgl_MultiTexCoord", but glGetError() returns that string.
   I am trying to load the file "armadillo_low.vbm". This is a binary file, so I try to find the string with /usr/bin/strings utility but I can't find it.
(3)Are there sample code that explains how to use glDrawElementsInstanced() or glDrawArraysInstanced()? I know jogl-demos and JUnit test case contain usefull sample code but I couldn't find it about above method.


-- InstancedRenderer1.java---------------------
        @Override
        public void init(GLAutoDrawable drawable) {
                GL4 gl4 = drawable.getGL().getGL4();
                drawable.setGL(new DebugGL4(drawable.getGL().getGL4()));

                try {
                        initShaders(gl4);
                } catch (IOException e1) {
                        e1.printStackTrace();
                }
                int n;

                try {
                        // Load the object
                        boolean b = object.loadFromVBM(gl4, "armadillo_low.vbm", 0, 1, 2);
                        if(b == false) throw new IllegalStateException("file not found, or some other error.");
                } catch (IOException e) {
                        e.printStackTrace();
                }
                // Bind its vertex array object so that we can append the instanced attributes
                object.bindVertexArray(gl4);

                // Generate the colors of the objects
                //    vmath::vec4 colors[INSTANCE_COUNT];
                FloatBuffer colorBuf = Buffers.newDirectFloatBuffer(INSTANCE_COUNT * 4);

                for (n = 0; n < INSTANCE_COUNT; n++) {
                        float a = n / 4.0f;
                        float b = n / 5.0f;
                        float c = n / 6.0f;

                        colorBuf.put((float) (0.5f * (Math.sin(a + 1.0f) + 1.0f)));
                        colorBuf.put((float) (0.5f * (Math.sin(b + 2.0f) + 1.0f)));
                        colorBuf.put((float) (0.5f * (Math.sin(c + 3.0f) + 1.0f)));
                        colorBuf.put(1.0f);
                }

                // Create and allocate the VBO to hold the weights
                // Notice that we use the 'colors' array as the initial data, but only because
                // we know it's the same size.
                gl4.glGenBuffers(1, weight_vbo, 0);
                gl4.glBindBuffer(GL4.GL_ARRAY_BUFFER, weight_vbo[0]);
                //    glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_DYNAMIC_DRAW);
                gl4.glBufferData(GL4.GL_ARRAY_BUFFER, INSTANCE_COUNT * 4, colorBuf, GL4.GL_DYNAMIC_DRAW);

                // Here is the instanced vertex attribute - set the divisor
                gl4.glVertexAttribDivisor(3, 1);
                // It's otherwise the same as any other vertex attribute - set the pointer and enable it
                //    glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, 0, NULL);
                gl4.glVertexAttribPointer(3, 4, GL4.GL_FLOAT, false, 0, 0);
                gl4.glEnableVertexAttribArray(3);

                // Same with the instance color array
                gl4.glGenBuffers(1, color_vbo, 0);
                gl4.glBindBuffer(GL4.GL_ARRAY_BUFFER, color_vbo[0]);
                gl4.glBufferData(GL4.GL_ARRAY_BUFFER, colorBuf.capacity(), colorBuf, GL4.GL_STATIC_DRAW);

                gl4.glVertexAttribDivisor(4, 1);
                //    glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 0, NULL);
                gl4.glVertexAttribPointer(4, 4, GL4.GL_FLOAT, false, 0, 0);

                gl4.glEnableVertexAttribArray(4);

                // Done (unbind the object's VAO)
                gl4.glBindVertexArray(0);

                isInitialized = true;
        }
-- VMBObject.java---------------------

        public boolean loadFromVBM(GL4 gl, String filename, int vertexIndex, int normalIndex, int texCoord0Index) throws IOException {
                if(filename == null) return false;
            File f = new File(filename);
            if(!f.exists()) return false;

                byte[] data = Files.readAllBytes(f.toPath());
                ByteBuffer buf = ByteBuffer.wrap(data);
                buf.order(ByteOrder.LITTLE_ENDIAN);

                int total_data_size = 0;
                m_header = VBMUtil.getHeader(buf);
                m_attrib = VBMUtil.getVMBAttribHeader(buf, m_header.getNum_attribs());
                m_frame = VBMUtil.getVBMFrameHeader(buf, m_header.getNum_frames());

            gl.glGenVertexArrays(1, m_vao, 0);
            gl.glBindVertexArray(m_vao[0]);
            gl.glGenBuffers(1, m_attribute_buffer, 0);
            gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, m_attribute_buffer[0]);

            for (int i = 0; i < m_header.getNum_attribs(); i++) {
                int attribIndex = i;

                if(attribIndex == 0)
                    attribIndex = vertexIndex;
                else if(attribIndex == 1)
                    attribIndex = normalIndex;
                 else if(attribIndex == 2)
                    attribIndex = texCoord0Index;
                //glVertexAttribPointer(attribIndex, m_attrib[i].components, m_attrib[i].type, GL_FALSE, 0, (GLvoid *)total_data_size);
                gl.glVertexAttribPointer(attribIndex, m_attrib[i].getComponents(), m_attrib[i].getType(), false, 0, total_data_size);
                // argument is as follows. 5126(0x1406) is GL_FLOAT
                //n, attribIndex, components,  type,  total_data_size
                //0, 0,  4, 5126, 0
                //1, 1,  3, 5126, 332064,
                //2, 2,  2, 5126, 581112

                gl.glEnableVertexAttribArray(attribIndex);
                //total_data_size += m_attrib[i].components * sizeof(GLfloat) * header->num_vertices;
                total_data_size += m_attrib[i].getComponents() * Buffers.SIZEOF_FLOAT * m_header.getNum_vertices();
            }

                ByteBuffer raw_data = VBMUtil.getRawData(buf, total_data_size);
            gl.glBufferData(GL4.GL_ARRAY_BUFFER, total_data_size, raw_data, GL4.GL_STATIC_DRAW);

            if (m_header.getNum_indices() > 0) {
                gl.glGenBuffers(1, m_index_buffer, 0);
                gl.glBindBuffer(GL4.GL_ELEMENT_ARRAY_BUFFER, m_index_buffer[0]);
                int element_size = 0;
                switch (m_header.getIndex_type()) {
                    case GL4.GL_UNSIGNED_SHORT:
                    element_size = Buffers.SIZEOF_SHORT;
                        break;
                    default:
                        element_size = Buffers.SIZEOF_INT;
                        break;
                }
                ByteBuffer indices = buf.slice();
                gl.glBufferData(GL4.GL_ELEMENT_ARRAY_BUFFER, m_header.getNum_indices() * element_size, indices, GL4.GL_STATIC_DRAW);
            }

            gl.glBindVertexArray(0);

            buf.clear();
            raw_data.clear();
            return true;
        }


Exception in thread "AWT-EventQueue-0" javax.media.opengl.GLException: Caught GLException: Thread[AWT-EventQueue-0,6,main] glGetError() returned the following error codes after a call to glVertexAttribPointer(<javax.media.opengl.GLArrayData> GLArrayDataWrapper[mgl_MultiTexCoord, index -1, location 1, isVertexAttribute true, dataType 0x1406, bufferClazz class java.nio.FloatBuffer, elements 4, components 2, stride 20b 5c, mappedElementCount 0, buffer java.nio.DirectFloatBufferU[pos=0 lim=20 cap=40], vboEnabled true, vboName 1, vboUsage 0x88e4, vboTarget 0x8892, vboOffset 12, alive true]): GL_INVALID_OPERATION ( 1282 0x502),  on thread AWT-EventQueue-0
        at javax.media.opengl.GLException.newGLException(GLException.java:75)
        at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1317)
        at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:1137)
        at javax.media.opengl.awt.GLJPanel$OffscreenBackend.doPaintComponent(GLJPanel.java:1965)
        at javax.media.opengl.awt.GLJPanel.paintComponent(GLJPanel.java:563)
        at javax.swing.JComponent.paint(JComponent.java:1053)
        at javax.swing.JComponent.paintChildren(JComponent.java:886)
        at javax.swing.JComponent.paint(JComponent.java:1062)
        at javax.swing.JComponent.paintChildren(JComponent.java:886)
        at javax.swing.JComponent.paint(JComponent.java:1062)
        at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
        at javax.swing.JComponent.paintChildren(JComponent.java:886)
        at javax.swing.JComponent.paintToOffscreen(JComponent.java:5230)
        at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1572)
        at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1495)
        at javax.swing.RepaintManager.paint(RepaintManager.java:1265)
        at javax.swing.JComponent.paint(JComponent.java:1039)
        at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:39)
        at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:79)
        at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:116)
        at java.awt.Container.paint(Container.java:1973)
        at java.awt.Window.paint(Window.java:3901)
        at javax.swing.RepaintManager$4.run(RepaintManager.java:835)
        at javax.swing.RepaintManager$4.run(RepaintManager.java:807)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:807)
        at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:782)
        at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:731)
        at javax.swing.RepaintManager.access$1300(RepaintManager.java:64)
        at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1720)
        at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:744)
        at java.awt.EventQueue.access$400(EventQueue.java:97)
        at java.awt.EventQueue$3.run(EventQueue.java:697)
        at java.awt.EventQueue$3.run(EventQueue.java:691)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:714)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Caused by: javax.media.opengl.GLException: Thread[AWT-EventQueue-0,6,main] glGetError() returned the following error codes after a call to glVertexAttribPointer(<javax.media.opengl.GLArrayData> GLArrayDataWrapper[mgl_MultiTexCoord, index -1, location 1, isVertexAttribute true, dataType 0x1406, bufferClazz class java.nio.FloatBuffer, elements 4, components 2, stride 20b 5c, mappedElementCount 0, buffer java.nio.DirectFloatBufferU[pos=0 lim=20 cap=40], vboEnabled true, vboName 1, vboUsage 0x88e4, vboTarget 0x8892, vboOffset 12, alive true]): GL_INVALID_OPERATION ( 1282 0x502),
        at javax.media.opengl.DebugGL4bc.writeGLError(DebugGL4bc.java:29466)
        at javax.media.opengl.DebugGL4bc.glVertexAttribPointer(DebugGL4bc.java:28177)
        at jogamp.opengl.util.glsl.GLSLArrayHandlerFlat.syncData(GLSLArrayHandlerFlat.java:62)
        at jogamp.opengl.util.glsl.GLSLArrayHandlerInterleaved.syncSubData(GLSLArrayHandlerInterleaved.java:66)
        at jogamp.opengl.util.glsl.GLSLArrayHandlerInterleaved.enableState(GLSLArrayHandlerInterleaved.java:78)
        at com.jogamp.opengl.util.GLArrayDataClient.enableBuffer(GLArrayDataClient.java:210)
        at jogamp.opengl.util.glsl.GLSLTextureRaster.display(GLSLTextureRaster.java:164)
        at javax.media.opengl.awt.GLJPanel$OffscreenBackend.postGL(GLJPanel.java:1914)
        at javax.media.opengl.awt.GLJPanel$Updater.display(GLJPanel.java:1350)
        at javax.media.opengl.awt.GLJPanel$8.run(GLJPanel.java:1424)
        at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1283)
        ... 43 more
Reply | Threaded
Open this post in threaded view
|

Re: how to use glDraw*Instanced()

gouessej
Administrator
Hi

mgl_MultiTexCoord comes from here and you can find an example of instancing in ardor3d-jogl in the renderer.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: how to use glDraw*Instanced()

toruwest
Hi  gouessej

Thank you for your quick response. I will check Ardor3D later.


Reply | Threaded
Open this post in threaded view
|

Re: how to use glDraw*Instanced()

gouessej
Administrator
If you use GLJPanel, replace it by GLCanvas or GLWindow. Sven talked about some regressions on Mac OS X 10.9.5, using another operating system until they are fixed might be a good idea.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: how to use glDraw*Instanced()

toruwest
I used GLJPanel with JFrame, so I replace the GLJPanel by GLCanvas. As the result, the exception has gone.
Replacing JFrame by GLWindow also solve the problem.

But the screen is blank.... apparently there is another problem with my code.

I will try to simplfy the  problem by removing the VBM loader and adding code for rendering some triangles.


Reply | Threaded
Open this post in threaded view
|

Re: how to use glDraw*Instanced()

gouessej
Administrator
Have you ever tested your code on another machine with another operating system? Simplifying your code to find more easily the culprit is a good idea.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: how to use glDraw*Instanced()

toruwest
 I've changed my code to use com.jogamp.opengl.math.Matrix4 class instead of MyMatrixUtil2  ( I found Matrix4 class today...), and upload them to GitHub (https://github.com/toruwest/jogl-instanced/blob/master/jogl-instanced/src/InstancedRenderer1.java)
 But the screen is still blank.

> Have you ever tested your code on another machine with another operating system?

No, currently, my main concern is to write multi triangle sample code. So I am not motivated to complete to port the redbook's sample so much.
 
I have created the new demo code found here : https://github.com/toruwest/jogl-instanced-many-triangles/tree/master/jogl-instanced-many-triangles/src/demos/triangles/ManyTriangleVAOInstancedExperiment0.java   

This works very fine.  

Next step, I tried to modify it to use ShaderState, GLUniformData, and GLArrayDataServer.
(Please See https://github.com/toruwest/jogl-instanced-many-triangles/tree/master/jogl-instanced-many-triangles/src/demos/triangles/ManyTriangleVAOInstancedExperiment1.java )

This code runs without any exceptions, but the screen is blank.   Note that I use DebugGL4 and it indicates no message.

Any advice will be very appreciated.


Reply | Threaded
Open this post in threaded view
|

Re: how to use glDraw*Instanced()

Sven Gothel
Administrator
On 10/09/2014 04:30 PM, toruwest [via jogamp] wrote:
>
> Next step, I tried to modify it to use ShaderState, GLUniformData, and
> GLArrayDataServer.
> (Please See
> https://github.com/toruwest/jogl-instanced-many-triangles/tree/master/jogl-instanced-many-triangles/src/demos/triangles/ManyTriangleVAOInstancedExperiment1.java )

+++

int NO_OF_INSTANCE = 30

interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3 + 4, GL.GL_FLOAT, false,
                                            3 * NO_OF_INSTANCE, GL.GL_STATIC_DRAW);
interleavedVBO.addGLSLSubArray("VertexPosition", 3, GL.GL_ARRAY_BUFFER);
interleavedVBO.addGLSLSubArray("VertexColor", 4, GL.GL_ARRAY_BUFFER);
FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
for(int i = 0; i < 3; i++) {
  ib.put(vertices, i*3, 3);
  ib.put(colors, i*4, 4);
}

^^^
compsPerElement = 3 + 4;

your initialElementCount = 3 * 30,
but you only push 3 * 2 elements.

to have this working, you would need to push
all 3 * 30 elements .. I guess.

See jogamp.opengl.util.glsl.GLSLTextureRaster

~Sven


signature.asc (828 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: how to use glDraw*Instanced()

Sven Gothel
Administrator
In reply to this post by toruwest
On 10/10/2014 03:58 AM, Sven Gothel wrote:

> On 10/09/2014 04:30 PM, toruwest [via jogamp] wrote:
>>
>> Next step, I tried to modify it to use ShaderState, GLUniformData, and
>> GLArrayDataServer.
>> (Please See
>> https://github.com/toruwest/jogl-instanced-many-triangles/tree/master/jogl-instanced-many-triangles/src/demos/triangles/ManyTriangleVAOInstancedExperiment1.java )
>
> +++
>
> int NO_OF_INSTANCE = 30
>
> interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3 + 4, GL.GL_FLOAT, false,
>                                             3 * NO_OF_INSTANCE, GL.GL_STATIC_DRAW);
> interleavedVBO.addGLSLSubArray("VertexPosition", 3, GL.GL_ARRAY_BUFFER);
> interleavedVBO.addGLSLSubArray("VertexColor", 4, GL.GL_ARRAY_BUFFER);
> FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer();
> for(int i = 0; i < 3; i++) {
>   ib.put(vertices, i*3, 3);
>   ib.put(colors, i*4, 4);
> }
>
> ^^^
> compsPerElement = 3 + 4;
>
> your initialElementCount = 3 * 30,
> but you only push 3 * 2 elements.
>
> to have this working, you would need to push
> all 3 * 30 elements .. I guess.
Your working demo ManyTriangleVAOInstancedExperiment0
only uses an VBO w/ initialElementCount = 3 * 2 elements !

Hence I assume its a typo here, i.e.:

- interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3 + 4, GL.GL_FLOAT, false,
-                                             3 * NO_OF_INSTANCE, GL.GL_STATIC_DRAW);

+ interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3 + 4, GL.GL_FLOAT, false,
+                                             3 * 2, GL.GL_STATIC_DRAW);


Can you commit your example incl demo unit test to our JOGL repo,
adding our generic JogAmp (c) ?
That would be nice to have - thank you!


>
> See jogamp.opengl.util.glsl.GLSLTextureRaster
>
> ~Sven
>



signature.asc (828 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: how to use glDraw*Instanced()

toruwest
It works now! wow!!

https://github.com/toruwest/jogl-instanced-many-triangles/tree/master/jogl-instanced-many-triangles/src/demos/instancedRendering

Please ignore my old code.  (ManyTriangleVAOInstancedExperiment*.java ) they are absolutely out of date.


> Can you commit your example incl demo unit test to our JOGL repo,
> adding our generic JogAmp (c) ?
> That would be nice to have - thank you!

I will do it soon.
Reply | Threaded
Open this post in threaded view
|

Re: how to use glDraw*Instanced()

toruwest
I think I complete the code with JOGL 2.2.4 (released on October 10).
https://github.com/toruwest/jogl-instanced-many-triangles

Are they OK?

I read http://jogamp.org/wiki/index.php/Jogl_FAQ#Bugreports_.26_Testing and
  http://jogamp.org/wiki/index.php/Contributing_a_new_feature_or_fix,
but still I'm not sure how to commit them. Do you mean just send a pull request on github?

Reply | Threaded
Open this post in threaded view
|

Re: how to use glDraw*Instanced()

Sven Gothel
Administrator
On 10/13/2014 09:06 AM, toruwest [via jogamp] wrote:
> I think I complete the code with JOGL 2.2.4 (released on October 10).
> https://github.com/toruwest/jogl-instanced-many-triangles
>
> Are they OK?
>
> I read http://jogamp.org/wiki/index.php/Jogl_FAQ#Bugreports_.26_Testing and
>   http://jogamp.org/wiki/index.php/Contributing_a_new_feature_or_fix,
> but still I'm not sure how to commit them. Do you mean just send a pull
> request on github?

yes sir! :)

~Sven


signature.asc (828 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: how to use glDraw*Instanced()

rgsousa
In reply to this post by toruwest
Hi toruwest,

Do you still have the VBMUtil source code? I'm trying to port this same code to Java but I don't understand .vbm file. So, I think to see your VBMUtil source code would help to solve this problem.

Thanks
Reply | Threaded
Open this post in threaded view
|

Re: how to use glDraw*Instanced()

gouessej
Administrator
Are you trying to render voxel-based morphometry?
Julien Gouesse | Personal blog | Website