glDrawElementsInstanced: VertexAttribute mat4 not applied per instance - java

I have a problem with rendering multiple instances of an object, using one VertexArrayObject and four VertexBufferObjects.
I cannot get my head around what's wrong with my approach.
Here are the basics:
My relatively simple Vertex-Shader-code:
#version 330 core
precision highp float;
layout (location=0) in vec3 position;
layout (location=1) in vec2 texcoord;
layout (location=3) in mat4 modelViewMatrix;
out vec2 textureCoord;
uniform mat4 pr_matrix;
void main() {
textureCoord = vec2(texcoord.x, texcoord.y);
vec4 mvPos = modelViewMatrix * vec4(position, 1.0);
gl_Position = pr_matrix * mvPos;
}
As you can see, I try to pass the model view matrix (model and camera_view combined) as an VertexAttribute.
As far as I know, a VertexAttribute is limited to a max of vec4, which means my mat4 will actually take up 4 * vec4 locations.
Each VAO and VBO exists only once. I do not use a separate one for each "gameobject", as some online-tutorials do.
Therefore I update each of the Buffers at specific positions. Buf first, let me show you the following code, which initializes them:
// VAO
this.vao = glGenVertexArrays();
glBindVertexArray(this.vao);
// buffer for vertex positions
this.positionVBO = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, this.positionVBO);
// upload null data to allocate vbo storage in memory
glBufferData(GL_ARRAY_BUFFER, vertexpoints * Float.BYTES, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
// buffer for texture coordinates
this.textureVBO = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, this.textureVBO);
glBufferData(GL_ARRAY_BUFFER, texturepoints * Float.BYTES, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, 0);
// buffer for transform matrices
this.matricesVBO = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, this.matricesVBO);
glBufferData(GL_ARRAY_BUFFER, mtrxsize * Float.BYTES, GL_DYNAMIC_DRAW);
// Byte size of one vec4
int vec4Size = 4 * Float.BYTES;
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, false, 4 * vec4Size, 0);
glVertexAttribDivisor(3, 1);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, false, 4 * vec4Size, 1 * vec4Size);
glVertexAttribDivisor(4, 1);
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_FLOAT, false, 4 * vec4Size, 2 * vec4Size);
glVertexAttribDivisor(5, 1);
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, false, 4 * vec4Size, 3 * vec4Size);
glVertexAttribDivisor(6, 1);
//buffer for indices
this.indicesVBO = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this.indicesVBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indsize * Integer.BYTES, GL_DYNAMIC_DRAW);
//unbind buffers and array
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
As far as I'm aware, this initialization should correspond to the 4 VertexAttributes, defined in the Vertex-Shader.
For test purposes, I initialize 4 gameobjects (A1, A2, B1, B2), each with:
4 x vec3 points for the position-attribute, resulting in 4 * 3 = 12 floating-points pushed to the positionVBO
4 x vec2 points for the texture-attribute, resulting in 4 * 2 = 8 floating-points pushed to the textureVBO
6 x int points for the indices to draw (0, 1, 2, 2, 3, 0), pushed to the indicesVBO
1 x mat4 for the modelViewMatrix-attribute, resulting in 4 * vec4 = 4 * 4 = 16 floating-points pushed to the matricesVBO
for each gameobject I push its data to the VBOs, using the following logic:
long vertoff = gameObjectVertOffset; // offset of the current gameobject's vertex points in position data
long texoff = gameObjectTexOffset; // offset of the current gameobject's texture points in texture data
long indoff = gameObjectIndOffset; // offset of the current gameobject's indices in index data
long instoff = gameObjectMatrixOffset; // offset of the current gameobject's matrix (vec4) in matrices data
// upload new position data
if(gameObjectVertBuf.capacity() > 0) {
gameObjectVertBuf.flip();
glBindBuffer(GL_ARRAY_BUFFER, this.positionVBO);
glBufferSubData(GL_ARRAY_BUFFER, vertoff * Float.BYTES, gameObjectVertBuf);
}
// upload new texture data
if(gameObjectTexBuf.capacity() > 0) {
gameObjectTexBuf.flip();
glBindBuffer(GL_ARRAY_BUFFER, this.textureVBO);
glBufferSubData(GL_ARRAY_BUFFER, texoff * Float.BYTES, gameObjectTexBuf);
}
// upload new indices data
if(gameObjectIndBuf.capacity() > 0) {
gameObjectIndBuf.flip();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this.indicesVBO);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, indoff * Integer.BYTES, gameObjectIndBuf);
}
// upload new model matrix data
if(gameObjectMatrixBuf.capacity() > 0) {
gameObjectMatrixBuf.flip();
glBindBuffer(GL_ARRAY_BUFFER, this.matricesVBO);
glBufferSubData(GL_ARRAY_BUFFER, instoff * Float.BYTES, gameObjectMatrixBuf);
}
Now to the actual rendering:
I want to draw element A 2 times and after that, element B 2 times.
for the instanced rendering, I group together the gameobjects, I knew i could render in one call, inside lists.
I now have two lists, each with two elements in them:
List1[A1, A2]
List2[B1, B2]
Once per list I now do:
numInstances = 2;
this.vao.bind();
shaderprogram.useProgram();
glDrawElementsInstanced(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, (int) (offset * Integer.BYTES), numInstances);
offset += 6 * numInstances; // 6 indices * 2 instances
The Problem:
This results in the first two elements being rendered correctly, but the second two (from the second list / glDrawElementsInstanced() call) are rendered with the transformation matrices of the first two elements.
It does not matter, which list of objects are rendered first. The second iteration always seems to use the modelViewMatrix attributes from the first ones.
As far as I understood, the glVertexAttribDivisor() call should limit the iteration of the matrices per instance instead of per vertex.
What am I missing here?

