简体   繁体   中英

drawing textures in opengl es 2.0

I have been having a problem with drawing texture in opengl es 2 on android for about 3 days and finally decided i should help after all my researching lead to dead ends. The problem is the texture is drawn as a black rectangle and not the actually image.

public class Sprite 
{
    private static final Shader spriteShader = ShaderManager.getInstance().getShader(1);
    private static final short[] drawOrder = { 0, 1, 2, 0, 2, 3 };
    private static ShortBuffer drawListBuffer;

    static 
    {
        ByteBuffer bb = ByteBuffer.allocateDirect(drawOrder.length * 2);
        bb.order(ByteOrder.nativeOrder());

        drawListBuffer = bb.asShortBuffer();
        drawListBuffer.put(drawOrder);
        drawListBuffer.position(0);     
    }

    private Context m_context;
    private int m_textureId = 0;
    private FloatBuffer m_vertexBuffer;
    private float[] m_coords = 
        {
            -0.5f,  0.5f, 0.0f, // Position 0
             0.0f,  0.0f, // TexCoord 0
            -0.5f, -0.5f, 0.0f, // Position 1
             0.0f,  1.0f, // TexCoord 1
             0.5f, -0.5f, 0.0f, // Position 2
             1.0f,  1.0f, // TexCoord 2
             0.5f,  0.5f, 0.0f, // Position 3
             1.0f,  0.0f // TexCoord 3
        };


    public Sprite(Context context)
    {
        m_context = context;

        ByteBuffer bb = ByteBuffer.allocateDirect(m_coords.length * 4);
        bb.order(ByteOrder.nativeOrder());

        m_vertexBuffer = bb.asFloatBuffer();
        m_vertexBuffer.put(m_coords);
        m_vertexBuffer.position(0);
    }

    public void initialize(String file)
    {
        InputStream inputStream = null;

        try 
        {
            inputStream = m_context.getAssets().open(file);
            m_textureId = loadTexture(inputStream);
        } 
        catch (IOException e) 
        {}
        finally
        {
            Util.closeStream(inputStream);
        }
    }

    public void draw()
    {
        spriteShader.use();

        int position = spriteShader.getAttribLocation("vPosition");
        int textureCoords = spriteShader.getAttribLocation("aTexCoords");
        int texture = spriteShader.getUniformLocation("uTexture");

        m_vertexBuffer.position(0);
        GLES20.glVertexAttribPointer(position, 3, GLES20.GL_FLOAT, false, 20, m_vertexBuffer);
        Util.checkGlError("vertex pointer poistion");
        m_vertexBuffer.position(3);
        GLES20.glVertexAttribPointer(textureCoords, 2, GLES20.GL_FLOAT, false, 20, m_vertexBuffer);
        Util.checkGlError("vertex pointer textureCoords");
        GLES20.glEnableVertexAttribArray(position);
        GLES20.glEnableVertexAttribArray(textureCoords);

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        Util.checkGlError("active trexture");
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, m_textureId);
        Util.checkGlError("bind texture");

        GLES20.glUniform1i(texture, 0);
        Util.checkGlError("uniform1i");
        GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
        Util.checkGlError("drawelements");

    }

    private int loadTexture(InputStream inputStream)
    {
        int[] texture = new int[1];
        GLES20.glGenTextures(1, texture, 0);

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture[0]); 

        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

        Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();

        return texture[0];
    }
}

vertex shader

attribute vec2 aTexCoords;
attribute vec4 vPosition;

varying vec2 vTexCoords;

void main()
{
vTexCoords = aTexCoords;
gl_Position = vPosition;
}

fragment shader

precision mediump float;

uniform sampler2D uTexture;
varying vec2 vTexCoords;

void main()
{
gl_FragColor = texture2D(uTexture, vTexCoords);
}

You could try using separate arrays for your vertexcoords and texcoords.

private float[] texCoords = {0,0,
                             0,1,
                             1,1,
                             1,0};

And create a separate float buffer for the texture coords. Also you could use a stride value of 0 in the glVertexAtrribPointer call, this would mean the array is considered to be tightly packed.

Your problem is in this line:

GLES20.glVertexAttribPointer(textureCoords, 2, GLES20.GL_FLOAT, false, 20, m_vertexBuffer);

With this you basically set the texture coordinates to be the same as vertex coordinates. Instead of m_vertexBuffer you need to set to m_vertexBuffer+3 as that is the address of the first texture coordinate.

Though I must say that if this was the only mistake you should see at least a part of the texture. For the purpose of testing set the texture parameters not to clamp to edge but repeat. If repeat gives you some strange result, it is most likely there is only a problem with texture coordinates. If not, there might be a problem with the texture itself.

turns out the very exception i was ignoring was being thrown in initialize(String) in turn preventing loadTexture(InputStream) from even being called. All i did was re pasted the image in my assest folder and it stopped throwing. Android or eclipse was just being weird for some reason

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM