I have spent a few days trying to get a VBO working on Android using OpenGL ES 2.0, but I just can't seem to get it to work.
Here is the code I am using:
/* The Android shader code */
private static final String[] androidVertexShaderCode = new String[] {
"attribute vec4 vertexPosition;",
"void main() {",
" gl_Position = vertexPosition;",
"}" };
private static final String[] androidFragmentShaderCode = new String[] {
"precision mediump float;",
"uniform vec4 colour;",
"void main() {",
" gl_FragColor = colour;",
"}" };
/* The Android shader */
public Shader androidShader;
/* The constructor with the render mode and the
* number of vertex values given */
public AndroidRenderer(int renderMode, int vertexValuesCount) {
super(renderMode, vertexValuesCount);
//Add this renderer to the list
allRenderers.add(this);
usage = GLES20.GL_STATIC_DRAW;
//Setup the Android shader
this.androidShader = new AndroidShader();
this.androidShader.vertexShader = ShaderUtils.createShader(ArrayUtils.toStringList(androidVertexShaderCode), Shader.VERTEX_SHADER);
this.androidShader.fragmentShader = ShaderUtils.createShader(ArrayUtils.toStringList(androidFragmentShaderCode), Shader.FRAGMENT_SHADER);
this.androidShader.create();
}
/* The method used to setup the buffers,
* assumes the vertices have already been set */
public void setupBuffers() {
//Create the vertices buffer
this.verticesBuffer = BufferUtils.createFlippedBuffer(this.verticesData);
int[] vh = new int[1];
GLES20.glGenBuffers(1, vh, 0);
//Setup the vertices handle
this.verticesHandle = vh[0];
//Bind the vertices buffer and give OpenGL the data
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.verticesHandle);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, Float.BYTES * verticesData.length, this.verticesBuffer, this.usage);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
//Check to see whether the normals have been set
if (this.normalsData != null) {
//Create the normals buffer
this.normalsBuffer = BufferUtils.createFlippedBuffer(this.normalsData);
int[] nh = new int[1];
GLES20.glGenBuffers(1, nh, 0);
//Setup the normals handle
this.normalsHandle = nh[0];
//Bind the normals buffer and give OpenGL the data
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.normalsHandle);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, Float.BYTES * verticesData.length, this.normalsBuffer, this.usage);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
//Check to see whether the colours have been set
if (this.colourData!= null) {
//Create the colours buffer
this.coloursBuffer = BufferUtils.createFlippedBuffer(this.colourData);
int[] ch = new int[1];
GLES20.glGenBuffers(1, ch, 0);
//Setup the colours handle
this.coloursHandle = ch[0];
//Bind the colours buffer and give OpenGL the data
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.coloursHandle);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, Float.BYTES * colourData.length, this.coloursBuffer, this.usage);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
//Check to see whether the texture coordinates have been set
if (this.textureData != null) {
//Create the texture coordinates buffer
this.texturesBuffer = BufferUtils.createFlippedBuffer(this.textureData);
int[] th = new int[1];
GLES20.glGenBuffers(1, th, 0);
//Setup the texture coordinates handle
this.texturesHandle = th[0];
//Bind the texture coordinates buffer and give OpenGL the data
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.texturesHandle);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, Float.BYTES * textureData.length, this.texturesBuffer, this.usage);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
}
}
/* The method used to draw the object */
public void render() {
this.androidShader.use();
short[] indices = new short[this.verticesData.length];
for (short a = 0; a < indices.length; a++)
indices[a] = a;
ShortBuffer indicesBuffer = BufferUtils.createFlippedBuffer(indices);
//Enable the arrays as needed
int vertexPositionAttribute = GLES20.glGetAttribLocation(this.androidShader.program, "vertexPosition");
int normalAttribute = 0;
int colourAttribute = 0;
int texturesAttribute = 0;
GLES20.glEnableVertexAttribArray(vertexPositionAttribute);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.verticesHandle);
GLES20.glVertexAttribPointer(vertexPositionAttribute, this.vertexValuesCount, GLES20.GL_FLOAT, false, 0, 0);
if (this.normalsData != null) {
GLES20.glEnableVertexAttribArray(normalAttribute);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.normalsHandle);
GLES20.glVertexAttribPointer(normalAttribute, 2, GLES20.GL_FLOAT, false, 0, 0);
}
if (this.colourData != null) {
colourAttribute = GLES20.glGetAttribLocation(this.androidShader.program, "colour");
Log.d("HELLO", "" + colourAttribute);
GLES20.glEnableVertexAttribArray(colourAttribute);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.coloursHandle);
GLES20.glVertexAttribPointer(colourAttribute, this.colourValuesCount, GLES20.GL_FLOAT, false, 0, 0);
}
if (this.textureData != null) {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.texturesHandle);
GLES20.glEnableVertexAttribArray(texturesAttribute);
GLES20.glVertexAttribPointer(texturesAttribute, this.textureValuesCount, GLES20.GL_FLOAT, false, 0, 0);
}
//Draw the arrays
GLES20.glDrawElements(this.renderMode, indices.length, GLES20.GL_UNSIGNED_SHORT, indicesBuffer);
//Disable the arrays as needed
if (this.normalsData != null)
GLES20.glDisableVertexAttribArray(normalAttribute);
if (this.textureData != null)
GLES20.glDisableVertexAttribArray(texturesAttribute);
if (this.colourData != null)
GLES20.glDisableVertexAttribArray(colourAttribute);
GLES20.glDisableVertexAttribArray(vertexPositionAttribute);
this.androidShader.stopUsing();
}
I haven't implemented the use of normal or textures at the moment, as I am just trying to draw a triangle where each vertex is a different color. I know that the shader should be working as I got this to work, rendering with only one color using the same shader, and vertices/colour data.
When I looked at LogCat, the message: : GL_INVALID_VALUE was being printed out. I then decided to print out the value of the colourAttribute found using glGetAttribLocation, and it turns out this was -1. Upon further research I found this: https://www.opengl.org/sdk/docs/man/html/glGetAttribLocation.xhtml, which states that the value of -1 is returned "If the named attribute variable is not an active attribute in the specified program object".
After searching Google, I haven't found a solution to the problem of the triangle not rendering, so would appreciate any help.
Thank you.