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.
Related
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()
I recently decided to start Learning OpenGL and got myself a book about OpenGL Core 3.3. The book is generally about C++.
So, after looking for a bit, I found a library in a language I was better in which provided almost the same functionality: lwjgl.
I followed the book's steps and translated the C++ syntax into java syntax, which worked until it got to actually drawing something.
There, the JVM just kept crashing, no matter what I changed about the code. After doing some debugging, I found out that the JVM crashed when I called either glVertexAttribPointer or glDrawArrays.
I am very new to OpenGL, and I am assuming this question must sound very stupid to someone more experienced, but: What do I need to change about this code?
float[] vertices = {
-0.5f, -0.5f, -0.0f,
0.5f, 0.5f, 0.0f,
0.0f,0.5f,0.0f
};
FloatBuffer b = BufferUtils.createFloatBuffer(9);
b.put(vertices);
int VBO = glGenBuffers();
int VAO = glGenVertexArrays();
log.info("VBO:" + VBO + "VAO: " + VAO);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(VAO);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 12, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
glBindVertexArray(0);
// Run the rendering loop until the user has attempted to close
// the window or has pressed the ESCAPE key.
while (!glfwWindowShouldClose(window))
{
// input
// -----
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw our first triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0); // no need to unbind it every time
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
I would be very thankful for any help i can get, if you need more info/ need to see more of my code please let me know. Thanks in advance
You have to bind the vertex buffer object to the target GL_ARRAY_BUFFER, before specifying the vertex attribute:
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 12, 0);
When glVertexAttribPointer is called, the buffer object currently bound to the ARRAY_BUFFER target is associated to the attribute (index) and a reference to the buffer object is stored in the state vector of the Vertex Array Object.
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)
I am trying to learn how to use LWJGL3 and I just got to a state where I want to render something (a test quad for now). I have a class that represents a mesh where I set up the VAO with vertex, colour and indices buffers and another object later takes the mesh instance, retrieves its VAO ID and attempts to render it.
The problem I have is that no matter what I try, nothing renders in the window. I can change the background colour through the glClearColor() method but the quad never shows up.
The VAO set up:
vertexCount = indices.length;
vaoID = glGenVertexArrays();
glBindVertexArray(vaoID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
//Vertices
FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(positions.length);
verticesBuffer.put(positions).flip();
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, verticesBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * 4, 0);
//Colours
FloatBuffer colorsBuffer = BufferUtils.createFloatBuffer(colors.length);
colorsBuffer.put(colors).flip();
colVboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, colVboID);
glBufferData(GL_ARRAY_BUFFER, colorsBuffer, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, false, 3 * 4, 0);
//Indices
IntBuffer indicesBuffer = BufferUtils.createIntBuffer(indices.length);
indicesBuffer.put(indices).flip();
idxVboID = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, idxVboID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL_STATIC_DRAW);
//Unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
The rendering code:
//Bind the shader
shaderProgram.bind();
//Bind the VAO
glBindVertexArray(mesh.getVaoID());
//Draw
glDrawElements(GL_TRIANGLES, mesh.getVertexCount(), GL_UNSIGNED_INT, 0);
//Restore
glBindVertexArray(0);
shaderProgram.unbind();
Vertex shader:
#version 330
layout (location=0) in vec3 pos;
layout (location=1) in vec3 inColor;
out vec3 exColor;
void main()
{
gl_Position = vec4(pos, 1.0);
exColor = inColor;
}
Fragment shader:
#version 330
in vec3 exColor;
out vec4 fragColor;
void main()
{
fragColor = vec4(exColor, 1.0);
}
What am I doing wrong?
The problem was not in the parts of code shown, but in the main loop that I copied from a book without thoroughly thinking through what it did. I ended up with a glClear call right before glfwSwapBuffers call, which cleared the buffer right before showing it.
Lesson of the day: don't just copy from a book, think thoroughly about what you're doing
(Thank you to the people of LWJGL formus for helping me discover this mistake)
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