views:

747

answers:

4

I have a series of OpenGL-ES calls that properly render a triangle and texture it with alpha blending on the emulator (2.0.1). When I fire up the same code on an actual device (Droid 2.0.1), all I get are white squares.

This suggests to me that the textures aren't loading, but I can't figure out why they aren't loading. All of my textures are 32-bit PNGs with alpha channels, under res/raw so they aren't optimized per the sdk docs.

Here's how I am loading my textures:

private void loadGLTexture(GL10 gl, Context context, int reasource_id, int texture_id)
{
    //Get the texture from the Android resource directory
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), reasource_id, sBitmapOptions);

    //Generate one texture pointer...
    gl.glGenTextures(1, textures, texture_id);
    //...and bind it to our array
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[texture_id]);

    //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_LINEAR);

    //Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);

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

    //Clean up
    bitmap.recycle();
}

Here's how I am rendering the texture:

        //Clear
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    //Enable vertex buffer
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
        //Push transformation matrix
        gl.glPushMatrix();
        //Transformation matrices
        gl.glTranslatef(x, y, 0.0f);
        gl.glScalef(scalefactor, scalefactor, 0.0f);
        gl.glColor4f(1.0f,1.0f,1.0f,1.0f);
        //Bind the texture
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[textureid]);
        //Draw the vertices as triangles
        gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE, indexBuffer);
        //Pop the matrix back to where we left it
        gl.glPopMatrix();
            //Disable the client state before leaving
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

And here are the options I have enabled:

        gl.glShadeModel(GL10.GL_SMOOTH);            //Enable Smooth Shading
        gl.glEnable(GL10.GL_DEPTH_TEST);            //Enables Depth Testing
        gl.glDepthFunc(GL10.GL_LEQUAL);             //The Type Of Depth Testing To Do
        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE_MINUS_SRC_ALPHA);

Edit: I just tried supplying a BitmapOptions to the BitmapFactory.decodeResource() call, but this doesn't seem to fix the issue, despite manually setting the same preferredconfig, density, and targetdensity.

Edit2: As requested, here is a screenshot of the emulator working. The underlaying triangles are shown with a circle texture rendered onto it, the transparency is working because you can see the black background.

alt text

Here is a shot of what the droid does with the exact same code on it: alt text

Edit3: Here are my BitmapOptions, updated the call above with how I am now calling the BitmapFactory, still the same results as below: sBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;

sBitmapOptions.inDensity = 160;
sBitmapOptions.inTargetDensity = 160;
sBitmapOptions.inScreenDensity = 160;
sBitmapOptions.inDither = false;
sBitmapOptions.inSampleSize = 1;
sBitmapOptions.inScaled = false;

Here are my vertices, texture coords, and indices:

    /** The initial vertex definition */
    private static final float vertices[] = { 
                                        -1.0f, -1.0f, 0.0f, 
                                        1.0f, -1.0f, 0.0f,
                                        -1.0f, 1.0f, 0.0f,
                                        1.0f, 1.0f, 0.0f
                                                        };
    /** The initial texture coordinates (u, v) */   
private static final float texture[] = {            
                                    //Mapping coordinates for the vertices
                                    0.0f, 1.0f,
                                    1.0f, 1.0f,
                                    0.0f, 0.0f,
                                    1.0f, 0.0f
                                    };
/** The initial indices definition */   
private static final byte indices[] = {
                                        //Faces definition
                                        0,1,3, 0,3,2
                                        };

Is there anyway to dump the contents of the texture once it's been loaded into OpenGL ES? Maybe I can compare the emulator's loaded texture with the actual device's loaded texture?

I did try with a different texture (the default android icon) and again, it works fine for the emulator but fails to render on the actual phone.

Edit4: Tried switching around when I do texture loading. No luck. Tried using a constant offset of 0 to glGenTextures, no change.

Is there something that I'm using that the emulator supports that the actual phone does not?

Edit5: Per Ryan below, I resized my texture from 200x200 to 256x256, and the issue was NOT resolved.

Edit: As requested, added the calls to glVertexPointer and glTexCoordPointer above. Also, here is the initialization of vertexBuffer, textureBuffer, and indexBuffer:

ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
vertexBuffer = byteBuf.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
byteBuf.order(ByteOrder.nativeOrder());
textureBuffer = byteBuf.asFloatBuffer();
textureBuffer.put(texture);
textureBuffer.position(0);
indexBuffer = ByteBuffer.allocateDirect(indices.length);
indexBuffer.put(indices);
indexBuffer.position(0);
loadGLTextures(gl, this.context);
A: 

I am unsure of what your problem is, I'm pretty new to development in general, but my OpenGL android problems with difference between the emulator and the phone were:

-Emulator can support non 2^x dimensions for bitmaps, phone cannot -Emulator flipped screen in NDK for openGL so I had to use negative coordinates to define the view in the emulator, while my G1 used the coordinates non-negated.

Hopefully this is able to help you in someway.

Ryan
+1 for the non power of two issue. What size in your texture?
CaseyB
It was 200x200, but I just resized it to 256x256, and it still has the same issue. That isn't it.
Dinedal
A: 

I think that it maybe that you are having trouble loading the texture from the APK. Try copying the texture to the SDCard and see if you can load it from there.

CaseyB
I tried this, and this made no difference.
Dinedal
A: 

Hello.

Im also new to Android OpenGL ES dev. I own a Milestone (euro version for Droid).

From what i can see so far, firing several tutorial apps from different books/websites on my milestone, it seems this phone handle OpenGL ES in a different way than all other android phones released so far.

I think its related to the OpenGL extensions supported on the device.

check this link for the list of the supported extensions, im pretty sure a code guru will find why exactly the droid is handling opengl es in such a weird way.

http://www.rbgrn.net/content/345-hands-on-motorola-droid-opengl-es-specs

Hope this helps.. a bit


EDITED :

I tweaked the manifest.xml and noticed when using

<uses-sdk android:minSdkVersion="6"/>

the resources aren't loading at all.

When using

<uses-sdk android:minSdkVersion="3"/>

resources are loading fine.

So i switched back to

<uses-sdk android:minSdkVersion="6"/>

and changed the way the bitmap is loaded.

Try to replace :

  //Get the texture from the Android resource directory 
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), reasource_id, sBitmapOptions); 

with :

InputStream is = context.getResources().openRawResource(your.resource.there);
    Bitmap bitmap = null;
    try {
        bitmap = BitmapFactory.decodeStream(is);

    } finally {
        //Always clear and close
        try {
            is.close();
            is = null;
        } catch (IOException e) {
        }
    }

Textures are loading fine on my milestone with that code, hope this work for yours !

Dullahx
would love to know if you can draw textures with my code.. :)
Dullahx
A: 

are you using the GL11 interface somewhere? GL11 is not supported by all devices. and also remove the glColor line, perhaps your texture is displayed but over-painted by the color? here some code snippet how i display my texture-meshes:

void draw(GL10 gl) {

    // Enabled the vertices buffer for writing and to be used during
    // rendering.
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    // Specifies the location and data format of an array of vertex
    // coordinates to use when rendering.
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

    gl.glEnable(GL10.GL_TEXTURE_2D);

    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
            GL10.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
            GL10.GL_LINEAR);

    gl.glBindTexture(GL10.GL_TEXTURE_2D, myTextureId);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

    gl.glDrawArrays(drawMode, 0, verticesCount);

    gl.glDisable(GL10.GL_TEXTURE_2D);
    // Disable the vertices buffer.
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

}
Sponge