Ok been strangling with this for 2 days. I have a small GLES2/Android App... two objects (both are squares but only one has texture coordinates). I have two Shader Programs, one deal with textures and its coordinates, the other just use a color in fragment shader.
when I only try to render one of these objects (and only compile and link one shader program ) every thing work fine, when I do this for both objects only the 2nd object (the textured square) is rendered. Yes I do switch the Shader Program before I render the corresponding object. one thing worth noting. when I debug; the vertix attribute pointer in one Shader Program = 0 = the Texture attribute pointer in the other program below is some code, Appreciate any help
public abstract class SquareShader extends ShaderProgram {
public static int ShaderProgramObjectId;
public static int VertexPositionHandle;
public static int ColorUniformHandle;
public static int ProjectionMatrixHandle;
public static int ModelMatrixHandle;
public static void Initialize()
{
ShaderProgramObjectId = LinkShaderProgram( R.raw.square_vertex_shader,
R.raw.square_fragment_shader);
ColorUniformHandle = GLES20.glGetUniformLocation(ShaderProgramObjectId, "u_Color");
ProjectionMatrixHandle = GLES20.glGetUniformLocation(ShaderProgramObjectId,
"u_ProjectionMatrix");
ModelMatrixHandle = GLES20.glGetUniformLocation(ShaderProgramObjectId, "u_ModelMatrix");
VertexPositionHandle = GLES20.glGetAttribLocation(ShaderProgramObjectId, "sq_VertexPosition");
GLES20.glEnableVertexAttribArray(VertexPositionHandle);
}
}
public abstract class TextureShader extends ShaderProgram {
public static int ShaderProgramObjectId;
public static int VertexPositionHandle;
public static int TexturePositionHandle;
public static int ProjectionMatrixHandle;
public static int ModelMatrixHandle;
public static int TextureUnitHandle;
public static void Initialize()
{
ShaderProgramObjectId = LinkShaderProgram( R.raw.texture_vertex_shader,
R.raw.texture_fragment_shader);
ProjectionMatrixHandle = GLES20.glGetUniformLocation(ShaderProgramObjectId,
"u_ProjectionMatrix");
ModelMatrixHandle = GLES20.glGetUniformLocation(ShaderProgramObjectId, "u_ModelMatrix");
TextureUnitHandle = GLES20.glGetUniformLocation(ShaderProgramObjectId, "u_TextureUnit");
VertexPositionHandle = GLES20.glGetAttribLocation(ShaderProgramObjectId, "a_VertexPosition");
TexturePositionHandle = GLES20.glGetAttribLocation(ShaderProgramObjectId, "a_TexturePosition");
GLES20.glEnableVertexAttribArray(VertexPositionHandle);
GLES20.glEnableVertexAttribArray(TexturePositionHandle);
}
}
public void onDrawFrame(GL10 gl10) {
//Shade Programs are Initialized in (onSurfaceChanged)
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(SquareShader.ShaderProgramObjectId);
GLES20.glUniformMatrix4fv(SquareShader.ProjectionMatrixHandle, 1, false,
DisplayUtility.ProjectionMatrix, 0);
SquarePlain.Draw();
GLES20.glUseProgram(TextureShader.ShaderProgramObjectId);
GLES20.glUniformMatrix4fv(TextureShader.ProjectionMatrixHandle, 1, false,
DisplayUtility.ProjectionMatrix, 0);
SquareTextured.Draw();
}
//SquarePlain
public static void Draw()
{
Matrix.setIdentityM(DisplayUtility.ModelMatrix, 0);
Matrix.translateM(DisplayUtility.ModelMatrix, 0, 100 , 0, 0);
GLES20.glUniformMatrix4fv(SquareShader.ModelMatrixHandle, 1, false, DisplayUtility.ModelMatrix, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, VBO_VertexBufferID[0]);
GLES20.glVertexAttribPointer(SquareShader.VertexPositionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, 0);
GLES20.glUniform4f(SquareShader.ColorUniformHandle, 0.0f, 0.0f, 1.0f, 1.0f);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT,
indicesBuffer);
}
//SquareTextured
public static void Draw()
{
Matrix.setIdentityM(DisplayUtility.ModelMatrix, 0);
Matrix.translateM(DisplayUtility.ModelMatrix, 0, 600 , 200, 0);
GLES20.glUniformMatrix4fv(TextureShader.ModelMatrixHandle, 1, false, DisplayUtility.ModelMatrix, 0);
//Bind vertices & Texture VBO
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, VBO_VertexBufferID[0]);
GLES20.glVertexAttribPointer(TextureShader.VertexPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, 0);
GLES20.glVertexAttribPointer(TextureShader.TexturePositionHandle, COORDS_PER_TexTure, GLES20.GL_FLOAT, false, vertexStride, COORDS_PER_VERTEX * Float.BYTES);
//Switch Texture Buffer
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureBufferId[0]);
//Bind Indices VBO
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, VBO_IndicesBufferID[0]);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, 0);
}
The issue is that the array of vertex attribute data for the texture coordinates (index
TexturePositionHandle) is enabled when the first object is drawn.Note, OpenGL is a state engine and a state is kept util it is changed again, even beyond frames.
You have to enable the generic vertex attribute array which are required for the shader program and you have to ensure that the other vertex attribute arrays are disabled, when an object is drawn: