Why do I get error INVALID_OPERATION when I call glMultiDrawElementsIndirect - java

I'm currently trying to use glMultiDrawElementsIndirect in with LWJGL in Java, but I have an error INVALID_OPERATION.
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, this.modelManager.indirect, NB_TYPE_MESH, 0);
I see in the documentation this error is about the GL_DRAW_INDIRECT_BUFFER or GL_ELEMENT_ARRAY_BUFFER, but I don't know where the problem is in my code.
Indirect buffer
int[] indirect = new int[NB_TYPE_MESH*5];
for(int i=0; i<2; i++) {
indirect[i] = getElementCount().get(i);
indirect[1+i] = Game.NB_MAX_OBJECTS/2;
indirect[2+i] = 0;
indirect[3+i] = i==0?0:getElementCount().get(i-1);
indirect[4+i] = i; // maybe 0
}
vboIdIndirect = glGenBuffers();
IntBuffer gIndirectBuffer = MemoryUtil.memAllocInt(indirect.length);
gIndirectBuffer.put(indirect).flip();
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, vboIdIndirect);
glBufferData(GL_DRAW_INDIRECT_BUFFER, gIndirectBuffer, GL_DYNAMIC_DRAW);
and my elements buffer
vboId = glGenBuffers();
vboIdList.add(vboId);
indicesBuffer = MemoryUtil.memAllocInt(indices.length);
indicesBuffer.put(indices).flip();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_DYNAMIC_DRAW);
indices contains indices for NB_TYPE_MESH types of mesh

If a buffer is bound to the target GL_DRAW_INDIRECT_BUFFER when glMultiDrawElementsIndirect is called, the indirect argument is interpreted as an offset in basic machine units into this buffer.
Hence you need to bind the GL_DRAW_INDIRECT_BUFFER before drawing the elements, but the indirect argument must be null:
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, this.modelManager.indirect, NB_TYPE_MESH, 0);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, vboIdIndirect);
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, null, NB_TYPE_MESH, 0);
See also Java Code Examples glMultiDrawElementsIndirect()

Related

glCopyBufferSubData Segmentation Fault SIGSEGV

I've recently stumbled on a problem that took a few hours to pin down. On a desctop PC my code worked fine, but on a Vivante embedded device it crashed with segmentation fault on a seemingly good code.
Here's the code:
// get our VBO
vboID = vboIDList.get(1);
glBindBuffer(GL_COPY_READ_BUFFER, vboID);
// create new buffer and copy data
int newVboID = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, newVboID);
indexBuffer = MemoryUtil.memAllocInt(indexBufferLength);
indexBuffer.put(new int[indexBufferLength]).flip();
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBuffer, GL_STATIC_DRAW);
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_ELEMENT_ARRAY_BUFFER, 0, 0, indexCount * INT_SIZE);
//INT_SIZE is a static final = 4
//replace VBO
vboIDList.set(1, newVboID);
glDeleteBuffers(vboID);
// unbind buffers
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_COPY_READ_BUFFER, 0);
it crashed on glBufferSubData with no clear reason.
Turned out that in a rare case indexCount was equal 0, so I was trying to copy 0 bytes. Some drivers handle this well, but others do not.
Just in case someone stumbles on this too, that's my answer. Check for a positive copy length before calling glCopyBufferSubData().

I'm trying to render a model using vbo in OpenGL (LWJGL)

