I have a packed vertex buffer containing postion coordinates aswell as color values for a vertex in the format {X, Y, Z, R, G, B, A}.
I am able to display the rectangle properly with a hardcoded color when I alter the fragment shader by taking out the a_Color attribute and hard coding a vec4 value for gl_FragColor but I am not able to pass the color vec4 attribute into the fragment shader (the rectangle won't display in that scenario).
What is the correct way to use glVertexAttribPointer(...) and glDrawElements(...) to draw from a packed vertex buffer in OpenGL ES 2.0?
See my code below:
public class GameRenderer implements Renderer {
public static final int POS_SZ = 3;
public static final int COL_SZ = 4;
public static final int FLOAT_SZ = 4;
public static final int SHORT_SZ = 2;
private FloatBuffer gridVB;
private ShortBuffer gridIndices;
int programCode, paPositionHandle, paColorHandle, puMVPMatrixHandle;
private final String vertexShaderCode =
"uniform mat4 u_MVPMatrix; \n" +
"attribute vec4 a_Position; \n" +
"void main(){ \n" +
" gl_Position = u_MVPMatrix * a_Position; \n" +
"} \n";
private String fragmentShaderCode =
"precision mediump float; \n" +
"attribute vec4 a_Color; \n" +
"void main(){ \n" +
" gl_FragColor = a_Color; \n" +
"} \n";
public void staticGrid() {
float vertexArray[] = {
-0.75f, 0.75f, 0.0f, // position
0.0f, 0.0f, 1.0f, 1.0f, // colour
0.75f, 0.75f, 0.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.75f, -0.75f, 0.0f,
0.0f, 0.0f, 1.0f, 1.0f,
-0.75f, -0.75f, 0.0f,
0.0f, 0.0f, 1.0f, 1.0f
};
short indicesArray[] = {
0, 1, 2, 0, 2, 3
};
ByteBuffer vbb = ByteBuffer.allocateDirect(vertexArray.length * FLOAT_SZ);
vbb.order(ByteOrder.nativeOrder());
gridVB = vbb.asFloatBuffer();
gridVB.put(vertexArray);
gridVB.position(0);
ByteBuffer ibb = ByteBuffer.allocateDirect(indicesArray.length * SHORT_SZ);
ibb.order(ByteOrder.nativeOrder());
gridIndices = ibb.asShortBuffer();
gridIndices.put(indicesArray);
gridIndices.position(0);
}
public void onSurfaceCreated(GL10 unused, EGLConfig arg1) {
GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
staticGrid();
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
programCode = GLES20.glCreateProgram();
GLES20.glAttachShader(programCode, vertexShader);
GLES20.glAttachShader(programCode, fragmentShader);
GLES20.glLinkProgram(programCode);
paPositionHandle = GLES20.glGetAttribLocation(programCode, "a_Position");
paColorHandle = GLES20.glGetAttribLocation(programCode, "a_Color");
puMVPMatrixHandle = GLES20.glGetUniformLocation(programCode, "u_MVPMatrix");
}
public void onDrawFrame(GL10 unused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glUseProgram(programCode);
int stride = (POS_SZ + COL_SZ) * FLOAT_SZ;
int indices_cnt = 6;
gridVB.position(0);
GLES20.glEnableVertexAttribArray(paPositionHandle);
GLES20.glVertexAttribPointer(paPositionHandle, POS_SZ, GLES20.GL_FLOAT, false, stride, gridVB);
gridVB.position(POS_SZ);
GLES20.glEnableVertexAttribArray(paColorHandle);
GLES20.glVertexAttribPointer(paColorHandle, COL_SZ, GLES20.GL_FLOAT, false, stride, gridVB);
// matrix manipulation ...
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices_cnt, GLES20.GL_UNSIGNED_SHORT, gridIndices);
}
}