I want to draw a image to the screen, but what I get is the black square but without the texture on it. The image path is correct and loaded, because the rect have the correct size. I have a separate class for loading the texture named Texture and a class for drawing the texture called Sprite. Here is the code:
// Class Texture
public void loadFromResources(final Context context, int id) {
GLES20.glGenTextures(1, mTextureID, 0);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Temporary create a bitmap
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), id, options);
// Bind texture to texturename
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID[0]);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
mSize = new Size(bmp.getWidth(), bmp.getHeight());
// We are done using the bitmap so we should recycle it.
bmp.recycle();
}
// Sprite class
public void setTexture(Texture texture) {
mTexture = texture;
Log.d("Sprite", mTexture.getSize().getWidth() + " " + mTexture.getSize().getHeight());
vertices = new float[] {
0.0f, 0.0f,
texture.getSize().getWidth(), 0.0f,
texture.getSize().getWidth(), texture.getSize().getHeight(),
0.0f, texture.getSize().getHeight() };
// The vertex buffer.
ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
// Create our UV coordinates.
uvs = new float[] {
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
1.0f, 0.0f
};
// The texture buffer
bb = ByteBuffer.allocateDirect(uvs.length * 4);
bb.order(ByteOrder.nativeOrder());
uvBuffer = bb.asFloatBuffer();
uvBuffer.put(uvs);
uvBuffer.position(0);
}
public void draw(float[] projectionMatrix) {
float[] scratch = new float[16];
float[] move = new float[16];
Matrix.setIdentityM(move, 0);
Matrix.translateM(move, 0, 10, 10, 0);
Matrix.multiplyMM(scratch, 0, projectionMatrix, 0, move, 0);
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
int mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the triangle coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, 2,
GLES20.GL_FLOAT, false,
2 * 4, vertexBuffer);
// Get handle to texture coordinates location
int mTexCoordLoc = GLES20.glGetAttribLocation(mProgram, "a_texCoord");
MyGLRenderer.checkGlError("glGetAttribLocation");
// Enable generic vertex attribute array
GLES20.glEnableVertexAttribArray(mTexCoordLoc);
MyGLRenderer.checkGlError("glEnableVertexAttribArray");
// Prepare the texturecoordinates
GLES20.glVertexAttribPointer(mTexCoordLoc, 2, GLES20.GL_FLOAT,
false,
0, uvBuffer);
MyGLRenderer.checkGlError("glVertexAttribPointer");
// Get handle to shape's transformation matrix
int mtrxhandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
MyGLRenderer.checkGlError("glGetUniformLocation");
// Apply the projection and view transformation
GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, scratch, 0);
MyGLRenderer.checkGlError("glUniformMatrix4fv");
mTexture.useTexture();
// Get handle to textures locations
int mSamplerLoc = GLES20.glGetUniformLocation(mProgram, "s_texture" );
MyGLRenderer.checkGlError("glGetUniformLocation");
// Set the sampler texture unit to 0, where we have saved the texture.
GLES20.glUniform1i( mSamplerLoc, 0);
MyGLRenderer.checkGlError("glUniform1i");
// Draw the triangle
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);
}
// MyGLRenderer class
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
mTexture = new Texture();
mTexture.loadFromResources(context, R.drawable.hex);
mSprite = new Sprite(context);
mSprite.setTexture(mTexture);
EDIT: Here are the shaders:
// vert
uniform mat4 uMVPMatrix;
attribute vec4 vPosition;
attribute vec2 a_texCoord;
varying vec2 v_texCoord;
void main() {
gl_Position = uMVPMatrix * vPosition;
v_texCoord = a_texCoord;
}
// frag
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
void main() {
gl_FragColor = texture2D( s_texture, v_texCoord );
}
And here is the full class Texture:
public class Texture {
private final int[] mTextureID = new int[1];
private Size mSize = new Size(0,0);
public Texture() {
}
public Size getSize() { return mSize; }
public void loadFromResources(final Context context, int id) {
GLES20.glGenTextures(1, mTextureID, 0);
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false; // No pre-scaling
// Temporary create a bitmap
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), id, options);
// Bind texture to texturename
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID[0]);
// Load the bitmap into the bound texture.
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0);
mSize = new Size(bmp.getWidth(), bmp.getHeight());
// We are done using the bitmap so we should recycle it.
bmp.recycle();
}
public void useTexture() {
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID[0]);
}
}