Texture doesn't draw
Asked Answered
C

2

0

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]);
    }
}
Calan answered 13/2, 2016 at 15:43 Comment(3)
Can you add the shaders please.Beeson
is mTexture.useTexture() binding the correct GL_TEXTURE_2D handler? I can't see the implementation of Texture class.Willtrude
I have edited the post and added the full Texture class and the shadersCalan
C
0

I found the problem: before the next lines were posted in the MyGLRenderer before constructing the Texture class, but now I have add them between glBindTexture() and texImage2D in Texture 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);

    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
            GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
            GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
Calan answered 21/2, 2016 at 17:38 Comment(0)
S
0

I had similar problems with my textures not being drawn (black screen) when using the same open gl commands.

To render the texture on the screen I also added some additional open gl commands to draw the texture using a vertex shader.

See this project for using a open gl vertex shader Simply calling the renderTexture method with the texture handle and appropriate width and height should fix your problems https://github.com/rsri/Pic2Fro/blob/b4fe69b44343dab2515c3fd6e769f3370bf31312/app/src/main/java/com/pic2fro/pic2fro/util/Util.java

Spearhead answered 17/3, 2018 at 0:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.