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)
Related
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.
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)
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
I am trying to render large VBO array objects, containing ~700000 values and I have ~1500000 values in my element_array buffer. But what I am getting is a blank screen. On the other hand if I just use only the VAO, my code works correctly. My code is as follows:
//Data buffers
FloatBuffer vertexBuffer = GLBuffers.newDirectFloatBuffer(this.coordCount);
vertexBuffer.put(Vertices);
vertexBuffer.rewind();
IntBuffer indexBuffer = GLBuffers.newDirectIntBuffer(this.indexCount);
indexBuffer.put(index);
indexBuffer.rewind();
//setting up the VBO
int nVBO = 2;
int[] VBO = new int[nVBO];
gl.glGenBuffers(nVBO, VBO,0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBO[0]);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER,VBO[1]);
gl.glBufferData(GL.GL_ARRAY_BUFFER, this.coordCount*Float.SIZE, vertexBuffer, GL.GL_STATIC_DRAW);
gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, this.indexCount*Integer.SIZE, indexBuffer, GL.GL_STATIC_DRAW);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, VBO[0]);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, VBO[1]);
gl.glEnableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
//gl.glVertexPointer(3, GL.GL_FLOAT, 0, vertexBuffer);
//gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
gl.glDrawElements(GL.GL_TRIANGLES, this.indexCount, GL.GL_UNSIGNED_INT, 0);
//gl.glDrawElements(GL.GL_TRIANGLES, this.indexCount, GL.GL_UNSIGNED_INT, indexBuffer);
gl.glDisableClientState(GLPointerFunc.GL_VERTEX_ARRAY);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
Any clues/suggestions on how I can fix this?
Is this code block called each time when the loop runs? If it is, you should divide your vbo phases into different blocks.This sample code may help you how to divide. (In the link that I post, you should just focus initVBO and renderVbo functions) I guess your initializing your vbo's sequentially, which it may make your program unresponsive.