the second two (from the second list / glDrawElementsInstanced() call) are rendered with the transformation matrices of the first two elements.
That's what you asked to do. How would the system know that it would need to use the second two elements from the array instead of the first two? All it sees is another draw call, and there are no changes to VAO state between them.
The system doesn't keep up with how many instances have been used in prior draw calls. That's your job.
Now, you could change the buffer binding for the attributes in question, but it's easier to use base-instance rendering. In these drawing functions, you specify an offset that is applied to the instance index for instanced attributes. So if you want to render two instances starting at instance index 2, you do this:
glDrawElementsInstancedBaseInstance(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, (int) (offset * Integer.BYTES), 2, 2);
Base instanced rendering is a GL 4.2 feature.

Related

OpenGl error Validation Failed: No vertex array object bound [duplicate]

This question already has an answer here:
Why does glValidateProgram fail when no VAO is bound?
(1 answer)
Closed last year.
Mesh class longer unbinds vao, though it still doesn't work. Everything seems like it should be in order. I bind vao, then vbo, I create the shader, but then it screws up validating it cause the vao isn't bound? How? I bind it when I make the mesh and never unbind it. I don't understand this program. What am I doing wrong
public boolean create(float vertices[]) {
vCount=vertices.length/3;
//generate vao id
vao=glGenVertexArrays();
glBindVertexArray(vao);
vbo=glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//static draw stores data in GPU
//GL_DYNAMIC_DRAW stores it in ram to be more accessible
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);//pass vertex data
/*glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, false, VERTEX_SIZE * 4, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, VERTEX_SIZE * 4, 12);*/
glVertexAttribPointer(0,3,GL_FLOAT,false,0,0);//allocates 3 spaces for x,y,z floats
return true;
}
Simple draw function.
public void draw() {
glDrawArrays(GL_TRIANGLES,0,vCount);
}
I shouldn't need to make a buffer or something for camera/object transform, should I? This method just initializes is
glUniformMatrix4fv(uniOProjectionMat,true,obj);
with my shader
#version 330 core
layout(location=0) in vec3 position;
uniform mat4 worldTransform;
uniform mat4 objectTransform;
uniform mat4 projection;
void main(){
gl_Position=projection*worldTransform *
objectTransform* vec4(position,1);
}
glValidateProgram checks whether the program can execute with the current OpenGL state. Because there is no standard vertex array object in a core profile context, you must bind a named VAO before validating the program.
Bind your VAO before the program is validated or don't call unBindVAO(). There is no need to unbind the VAO at all.

