I'm trying to figure out how to put different textures into different texture units and choose which texture to draw with. I have the following code in my onDrawFrame()
method
int[] texture = new int[7];
texture[0] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture1);
texture[1] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture2);
texture[2] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture3);
texture[3] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture4);
texture[4] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture5);
texture[5] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture6);
texture[6] =TextureHelper.loadTexture(mActivityContext,R.drawable.texture7);
for (int i = 0; i < 7; i ++) {
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[i]);
GLES20.glUniform1i(mTextureUniformHandle, i);
Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, -0.60f + 0.2f * i, 0.0f, 0.0f);
draw();
}
What this is supposed to do is load seven different textures into separate texture units and draw cubes, each cube with a different texture. However, what ends up happening is that all of the cubes end up being drawn with the first texture.
It works correctly if I change GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + i)
to GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
and GLES20.glUniform1i(mTextureUniformHandle, i)
to GLES20.glUniform1i(mTextureUniformHandle, 0)
, but that just uses a single texture unit and replaces the texture in that unit every time, which is not what I want to do.
What am I doing wrong? Thanks in advance.
EDIT:
Vertex shader:
"uniform mat4 u_MVPMatrix;" + // A constant representing the
// combined
// model/view/projection matrix.
"uniform mat4 u_MVMatrix;" + // A constant representing the
// combined model/view matrix.
"attribute vec4 a_Position;" + // Per-vertex position
// information we will pass in.
"attribute vec4 a_Color;" + // Per-vertex color information we
// will pass in.
"attribute vec2 a_TexCoordinate;" + // Per-vertex texture
// coordinate information we
// will pass in.
"varying vec3 v_Position;" + // This will be passed into the
// fragment shader.
"varying vec4 v_Color;" + // This will be passed into the
// fragment shader.
"varying vec2 v_TexCoordinate;" + // This will be passed into
// the fragment shader.
// The entry point for our vertex shader.
"void main()" + "{" +
// Transform the vertex into eye space.
"v_Position = vec3(u_MVMatrix * a_Position);" +
// Pass through the color.
"v_Color = a_Color;" +
// Pass through the texture coordinate.
"v_TexCoordinate = a_TexCoordinate;" +
// gl_Position is a special variable used to store the final
// position.
// Multiply the vertex by the matrix to get the final point in
// normalized screen coordinates.
"gl_Position = u_MVPMatrix * a_Position;" + "} ";
Fragment shader:
"precision mediump float;" + // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
"uniform sampler2D u_Texture;" + // The input texture.
"varying vec3 v_Position;" + // Interpolated position for this fragment.
"varying vec4 v_Color;" + // This is the color from the vertex shader interpolated across the
// triangle per fragment.
"varying vec2 v_TexCoordinate;" + // Interpolated texture coordinate per fragment.
// The entry point for our fragment shader.
"void main()" +
"{" +
// Multiply the color by the diffuse illumination level and texture value to get final output color.
"gl_FragColor = (v_Color * texture2D(u_Texture, v_TexCoordinate));" +
"}";
draw() method:
public void draw() {
// Pass in the position information
mCubePositions.position(0);
GLES20.glVertexAttribPointer(mPositionHandle, mPositionDataSize, GLES20.GL_FLOAT, false, 0, mCubePositions);
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Pass in the color information
mCubeColors.position(0);
GLES20.glVertexAttribPointer(mColorHandle, mColorDataSize, GLES20.GL_FLOAT, false, 0, mCubeColors);
GLES20.glEnableVertexAttribArray(mColorHandle);
// Pass in the texture coordinate information
mCubeTextureCoordinates.position(0);
GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, mCubeTextureCoordinates);
GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);
// This multiplies the view matrix by the model matrix, and stores the
// result in the MVP matrix
// (which currently contains model * view).
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// Pass in the modelview matrix.
GLES20.glUniformMatrix4fv(mMVMatrixHandle, 1, false, mMVPMatrix, 0);
// This multiplies the modelview matrix by the projection matrix, and
// stores the result in the MVP matrix
// (which now contains model * view * projection).
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
// Pass in the combined matrix.
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Draw the cube.
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
}
Assigning mTextureUniformHandle :
mTextureUniformHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_Texture");