0

我在 android 上的 opengl es 2 中绘制纹理时遇到了大约 3 天的问题,最后决定在我所有的研究导致死胡同后我应该提供帮助。问题是纹理被绘制为黑色矩形,而不是实际图像。

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];
    }
}

顶点着色器

attribute vec2 aTexCoords;
attribute vec4 vPosition;

varying vec2 vTexCoords;

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

片段着色器

precision mediump float;

uniform sampler2D uTexture;
varying vec2 vTexCoords;

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

3 回答 3

1

您可以尝试为您的顶点坐标和 texcoords 使用单独的数组。

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

并为纹理坐标创建一个单独的浮动缓冲区。您也可以在 glVertexAtrribPointer 调用中使用 0 的步幅值,这意味着该数组被认为是紧密排列的。

于 2013-05-10T05:57:06.770 回答
0

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.

于 2013-05-10T07:16:59.053 回答
0

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

于 2013-05-10T07:17:49.423 回答