OpenGL VBO with single float per Vertex problem

I have been stuck all day yesterday with this problem and cant figure it out. The code is below but generally i am trying to give a mesh Vertex Attributes for 1.Postions 2.Indices 3.Normals and 4.a single float value.
The values are all stored in different VBOs and after binding each vbo i declare the vertexAttribPointer. I cant get both normals and float value working. What im seeing seems like the position of the float value is either the x y or z part of the normals vec3 in the previous vbo.
GL4 gl = GLContext.getCurrentGL().getGL4();
int[] vaoids = new int[1];
gl.glGenVertexArrays(1,vaoids,0);
int[] vboids = new int[4];
gl.glGenBuffers(4,vboids,0);
gl.glBindVertexArray(vaoids[0]);
FloatBuffer verticesBuffer = FloatBuffer.allocate(mesh.vertices.length);
verticesBuffer.put(mesh.vertices);
verticesBuffer.flip();
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vboids[0]);
gl.glBufferData(gl.GL_ARRAY_BUFFER, mesh.vertices.length * 4 ,verticesBuffer,gl.GL_STATIC_DRAW);
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(0, 3, gl.GL_FLOAT, false, 0, 0);
verticesBuffer.clear();
verticesBuffer = null;
//normal buffer
FloatBuffer normalBuffer = FloatBuffer.allocate(mesh.normals.length);
normalBuffer.put(mesh.normals);
normalBuffer.flip();
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vboids[2]);
gl.glBufferData(gl.GL_ARRAY_BUFFER, mesh.normals.length * 4 ,normalBuffer,gl.GL_STATIC_DRAW);
gl.glEnableVertexAttribArray(2);
gl.glVertexAttribPointer(2, 3, gl.GL_FLOAT, false, 0, 0);
normalBuffer.clear();
normalBuffer = null;
//color buffer
float[] colors = new float[mesh.vertices.length/3];
Arrays.fill(colors,255.0f);
FloatBuffer colorBuffer = FloatBuffer.allocate(colors.length);
colorBuffer.put(colors);
colorBuffer.flip();
gl.glBindBuffer(gl.GL_ARRAY_BUFFER, vboids[3]);
gl.glBufferData(gl.GL_ARRAY_BUFFER, colors.length * 4 ,colorBuffer,gl.GL_STATIC_DRAW);
gl.glEnableVertexAttribArray(3);
gl.glVertexAttribPointer(3, 1, gl.GL_FLOAT,false, 0, 0);
colorBuffer.clear();
colorBuffer = null;
IntBuffer indicesBuffer = IntBuffer.allocate(mesh.indices.length);
indicesBuffer.put(mesh.indices);
indicesBuffer.flip();
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, vboids[1]);
gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, mesh.indices.length * 4 ,indicesBuffer,gl.GL_STATIC_DRAW);
gl.glEnableVertexAttribArray(1);
gl.glVertexAttribPointer(1, mesh.type.equals(MeshType.TRIANGLE) ? 3 : mesh.type.equals(MeshType.LINE) ? 2 : mesh.type.equals(MeshType.POINT) ? 1:0, gl.GL_UNSIGNED_INT, false, 0, 0);
indicesBuffer.clear();
indicesBuffer = null;
//gl.glBindBuffer(gl.GL_ARRAY_BUFFER,0);
gl.glBindVertexArray(0);
This the code that declares the vao and vbos. I render with glDrawElements and enable the needed VertexAttributeArray Indices before that. In my Shader I access the value as following:
layout (location=0) in vec3 position;
layout (location=2) in vec3 normal;
layout (location=3) in float color;
out vec3 normals;
out vec4 positionWorldSpace;
out flat float vertexColor;
And the fragment shader
in flat float color;
I can get both of them working separate but if i declare both they float values are not correct anymore. The normals seems to be right however. As i said the values in the float seem the be values from the normals. Can there be some sort of overflow from the normal vbo to the float vbo? After hours of looking at the code i just cant spot the error.
The indices are not attributes. The [Index buffer](Index buffers) (GL_ELEMENT_ARRAY_BUFFER) is stated in the VAO directly. See Vertex Specification.
When you use glDrawArrays then the order vertex coordinates of the vertex coordinates in the array defines the primitives. If you want to use a different order or you want to use vertices for different primitives, then you have to use glDrawElements. When you use glDrawElements, then the primitives are defined by the vertex indices in the GL_ELEMENT_ARRAY_BUFFER buffer:
gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, vboids[1]);
gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER, mesh.indices.length * 4 ,indicesBuffer,gl.GL_STATIC_DRAW);
// DELETE
//gl.glEnableVertexAttribArray(1);
//gl.glVertexAttribPointer(1, mesh.type.equals(MeshType.TRIANGLE) ? 3 : mesh.type.equals(MeshType.LINE) ? 2 : mesh.type.equals(MeshType.POINT) ? 1:0, gl.GL_UNSIGNED_INT, false, 0, 0);
indicesBuffer.clear();
indicesBuffer = null;
gl.glBindVertexArray(0);
gl.glDrawElements(gl.GL_TRIANGLES, mesh.indices.length, gl.GL_UNSIGNED_INT, null);