I am trying to render a model by importing the .obj File. Im successfully importing and preparing the data to be rendered in FloatBuffers/IntegerBuffers but cant manage to render it. Can someone help me?
This is the class that renders and initializes the VBOs
private int vertexBufferID;
private int indexBufferID;
private int numberIndices;
public void init() {
try{
InputStream objInputStream = new FileInputStream("./res/obj/Terrain.obj");
Obj obj = ObjReader.read(objInputStream);
obj = ObjUtils.convertToRenderable(obj);
IntBuffer indices = ObjData.getFaceVertexIndices(obj, 3);
FloatBuffer vertices = ObjData.getVertices(obj);
// FloatBuffer texCoords = ObjData.getTexCoords(obj, 2);
// FloatBuffer normals = ObjData.getNormals(obj);
vertexBufferID = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferID);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL30.glBindVertexArray(0);
indexBufferID = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
}catch(IOException e)
{
e.printStackTrace();
}
}
public void render() {
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vertexBufferID);
GL11.glVertexPointer(3, GL11.GL_FLOAT, 0, 0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
GL11.glDrawElements(GL11.GL_TRIANGLES, numberIndices, GL11.GL_UNSIGNED_INT, 0);
}
I get no error code the object is just not rendered. I am able to render the Object using Display Lists.
I've now solved the problem and am now able to import .obj-Files and render them using vbo/vao. Im using "Obj - a simple Wavefront OBJ file loader and writer" to prepare the data to be rendered.
The code to load up and prepare the .obj file
InputStream objInputStream = new FileInputStream(pathTObjFile);
Obj obj = ObjReader.read(objInputStream);
obj = ObjUtils.convertToRenderable(obj);
IntBuffer indices = ObjData.getFaceVertexIndices(obj, 3);
FloatBuffer vertices = ObjData.getVertices(obj);
Now the data is stored in 2 VBOs and the VBO for the vertices is stored in a VAO:
vaoId = GL30.glGenVertexArrays();
The Vertex Array Object ID (vaoID) is an Integer that is called if we are calling the VAO.
GL30.glBindVertexArray(vaoId);
To be able to do anything with the VAO we have to bind or "select" it.
vboId = GL15.glGenBuffers();
The VBOs also have an ID to be called with. We are creating the Vertex Buffer Object ID here (vboId)
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);
Now we select the VBO and store the vertices in it.
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL30.glBindVertexArray(0);
First we put the VBO in the first attribute list of the VAO (a VAO has 16 lists), then we unbind the VAO and the VBO.
vboiId = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
indicesCount = indices.capacity();
At the end of the Initialization we have create the vbo for the indices so the Vertices can be connected to each others to create faces in the right way. Therefor we bind the vboiId and store the index data inside. Then we unbind the VBO again and save the number of Indices stored in the VBO because we have to tell it OpenGL to be able to render it later.
Rendering the Object:
GL30.glBindVertexArray(vaoId);
GL20.glEnableVertexAttribArray(0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);
To Render the Object we have to bind the VAO and the VBO inside. We also have to select the VBO for the Indices. That is done by the code snippet above.
GL11.glDrawElements(GL11.GL_TRIANGLES, indicesCount, GL11.GL_UNSIGNED_INT, 0);
Now we draw the Object and
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
Deselect the VBOs and VAOs again.
Here is the whole code combined
private int vboiId;
private int vaoId;
private int vboId;
private int indicesCount;
public void init() {
try{
InputStream objInputStream =
new FileInputStream("./res/obj/Terrain.obj");
Obj obj = ObjReader.read(objInputStream);
obj = ObjUtils.convertToRenderable(obj);
IntBuffer indices = ObjData.getFaceVertexIndices(obj, 3);
FloatBuffer vertices = ObjData.getVertices(obj);
FloatBuffer texCoords = ObjData.getTexCoords(obj, 2);
FloatBuffer normals = ObjData.getNormals(obj);
indicesCount = indices.capacity();
vaoId = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vaoId);
vboId = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertices, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL30.glBindVertexArray(0);
vboiId = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indices, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
}catch(IOException e)
{
e.printStackTrace();
}
}
public void render() {
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
GL30.glBindVertexArray(vaoId);
GL20.glEnableVertexAttribArray(0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);
GL11.glDrawElements(GL11.GL_TRIANGLES, indicesCount, GL11.GL_UNSIGNED_INT, 0);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
For further and more detailed information i strongly recommend u to read The quad with Draw Array, The Quad with Draw Elements and if you want to go more in detail look up the OpenGL 3.2 and above tutorials on the Main Page of the LWJGL Wiki.
For information on how to use the Obj loader I used look up The sample projects using this loader
My code basically consists of a mixture of the code on this websites.
Edit: If you try to render multiple Objects you have to Clear the Color before rendering the first object (First line of the Render method)

OpenGL vertex arrays throw invalid operation error

I've recently started using OpenGL and LWJGL but ever since I tried to mess with/add vertex array objects, I've been getting the same error over and over:
GL_INVALID_OPERATION
I am having a hard time understanding why but I managed to pin down to problem to these methods:
glEnableClientState(GL_VERTEX_ARRAY);
vao = glGenVertexArrays();
glBindVertexArray(vao);
glEnableVertexAttribArray(vao);
glVertexAttribPointer(0, count, GL_FLOAT, false, Float.SIZE * 2, 0);
glBindVertexArray(0);
...so basically anything that has to do with vertex arrays throws this error. If anyone could point out what exactly I am doing wrong, that would be great. This is the rest of my code:
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import static org.lwjgl.opengl.GL30.*;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import org.lwjgl.BufferUtils;
public class Model {
private int count;
private int ibo, vao;
public Model(float[] vertices, int[] indices) {
count = indices.length;
glEnableClientState(GL_VERTEX_ARRAY);
vao = glGenVertexArrays();
glBindVertexArray(vao);
glEnableVertexAttribArray(vao);
glVertexAttribPointer(0, count, GL_FLOAT, false, Float.SIZE * 2, 0);
glBindVertexArray(0);
FloatBuffer vBuffer = BufferUtils.createFloatBuffer(vertices.length);
vBuffer.put(vertices).flip();
int vbo = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vBuffer, GL_STATIC_DRAW);
IntBuffer iBuffer = BufferUtils.createIntBuffer(indices.length);
iBuffer.put(indices).flip();
ibo = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, iBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
public void draw() {
glBindVertexArray(vao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0);
}
}
The parameter of glEnableVertexAttribArray is the attibute index. This means you have to change your code like this:
glBindVertexArray( vao );
glEnableVertexAttribArray( 0 ); // <--- attribute index instead of object name
Or you may use glEnableVertexArrayAttrib:
glEnableVertexArrayAttrib( vao, 0 );
OpenGL 4.6 core profile specification, 10.3. VERTEX ARRAYS, page 354:
An individual generic vertex attribute array in a vertex array object is enabled with the commands
void EnableVertexAttribArray( uint index );
void EnableVertexArrayAttrib( uint vaobj, uint index );
Note, glEnableClientState is part of the deprecated fixed function pipeline. If you want to use the fixed function pipeline and glEnableClientState, then you have to use glVertexPointer instead of glVertexAttribPointer.

How to create and use VBOs in OpenGL ES 2

I am looking for help with understanding VBOs. I have done a ton of research and have found tutorials on the subject, but they are still vague to me. I have a few questions:
Where should a VBO be created, and how should I create one?
I am currently using the code right below to initialize my vertex and index buffers:
vertices = new float[]
{
p[0].x, p[0].y, 0.0f,
p[1].x, p[1].y, 0.0f,
p[2].x, p[2].y, 0.0f,
p[3].x, p[3].y, 0.0f,
};
// The order of vertex rendering for a quad
indices = new short[] {0, 1, 2, 0, 2, 3};
ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer dlb = ByteBuffer.allocateDirect(indices.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(indices);
drawListBuffer.position(0);
If I am correct, this is not creating a VBO. So, if I wanted to make a VBO, would the code to create a VBO go right after the code listed above? If so, how would it be created?
Also, how is a VBO rendered and drawn to screen?
Is it rendered and drawn the same way as just using vertex and index arrays? If not, what is the process? Currently, I render and draw my objects as shown in the code below:
GLES20.glUseProgram(GraphicTools.sp_SolidColor);
mPositionHandle =
GLES20.glGetAttribLocation(GraphicTools.sp_SolidColor, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_FLOAT, false,
0, vertexBuffer);
mtrxHandle = GLES20.glGetUniformLocation(GraphicTools.sp_SolidColor,
"uMVPMatrix");
GLES20.glUniformMatrix4fv(mtrxHandle, 1, false, m, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
If you have any questions, let me know. Thanks in advance.
A Vertex Buffer Object is a buffer where vertex array data can be stored. The data are uploaded one time to the graphics memory (GPU) and can be used repeatedly to draw a mesh.
First you have to create 2 buffer objects, one for the vertices and one for the indices:
int buffers[] = new int[2];
GLES20.glGenBuffers(2, buffers, 0);
int vbo = buffers[0];
int ibo = buffers[1];
Then you have to bind the buffer and to transfer the data
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo);
GLES20.glBufferData(
GLES20.GL_ARRAY_BUFFER,
vertexBuffer.capacity() * 4, // 4 = bytes per float
vertexBuffer,
GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo);
GLES20.glBufferData(
GLES20.GL_ELEMENT_ARRAY_BUFFER,
drawListBuffer.capacity() * 2, // 2 = bytes per short
drawListBuffer,
GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
If you want to draw the mesh, then you have to define the array of generic vertex attribute data and you have to bind the index buffer, but you don't have to transfer any data to the GPU:
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo);
GLES20.glVertexAttribPointer(
mPositionHandle, 3,
GLES20.GL_FLOAT, false,
0, 0); // <----- 0, because "vbo" is bound
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo);
GLES20.glDrawElements(
GLES20.GL_TRIANGLES, indices.length,
GLES20.GL_UNSIGNED_SHORT, 0); // <----- 0, because "ibo" is bound
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
See also An Introduction to Vertex Buffer Objects (VBOs)

VAO Rendering incorrectly in LWJGL

I am trying to use VAOs to render and am having trouble with incorrect rendering.
I do have a little experience in the subject but not a huge amount.
This is my binding Code:
//RawModel is just a type to store vao id and number of indices.
public RawModel loadToVao(float[] positions, int[] indices){
//create VAO and bind it
int vaoID = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vaoID);
//create index buffer
int indexVBO = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, indexVBO);
IntBuffer indexBuffer = BufferUtils.createIntBuffer(indices.length);
indexBuffer.put(indices);
indexBuffer.flip();
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indexBuffer , GL15.GL_STATIC_DRAW);
//create vertex buffer
int positionVBO = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, positionVBO);
FloatBuffer vertBuffer = BufferUtils.createFloatBuffer(positions.length);
vertBuffer.put(positions);
vertBuffer.flip();
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, vertBuffer , GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0,0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL30.glBindVertexArray(0);
return new RawModel(vaoID, indices.length);
}
This is my render code:
GL30.glBindVertexArray(obj.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL11.glDrawArrays(GL11.GL_POINTS, 0, sphere.getRawModel().getSize());
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, sphere.getRawModel().getSize());
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
I render both points and Triangles just to see what is going wrong. eventually will only be triangles.
This code always seems to give me a point at the objects centre which should not be there. It also has incorrect grouping of elements so triangles render completely wrong.
If anyone could help it would be great.
Thanks

Categories