Skip to content Skip to sidebar Skip to footer

Android Opengl-es Loading A Non-power Of 2 Texture

I have an app that I've been repeatedly playing with in android, it uses opengl-es. Currently I load textures from a bitmap like so: //Load up and flip the texture - then dispose t

Solution 1:

I think if you tried creating a bitmap with the power of 2 axis sizes and then add your bitmap it should work just fine. maybe something like

Bitmap.createBitmap(notPowerOf2Bitmap, offx, offy, xsize, ysize, bitmapFlag)

other than that, I would say suffer through the photoshop process. How many pictures you got?

Solution 2:

Non-power-of-two (NPOT) bitmaps are supported on some GLES platforms, but you have to check to see if the appropriate extension exists. Note, however, that at least on PowerVR SGX, even though NPOT is supported, there are still some other fairly arbitrary restrictions; for example, your texture width must be a multiple of 2 (if not a power of 2). Also, NPOT rendering tends to be a bit slower on many GPUs.

One thing you can do is just create a wrapper texture which is a power-of-two size and then use glTexSubimage2D to upload the texture to cover only part of that, and then adjust your texture coordinates accordingly. The obvious drawback to this is that you can't use texture wrapping in that circumstance. If you absolutely must support wrapping, you could just scale your texture to the nearest power-of-two size before you call glTexImage2D, although this usually introduces sampling artifacts and makes things blurry, especially if you're trying to do pixel-precise 2D work.

Another thing you might consider, if you don't need to support wrapping, is to make a "texture atlas," in which you condense all of your textures into a few big textures, and have your polygons map to just some portions of the texture atlas(es). You have to be careful when generating MIPmaps, but other than that it usually provides a pretty nice performance benefit, as well as making more efficient use of texture memory since you're not wasting so much on padded or scaled images.

Solution 3:

I have 2 solutions I have employed for this problem. I can be more specific if necessary, but conceptually you can: -

  1. Make the image a power of 2, and the section to crop you fill with 100% alpha channel and load the images with alpha enabled.

  2. Tweak your texture vector / buffer so it doesn't load that section. So instead of using the default

    float texture[] = { 
        0.0f, 1.0f, //1.0f, 1.0f, //0.0f, 0.0f, //1.0f, 0.0f, //
    };
    

as the matrix (obviously this is for loading an image to a 2 triangled square), factor back by ratio the area to crop, eg.

float texture[] = { 
        0.0f, 0.75f, //0.9f, 0.75f, //0.0f, 0.0f, //0.9f, 0.0f, //
     };

of course, be precise with your math or the unwanted bit may bleed in, or you'll cut out some of the real image. Obviously this array is calculated on the fly and not hard-coded as I have demonstrated here.

Solution 4:

Uh why don't you create two bitmaps. Load the first one as you're doing then use createBitmapScaled to turn that bitmap into a power of two. Performance-wise I don't know if it is the fastest method possible but it works.

Solution 5:

YOu can use GLES20.glTexImage2D() to create a empty texture with specified width and height. The example code is

publicstaticintgenTexture(int texWidth, int texHeight) {
    int[] textureIds = newint[1];
    GLES20.glGenTextures(1, textureIds, 0);
    assertNoError();
    int textureId = textureIds[0];
    texWidth = Utils.nextPowerOf2(texWidth);
    texHeight = Utils.nextPowerOf2(texHeight);

    GLES20.glBindTexture(GL11.GL_TEXTURE_2D, textureId);
    GLES20.glTexParameteri(
            GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
    GLES20.glTexParameteri(
            GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
    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);

    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
            texWidth, texHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);

    return textureId;
}

Post a Comment for "Android Opengl-es Loading A Non-power Of 2 Texture"