Empty render with OpenGL on Android

I'm trying to render a scene using OpenGL ES 2.0 in an Android App, however, the screen keeps being drawn with the defined clear color.
I had success rendering simpler examples, but I'm failing when using packed vertex buffer.
The idea is to render a scene with a camera inside a Sphere, here are some code snippets which should give some context and also is where I think the bug is.
Fragment Shader:
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 vTextureCoord;
uniform inputImageTexture;
void main()
{
vec4 color = texture2D(inputImageTexture, vTextureCoord);
gl_FragColor = vec4(1.0);
}
Vertex Shader:
uniform mat4 uMVPMatrix;
uniform mat4 uTransform;
attribute vec4 aPosition;
attribute vec4 aTextureCoord;
varying vec2 vTextureCoord;
void main()
{
gl_Position = uMVPMatrix * aPosition * vec4(1, -1, 1, 1);
vec4 coord = (aTextureCoord / 2.0) + 0.5;
vTextureCoord = (uTransform * coord).xy;
}
The GL program initialization:
mProgram = new ProgramObject();
if(mProgram.init(vsh, fshResult)) {
GLES20.glClearColor(1.0f, 0.f, 0.f, 1.f);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glDisable(GLES20.GL_CULL_FACE);
uMVPMatrixLocation = mProgram.getUniformLoc("uMVPMatrix");
aPositionLocation = mProgram.attributeLocation("aPosition");
aTextureCoordLocation = mProgram.attributeLocation("aTextureCoord");
mTransformLoc = mProgram.getUniformLoc("uTransform");
}
Vertex loading:
sphere = new Sphere(SPHERE_SLICES, 0.f, 0.f, 0.f, SPHERE_RADIUS, SPHERE_INDICES_PER_VERTEX);
mProgram.bind();
final int buffers[] = new int[1];
GLES20.glGenBuffers(1, buffers, 0);
mVertexBuffer = buffers[0];
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBuffer);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, sphere.getVerticesSize(), sphere.getVertices(), GLES20.GL_STATIC_DRAW);
Render:
GLES20.glViewport(viewport.x, viewport.y, viewport.width, viewport.height);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(TEXTURE_2D_BINDABLE, texID);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBuffer);
GLES20.glEnableVertexAttribArray(aPositionLocation);
GLES20.glVertexAttribPointer(aPositionLocation, 3,
GLES20.GL_FLOAT, false, sphere.getVerticesStride(), sphere.getVertices());
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBuffer);
GLES20.glEnableVertexAttribArray(aTextureCoordLocation);
GLES20.glVertexAttribPointer(aTextureCoordLocation, 2,
GLES20.GL_FLOAT, false, sphere.getVerticesStride(),
sphere.getVertices().duplicate().position(3));
Matrix.multiplyMM(pvMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
Matrix.multiplyMM(mvpMatrix, 0, pvMatrix, 0, modelMatrix , 0);
GLES20.glUniformMatrix4fv(uMVPMatrixLocation, 1, false, mvpMatrix, 0);
for (int j = 0; j < sphere.getNumIndices().length; ++j) {
GLES20.glDrawElements(GLES20.GL_TRIANGLES, sphere.getNumIndices()[j], GLES20.GL_UNSIGNED_SHORT, sphere.getIndices()[j]);
}
Any insights are welcome, thank you very much.
Update
The could was running without any errors on a Galaxy S6, but, now running on a One Plus X I'm getting the following error:
<gl_draw_error_checks:598>: GL_INVALID_OPERATION
glDrawElements: glError 0x502
After running:
for (int j = 0; j < sphere.getNumIndices().length; ++j) {
GLES20.glDrawElements(GLES20.GL_TRIANGLES, sphere.getNumIndices()[j], GLES20.GL_UNSIGNED_SHORT, sphere.getIndices()[j]);
}
You're mixing up two ways of using vertex arrays:
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBuffer);
...
GLES20.glVertexAttribPointer(aPositionLocation, 3,
GLES20.GL_FLOAT, false, sphere.getVerticesStride(), sphere.getVertices());
In ES 2.0, there are two ways of using vertex arrays:
Client-side vertex arrays.
Vertex-buffer objects (VBOs).
With client-side vertex arrays, you don't store your vertex data in VBOs, but pass the vertex data directly as the last argument to the glVertexAttribPointer() call. In C/C++ bindings, this is a pointer to the data, in the Java bindings it's a Java Buffer object.
When using VBOs, you store your vertex data in a VBO, using glBufferData(). Then you bind the VBO before the glVertexAttribPointer() call, and pass the offset of the data relative to the start of the VBO as the last argument.
In your example:
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBuffer);
GLES20.glEnableVertexAttribArray(aPositionLocation);
GLES20.glVertexAttribPointer(aPositionLocation, 3,
GLES20.GL_FLOAT, false, sphere.getVerticesStride(), 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBuffer);
GLES20.glEnableVertexAttribArray(aTextureCoordLocation);
GLES20.glVertexAttribPointer(aTextureCoordLocation, 2,
GLES20.GL_FLOAT, false, sphere.getVerticesStride(), 12);
Note that the offset is in bytes, so it's 12 bytes if your colors are offset by 3 floats relative to the positions.
Client-side vertex arrays are deprecated, and partly unavailable, in newer versions of OpenGL. So storing the data in VBOs, as you already are, is the right way to go.

