Pergunta

Hello StackOverflow community. I have been working on a live wallpaper for android using OpenGL and have been successful thus far in getting OpenGL to render on the live wallpaper and have also been able to load and bind a single texture onto a quad. However when I load more than one texture the last bound texture which is a crate texture is bound onto the first quad which should have a dirt texture, and the second quad tries to bind to a texture that does not exist.

This is my quad class which draw the quads and binds whatever texture the texture object stores:

public class Quad {

    /** The quad's location in space. */
    private float[] vector;

    private Texture texture;

    /** Buffer holding the vertices. */
    private FloatBuffer vertexBuffer;

    /** Array holding the quad's size. */
    private float[] vertices;

    public Quad(GL10 gl, Context context, float[] vector, Texture texture) {
        this.vector = vector;
        this.texture = texture;

        // Check the length of the vector to make sure it is valid.
        if(vector.length != 8) {
            throw new IllegalArgumentException("Please pass a vector with a length of 8. (x, y, z) (w, h) (rotX, rotY, rotZ)");
        }

        vertices = new float[] { 
            0,       0,       0.0f,         // V1 - bottom left
            0,       vector[4], 0.0f,       // V2 - top left
            vector[3], 0,       0.0f,       // V3 - bottom right
            vector[3], vector[4], 0.0f      // V4 - top right
        };

        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4); 
        byteBuffer.order(ByteOrder.nativeOrder());
        vertexBuffer = byteBuffer.asFloatBuffer();
        vertexBuffer.put(vertices);
        vertexBuffer.position(0);
    }

    public void draw(GL10 gl) {
        // Reset the Modelview Matrix
        gl.glLoadIdentity();

        float[] cameraVector = Camera.getLocationVector();

        // Translate the object
        gl.glTranslatef(vector[0] - cameraVector[0], vector[1] - cameraVector[1], vector[2] - cameraVector[2]);

        // Rotate the object
        gl.glRotatef(vector[5] - cameraVector[3], 1f, 0f, 0f);
        gl.glRotatef(vector[6] - cameraVector[4], 0f, 1f, 0f);
        gl.glRotatef(vector[7] - cameraVector[5], 0f, 0f, 1f); 

        // Bind the previously generated texture
        int crap = texture.getTextureID();
        gl.glBindTexture(GL10.GL_TEXTURE_2D, texture.getTextureID());

        // Point to our buffers
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        // Set the face rotation
        gl.glFrontFace(GL10.GL_CW);

        // Point to our vertex buffer
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texture.getBuffer());

        // Draw the vertices as triangle strip
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);

        // Disable the client state before leaving
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    }
}

This is how I initialize my quads:

Texture.loadTextures(gl, context);

quad = new Quad(gl, context, new float[] { 0.0f, 0.0f, -5.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, }, Texture.TEXTURE_DIRT);
quad2 = new Quad(gl, context, new float[] { -1.0f, 0.0f, -10.0f, 1.0f, 1.0f, 0.0f, 45.0f, 0.0f, }, Texture.TEXTURE_CRATE);

This is the texture class that manages all the wallpaper's textures loaded from android bitmaps:

public class Texture {

    /** Buffer holding the texture coordinates. */
    private FloatBuffer textureBuffer;

    private final float textureCoords[] = {         
            0.0f, 1.0f,     // Top left     (V2)
            0.0f, 0.0f,     // Bottom left  (V1)
            1.0f, 1.0f,     // Top right    (V4)
            1.0f, 0.0f      // Bottom right (V3)
    };

    /** The texture this specific instance is pointing to. */
    private int texture;

    /** The id of the texture to be grabbed from android bitmap loader. */
    private int textureID;

    /** Stores all texture data. */
    private static ArrayList<Texture> textureList;

    /** List of all registered textures */
    private static int lastRegisteredTexture;

    /** Array of all loaded texture pointers. */
    private static int[] textures;

    /** Flag to indicate whether the class has been initialized properly. */
    private static boolean isInitialized;

    private static boolean texturesGenned;

    /////////////////////////////////////////////////////////////////////////////////////////

    // All recycled textures loaded on app launch
    public static Texture TEXTURE_DIRT;
    public static Texture TEXTURE_CRATE;

    /**
     * Create a new opengl texture.
     * @param gl
     * @param context
     * @param id
     */
    private Texture(GL10 gl, Context context, int id) {
        if(isInitialized) {
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(textureCoords.length * 4);
            byteBuffer.order(ByteOrder.nativeOrder());
            textureBuffer = byteBuffer.asFloatBuffer();
            textureBuffer.put(textureCoords);
            textureBuffer.position(0);

            textureID = id;

            // Add the texture into the list before loading the texture so the
            // size of the texture pointer array can be determined and not have to be
            // reinitialized
            textureList.add(this);
        } else {
            throw new IllegalStateException("Not yet initialized.");
        }
    }

    /**
     * Load the texture into opengl.
     * @param gl
     * @param context
     * @param id
     */
    private static void loadGLTexture(GL10 gl, Context context) {
        gl.glGenTextures(textures.length, textures, 0);

        for(int i = 0; i < textureList.size(); i++) {
            // Loading texture without scaling
            BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inScaled = false;
            Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), textureList.get(i).getID(), opts);

            // ...And bind it to our array
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textureList.get(i).getTextureID());

            // Create nearest filtered texture
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);

            // Use Android GLUtils to specify a two-dimensional texture image from our bitmap
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

            textureList.get(i).texture = lastRegisteredTexture;
            lastRegisteredTexture++;

            // Clean up native resources
            bitmap.recycle();
        }

        Log.d("Test", "Test2");
    }

    public int getTextureID() {
        return textures[texture];
    }

    public FloatBuffer getBuffer() {
        return textureBuffer;
    }

    private int getID() {
        return textureID;
    }

    public static void loadTextures(GL10 gl, Context context) {
        if(!isInitialized) {
            isInitialized = true;

            textureList = new ArrayList<Texture>();

            // Load all static textures
            TEXTURE_DIRT = new Texture(gl, context, R.raw.dirt);
            TEXTURE_CRATE = new Texture(gl, context, R.drawable.crate);

            // Initialize the texture pointer to match the number of textures
            textures = new int[textureList.size()];

            loadGLTexture(gl, context);
        } else {
            throw new IllegalStateException("Already initialized.");
        }
    }

}

My suspension is that OpenGL is somehow loading one texture over the other due to a flaw in my logic and I believe the problem is happening somewhere in "loadGLTexture". Thanks ahead of time.

Foi útil?

Solução

You called glBindTexture first.

gl.glBindTexture(GL10.GL_TEXTURE_2D, textureList.get(i).getTextureID());

But [texture] is set later.

textureList.get(i).texture = lastRegisteredTexture;

So the first texture(textures[0]) was replaced and the second not binded.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top