Hi
I am new to OpenGL and JOGL. I am using GL3 and GL4 I have set up a basic app to create a NEWT window and link a program using shaders. I have been learning how to draw basic shapes mainly triangles, squares, and circles using different primitive tokens and drawing methods. I have drawn 3 colored squares: red, green, and blue using DrawArrays, MultiDrawArrays, and DrawElements but 1 cannot get it to work using MultiDrawElements at best I get the first red square to draw This is what it should look like I can draw the first red square if i use DrawElement method which is commented out in following code but MultiDrawElementsDraws nothing. I can get MultiDrawElements to draw the first red square to draw if I move the glVertexAttribPointer methods into the display method and enable and disable these along with binding the buffers but I want to hopefully just use the display method and set the state in the init method. Below is the code package demo; import com.jogamp.common.nio.PointerBuffer; import com.jogamp.opengl.GL4; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.util.GLBuffers; import demo.common.core.BasicDemo; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; import static com.jogamp.opengl.GL.*; /** * Created by James on 20/12/2015. * * Draws 3 squares using method drawElements * 3 primitive each made up of 2 triangles using 4 vertices (6 elements) * 1 red, 1 green, and 1 blue */ public class MultiDrawElements2 extends BasicDemo { private static final boolean fps = false; public MultiDrawElements2(final boolean fps) { super(fps); } public static void main(final String... args) { new MultiDrawElements2(fps); } // 3 0 // 2 1 private static final float[] VERTEX_DATA = { 250.0f, 250.0f, 0.0f, 1.0f, // 0 right top 250.0f, 350.0f, 0.0f, 1.0f, // 1 right bottom - reused 150.0f, 350.0f, 0.0f, 1.0f, // 2 left bottom 150.0f, 250.0f, 0.0f, 1.0f, // 3 left top - reused 450.0f, 250.0f, 0.0f, 1.0f, 450.0f, 350.0f, 0.0f, 1.0f, 350.0f, 350.0f, 0.0f, 1.0f, 350.0f, 250.0f, 0.0f, 1.0f, 650.0f, 250.0f, 0.0f, 1.0f, 650.0f, 350.0f, 0.0f, 1.0f, 550.0f, 350.0f, 0.0f, 1.0f, 550.0f, 250.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f }; private static final short[] ELEMENT_DATA = { // Note that we start from 0! 0, 1, 3, 1, 2, 3, 0, 1, 3, 1, 2, 3, 0, 1, 3, 1, 2, 3 }; private static final int PRIM_COUNT = 3; private static final int VERTICES_COUNT = 4; private static final int VERTICES_SIZE = 4; private static final int COLOUR_SIZE = 4; private static final int ELEMENT_COUNT = 6; private static final int COLOUR_START = PRIM_COUNT * VERTICES_COUNT * VERTICES_SIZE * GLBuffers.SIZEOF_FLOAT; private static final int[] COUNT = { ELEMENT_COUNT, ELEMENT_COUNT, ELEMENT_COUNT }; private static final IntBuffer ELEMENT_COUNT_INT_BUFFER = GLBuffers.newDirectIntBuffer(COUNT); private static final byte[] OFFSET = { (byte) 0, (byte) 6, (byte) 12}; private static final PointerBuffer ELEMENT_OFFSET_POINTER_BUFFER = PointerBuffer.allocateDirect(OFFSET.length); static { ELEMENT_OFFSET_POINTER_BUFFER.put(OFFSET[0]); ELEMENT_OFFSET_POINTER_BUFFER.put(OFFSET[1]); ELEMENT_OFFSET_POINTER_BUFFER.put(OFFSET[2]); } private static final int[] VAO = new int[1]; private static final int[] VBO = new int[1]; private static final int[] EBO = new int[1]; @Override public void init(GLAutoDrawable glAutoDrawable) { super.init(glAutoDrawable); final GL4 gl = glAutoDrawable.getGL().getGL4(); gl.glGenVertexArrays(VAO.length, IntBuffer.wrap(VAO)); gl.glGenBuffers(VBO.length, IntBuffer.wrap(VBO)); gl.glGenBuffers(EBO.length, IntBuffer.wrap(EBO)); gl.glBindVertexArray(VAO[0]); gl.glBindBuffer(GL_ARRAY_BUFFER, VBO[0]); { final FloatBuffer buffer = GLBuffers.newDirectFloatBuffer(VERTEX_DATA); gl.glBufferData(GL_ARRAY_BUFFER, VERTEX_DATA.length * GLBuffers.SIZEOF_FLOAT, buffer, GL_STATIC_DRAW); } gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO[0]); { final ShortBuffer buffer = GLBuffers.newDirectShortBuffer(ELEMENT_DATA); gl.glBufferData(GL_ELEMENT_ARRAY_BUFFER, ELEMENT_DATA.length * GLBuffers.SIZEOF_SHORT, buffer, GL_STATIC_DRAW); } gl.glVertexAttribPointer(0, VERTICES_SIZE, GL_FLOAT, false, 0, 0); gl.glEnableVertexAttribArray(0); gl.glVertexAttribPointer(1, COLOUR_SIZE, GL_FLOAT, false, 0, COLOUR_START); gl.glEnableVertexAttribArray(1); } @Override public void display(GLAutoDrawable glAutoDrawable) { super.display(glAutoDrawable); final GL4 gl = glAutoDrawable.getGL().getGL4(); gl.glUseProgram(PROGRAM[0]); { gl.glBindVertexArray(VAO[0]); gl.glUniformMatrix4fv(LOCATIONS[Location.PROJECTION_MATRIX.getLocation()], 1, false, PROJECTION_MATRIX, 0); // gl.glDrawElements(GL_TRIANGLES, ELEMENT_COUNT, GL_UNSIGNED_SHORT, 0); // Draws first square (red) gl.glMultiDrawElements(GL_TRIANGLES, ELEMENT_COUNT_INT_BUFFER, GL_UNSIGNED_SHORT, ELEMENT_OFFSET_POINTER_BUFFER, PRIM_COUNT); } gl.glUseProgram(0); } } I have searched the internet for a example but have not been able to find one that uses GL3 or above and MultiDrawElements Thanks in advance James |
Hi James,
this may help you, https://github.com/elect86/jogl-samples/blob/master/jogl-samples/src/tests/gl_320/draw/Gl_320_draw_multiple.java Anyway, I am coming with a gl4 example if you are interested as well |
Thanks I've been looking at the example and made a few changes it now draws first red square using MultidrawElements but still not fully working here's my updated code. Yes I would definitely be interested in GL4 example
package demo; import com.jogamp.common.nio.PointerBuffer; import com.jogamp.opengl.GL4; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.util.GLBuffers; import demo.common.core.BasicDemo; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; import static com.jogamp.opengl.GL.*; /** * Created by James on 20/12/2015. * * Draws 3 squares using method drawElements * 3 primitive each made up of 2 triangles using 4 vertices (6 elements) * 1 red, 1 green, and 1 blue */ public class MultiDrawElements2 extends BasicDemo { private static final boolean fps = false; public MultiDrawElements2(final boolean fps) { super(fps); } public static void main(final String... args) { new MultiDrawElements2(fps); } // 3 0 // 2 1 private static final float[] VERTEX_DATA = { 250.0f, 250.0f, 0.0f, 1.0f, // 0 right top 250.0f, 350.0f, 0.0f, 1.0f, // 1 right bottom - reused 150.0f, 350.0f, 0.0f, 1.0f, // 2 left bottom 150.0f, 250.0f, 0.0f, 1.0f, // 3 left top - reused 450.0f, 250.0f, 0.0f, 1.0f, 450.0f, 350.0f, 0.0f, 1.0f, 350.0f, 350.0f, 0.0f, 1.0f, 350.0f, 250.0f, 0.0f, 1.0f, 650.0f, 250.0f, 0.0f, 1.0f, 650.0f, 350.0f, 0.0f, 1.0f, 550.0f, 350.0f, 0.0f, 1.0f, 550.0f, 250.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f }; private static final int[] ELEMENT_DATA = { // Note that we start from 0! 0, 1, 3, 1, 2, 3 }; private static final int PRIM_COUNT = 3; private static final int VERTICES_COUNT = 4; private static final int VERTICES_SIZE = 4; private static final int COLOUR_SIZE = 4; private static final int ELEMENT_COUNT = 6; private static final int COLOUR_START = PRIM_COUNT * VERTICES_COUNT * VERTICES_SIZE * GLBuffers.SIZEOF_FLOAT; private static final int[] COUNT = { ELEMENT_COUNT, ELEMENT_COUNT, ELEMENT_COUNT }; private static final IntBuffer ELEMENT_COUNT_INT_BUFFER = GLBuffers.newDirectIntBuffer(COUNT); private static final int[] VAO = new int[1]; private static final int[] VBO = new int[1]; private static final int[] EBO = new int[1]; @Override public void init(GLAutoDrawable glAutoDrawable) { super.init(glAutoDrawable); final GL4 gl = glAutoDrawable.getGL().getGL4(); gl.glGenVertexArrays(VAO.length, IntBuffer.wrap(VAO)); gl.glGenBuffers(VBO.length, IntBuffer.wrap(VBO)); gl.glGenBuffers(EBO.length, IntBuffer.wrap(EBO)); gl.glBindVertexArray(VAO[0]); gl.glBindBuffer(GL_ARRAY_BUFFER, VBO[0]); { final FloatBuffer buffer = GLBuffers.newDirectFloatBuffer(VERTEX_DATA); gl.glBufferData(GL_ARRAY_BUFFER, VERTEX_DATA.length * GLBuffers.SIZEOF_FLOAT, buffer, GL_STATIC_DRAW); } gl.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO[0]); { final IntBuffer buffer = GLBuffers.newDirectIntBuffer(ELEMENT_DATA); gl.glBufferData(GL_ELEMENT_ARRAY_BUFFER, ELEMENT_DATA.length * GLBuffers.SIZEOF_INT, buffer, GL_STATIC_DRAW); } gl.glVertexAttribPointer(0, VERTICES_SIZE, GL_FLOAT, false, 0, 0); gl.glEnableVertexAttribArray(0); gl.glVertexAttribPointer(1, COLOUR_SIZE, GL_FLOAT, false, 0, COLOUR_START); gl.glEnableVertexAttribArray(1); } @Override public void display(GLAutoDrawable glAutoDrawable) { super.display(glAutoDrawable); final GL4 gl = glAutoDrawable.getGL().getGL4(); gl.glUseProgram(PROGRAM[0]); { gl.glBindVertexArray(VAO[0]); final PointerBuffer pointerBuffer = PointerBuffer.allocateDirect(3); pointerBuffer.put(0); pointerBuffer.put(0); pointerBuffer.put(0); pointerBuffer.rewind(); gl.glUniformMatrix4fv(LOCATIONS[Location.PROJECTION_MATRIX.getLocation()], 1, false, PROJECTION_MATRIX, 0); gl.glMultiDrawElements(GL_TRIANGLES, ELEMENT_COUNT_INT_BUFFER, GL_UNSIGNED_INT, pointerBuffer, PRIM_COUNT); } gl.glUseProgram(0); } } |
This post was updated on .
I don't see anything wrong there..
Anyway, just for curiosity, try 1) private static final int[] ELEMENT_DATA = { // Note that we start from 0! 0, 1, 3, 1, 2, 3, 0, 1, 3, 1, 2, 3, 0, 1, 3, 1, 2, 3 }; and pointbuffer = 0, 6*4, (6+6)*4 2) private static final int[] ELEMENT_DATA = { // Note that we start from 0! 0, 1, 3, 1, 2, 3 }; and pointbuffer = 0 3) modify the first 4 colors 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, to 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, What you see? Ps: do you catch any gl error? Pps: is your whole code visible anywhere? |
Just first red square still
|
Try the other two, I modified it
|
In reply to this post by elect
Tried that still draws just first square. I'm using intellij and there is no errors in run window and it starts up and shuts down fine. My codes not visible anywhere. I could post full app 5 classes and 2 shaders if you want.
|
just trying 2 and 3
|
2. didn't work 3. i square blue bottom left cornner, red top right corner and green diagnol
|
Try
glMultiDrawElementsBaseVertex( GL_TRIANGLES, ELEMENT_COUNT_INT_BUFFER, GL_UNSIGNED_INT, pointerBuffer, PRIM_COUNT, GLBuffers.newDirectIntBuffer(new int[]{0, 4,8}) ); |
Thanks a lot that works what would array be if data was packed has following
250.0f, 250.0f, 0.0f, 1.0f, // 0 right top 250.0f, 350.0f, 0.0f, 1.0f, // 1 right bottom - reused 150.0f, 350.0f, 0.0f, 1.0f, // 2 left bottom 150.0f, 250.0f, 0.0f, 1.0f, // 3 left top - reused 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 450.0f, 250.0f, 0.0f, 1.0f, 450.0f, 350.0f, 0.0f, 1.0f, 350.0f, 350.0f, 0.0f, 1.0f, 350.0f, 250.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 650.0f, 250.0f, 0.0f, 1.0f, 650.0f, 350.0f, 0.0f, 1.0f, 550.0f, 350.0f, 0.0f, 1.0f, 550.0f, 250.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f tried 0, 8 , 16 but draws green, blue then black from left to right instead of red green blue from left to right (red square drawn last instead of first and is black) |
You'r welcome, I should have seen since the begin. Opengl needed an array of offset to start the n-th element drawing from, and that was the base vertex.. If [0,8,16] doesnt work then I guess you can't do like that with glMultiDrawElementsBaseVertex, either interleaved (the best since it exploits data locality) position0, color0, position1, color1, position2, color2 or one after each other position0, position1, position2, color0, color1, color2 or separate position0, position1, position2 color0, color1, color2 or (I think) glMultiDrawElementsIndirect |
Or try [0,4,8] with COLOR_START = 4*4*Float.BYTES
|
In reply to this post by James
Sorted index 0 8 and 16 worked needed to change the following
private static final int COLOUR_START = PRIM_COUNT * VERTICES_COUNT * VERTICES_SIZE * GLBuffers.SIZEOF_FLOAT; to private static final int COLOUR_START = VERTICES_COUNT * VERTICES_SIZE * GLBuffers.SIZEOF_FLOAT; Thanks |
In reply to this post by James
I almost forgot https://github.com/elect86/jogl-samples/blob/master/jogl-samples/src/tests/gl_430/Gl_430_multi_draw_indirect.java |
Hi,
5 years later, I found this discussion instructive to understand glMultiDrawElements but I still thrive to make it work. Using JOGL 2.3.2, Mac 10.12.6, I get a JVM crash. I think I did not understand properly how to build the PointerBuffer. Here is what I want to do I have a collection of vertices/normals/colors in their dedicated buffers. I want to draw quads (based on GL_TRIANGLE_FAN) that share vertex between each other. I want to do like this because input data is made of shared vertices described in an input file and I want to avoid repeating them manually. Here is how I try to do it I first register vertices, normals and colors with FloatBuffers. I think I do this properly since I can use glMultiDrawArrays properly with other case where vertices are repeated (hence I do not need an index since vertices of the same triangle fan will be contiguous, and all triangle fans have their start index and length defined). Then I invoke glMultiDrawElements as follow : gl2.glMultiDrawElements(glGeometryType, elementsCountBuffer, GL.GL_UNSIGNED_INT, elementsIndicesBuffer, elementsIndicesBuffer.capacity()); where elementsCount is filled with a 1D array as follow : IntBuffer elementCountBuffer = Buffers.newDirectIntBuffer(elementsCount); // int[] elementsCount elementCountBuffer.rewind(); and elementsIndices is filled with a 2D array as follow : PointerBuffer elementIndicesBuffer = PointerBuffer.allocateDirect(size(elementsIndices)); // int[][] elementsIndices, where size(array) returns #row x #columns for (int i = 0; i < elementsIndices.length; i++) { // Each i is the ID of a GL_TRIANGLE_FAN for (int j = 0; j < elementsIndices[i].length; j++) { // Each j is the index of a vertex to use in the vertex/normal/color buffers to draw the ith triangle fan elementIndicesBuffer.put(elementsIndices[i][j]); } } elementIndicesBuffer.rewind(); I am almost sure I do this wrong because the man page of the function states that the last argument - drawcount - should describe the length of the two buffer, hence that they should be equals. As the purpose of this function is to draw multiple elements based on vertices that may be shared among these elements, I wonder how elementIndicesBuffer could be anything else than a 2D array? Otherwise, if it is a 1D array, how can I register in it the list of indices for the first triangle fan, then second triangle fan, etc? Thanks for your help! |
Resolved! There is a method in PointerBuffer that was not used by James and Elect which simplify the 2D index. Here is an example assuming an input int[][] elementsIndice, where each line is a list of indices for 1 element (e.g. a triangle fan). Each line can have a different number of vertex indices.
PointerBuffer elementIndicesBuffer = PointerBuffer.allocateDirect(elementsIndices.length); IntBuffer elementCountBuffer = Buffers.newDirectIntBuffer(elementsCount); for (int i = 0; i < elementsIndices.length; i++) { IntBuffer elementDataBufferI = Buffers.newDirectIntBuffer(elementsIndices[i]); elementDataBufferI.rewind(); elementIndicesBuffer.referenceBuffer(elementDataBufferI); elementCountBuffer.put(elementsIndices[i].length); } elementCountBuffer.rewind(); elementIndicesBuffer.rewind(); Surprisingly, there is no need to bind any element buffer. Vertex, color and normal buffer must be bind. Then one simply invoke glMultiDrawElements(GL.GL_TRIANGLE_FAN, elementCountBuffer, GL.GL_UNSIGNED_INT, elementsIndicesBuffer, elementCountBuffer.capacity()); |
Free forum by Nabble | Edit this page |