How do I use Vertex Array Objects in OpenGL

I'm using lwjgl 3 as a Java wrapper to OpenGL, and I'm trying to figure out how to render things with Vertex Array Objects. I have not been able to find any examples online that show how to use a VAO that has both shader attributes and uses the element array buffer.
According to this vao tutorial, I need to do something like this:
// Create a new Vertex Array Object in memory and select it (bind)
// A VAO can have up to 16 attributes (VBO's) assigned to it by default
vaoId = GL30.glGenVertexArrays();
GL30.glBindVertexArray(vaoId);
// Create a new Vertex Buffer Object in memory and select it (bind)
// A VBO is a collection of Vectors which in this case resemble the location of each vertex.
vboId = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticesBuffer, GL15.GL_STATIC_DRAW);
// Put the VBO in the attributes list at index 0
GL20.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
// Deselect (bind to 0) the VBO
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
// Deselect (bind to 0) the VAO
GL30.glBindVertexArray(0);
However, I don't understand how to adapt this tutorial to my project, because I am using glVertexAttribPointer to deal with fields in the shader. These fields have id's that are assigned to them when the shader is compiled. In the above example, they seem to be able to use the default field 0. However, I checked, for me posAttrib is in field 0.
How should I associate a VBO with my VAO?
private int createVao(int shaderProgramId, FloatBuffer vertices, IntBuffer order) {
int floatSize = 4;
int stride = 7 * floatSize;
int vaoId = glGenVertexArrays();
glBindVertexArray(vaoId);
int vboId = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
int eboId = glGenBuffers();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboId);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, order, GL_STATIC_DRAW);
int posAttrib = shaderProgramService.getAttribute(shaderProgramId, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, false, stride, 0);
int colAttrib = shaderProgramService.getAttribute(shaderProgramId, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, false, stride, 2 * floatSize);
int texAttrib = shaderProgramService.getAttribute(shaderProgramId, "texcoord");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, false, stride, 5 * floatSize);
// glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); <==== Removed
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
return vaoId;
}
EDIT: Thanks #RetoKoradi, getting rid of the glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); call improved things. The scene flashed onscreen, but I got a seg-fault on the second frame. After some debugging, the issue was with another object I was trying to render that was not yet using VAO's. I was making calls like this to render the object:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, texturedPoints.getEboId());
glBindBuffer(GL_ARRAY_BUFFER, texturedPoints.getVboId());
glBindTexture(GL_TEXTURE_2D, texturedPoints.getTextureId());
specifyVertexAttributes();
int count = texturedPoints.getCount();
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
Somehow that interfered with subsequent VAO rendering calls that looked like this:
glBindVertexArray(texturedPoints.getVaoId());
glBindTexture(GL_TEXTURE_2D, texturedPoints.getTextureId());
glDrawElements(GL_TRIANGLES, texturedPoints.getCount(), GL_UNSIGNED_INT, 0);
The glDrawElements call would seg-fault the second time that the main loop went around and called it. After moving everything over to VAO's the problems have gone away.

OpenGL ES 2.0 VBO issue

I am trying to switch to VBOs, without indices for now. But all I get is just a blank screen. Can someone point out why it is blank? The same code works fine if I comment out the vbo-specific code and replace 0(offset) in glVertexAttribPointer by mFVertexBuffer, i.e without using VBOs.
This is my onDraw method
GLES20.glClearColor(0.50f, 0.50f, 0.50f, 1.0f);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
// Bind default FBO
// GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glUseProgram(mProgram);
checkGlError("glUseProgram");
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, id);
int vertexCount = mCarVerticesData.length / 3;
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
checkGlError("1");
GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT,false, 0, 0);
checkGlError("2");
GLES20.glEnableVertexAttribArray(positionHandle);
checkGlError("3 ");
transferTexturePoints(getTextureHandle());
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
checkGlError("glDrawArrays");
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glDisableVertexAttribArray(positionHandle);
GLES20.glDisable(GLES20.GL_BLEND);
This is my vbo setup:
// Allocate and handle vertex buffer
ByteBuffer vbb2 = ByteBuffer.allocateDirect(mCarVerticesData.length
* FLOAT_SIZE_BYTES);
vbb2.order(ByteOrder.nativeOrder());
mFVertexBuffer = vbb2.asFloatBuffer();
mFVertexBuffer.put(mCarVerticesData);
mFVertexBuffer.position(0);
// Allocate and handle vertex buffer
this.buffers = new int[1];
GLES20.glGenBuffers(1, buffers, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, mFVertexBuffer.capacity()
* FLOAT_SIZE_BYTES, mFVertexBuffer, GLES20.GL_STATIC_DRAW);
Before linking my program:
GLES20.glBindAttribLocation(program, 0, "aPosition");
checkGlError("bindAttribLoc");
And my vertex shader is :
uniform mat4 uMVPMatrix;
attribute vec4 aPosition;
attribute vec2 aTextureCoordinate;
varying vec2 v_TextureCoordinate;
void main()
{
gl_Position = uMVPMatrix * aPosition;
v_TextureCoordinate = aTextureCoordinate;
gl_PointSize= 10.0;
}
You need to also generate an elements array and call something like this in order to render your "object":
// Bind the vertex buffer
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, _bufferIds.get(2));
GLES20.glVertexAttribPointer(4, 4, GLES20.GL_FLOAT, false, 4*4, 0);
// Bind the elements buffer and draw it
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, _bufferIds.get(1));
GLES20.glDrawElements(GLES20.GL_TRIANGLES, _numElements, GLES20.GL_UNSIGNED_SHORT, 0);
Hope that helps.
I solved the problem by rewriting the way I was uploading vertices data. I was modifying it and so, I needed to call glBindBufferData again for it to be uploaded. And I was able to use VBOs without using glDrawElements and indices, and it works well.

Categories

Resources