Question

public static int loadTexture(int resourceID) {
    int textureHandle[] = new int[1];
    GLES20.glGenTextures(1, textureHandle, 0);

    if (textureHandle[0] != 0) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;

        Bitmap b = BitmapFactory.decodeResource(SlingBall.context.getResources(), resourceID, options);

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[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);

        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, b, 0);

        b.recycle();
    }

    if (textureHandle[0] == 0) {
        throw new RuntimeException("RUFK");
    }

    return textureHandle[0];
}

Here's my code for loading in a texture from resources. This has worked fine for loading a 16x16 PNG file, but when trying to load anything that ISN'T 16x16 (smaller or bigger), it just turns out completely black.

I've tried creating several new PNG's, and yes, every single one that is 16x16 gets loaded properly.

This function gets called in onSurfaceCreated(), btw.

What is going on?

EDIT: Might as well add the shaders, not that I think it should be relevant, seeing as they work fine with 16x16.

VERTEX

uniform mat4 u_mvpMatrix;
attribute vec3 a_vertexPosition;
attribute vec2 a_texturePosition;

varying vec2 v_texturePosition;

void main() {
    v_texturePosition = a_texturePosition;
    gl_Position = u_mvpMatrix * vec4(a_vertexPosition, 1.0);
}

FRAGMENT

precision mediump float;

uniform vec4 u_color;
uniform sampler2D u_texture;

varying vec2 v_texturePosition;

void main() {
    gl_FragColor = texture2D(u_texture, v_texturePosition);
}

(Its a lot more in reality, but I've taken it all out for debugging. Didn't make a difference tho. u_color isnt even used now)

VERTEX DATA

private static final float vertexData[] = {
            -1f, -1f, 0f,       0f, 0f,
            -1f, 1f, 0f,        0f, 1f,
            1f, -1f, 0f,        1f, 0f,
            1f, 1f, 0f,         1f, 1f
    };

3 for position, 2 for texture position.

I'm sorry if I'm not applying sufficient data, but I just have no clue where the problem is, and am just figuring it's probably something I'm doing wrong with the texture loading, since everything else works for 16x16. If there's anywhere you think the problem may lie in the code, please tell me so and I'll edit in the data.

Was it helpful?

Solution

If you are using non-power-of-two (NPOT) texture, thing can get a little complicated. Excerpt from OpenGL ES 2.0 Specification (section 3.8.2 pp.87-88):

Calling a sampler from a fragment shader will return (R; G; B; A) = 
(0; 0; 0; 1) if any of the following conditions are true:

...

- A two-dimensional sampler is called, the corresponding texture image is a
non-power-of-two image (as described in the Mipmapping discussion of
section 3.7.7), and either the texture wrap mode is not CLAMP_TO_EDGE, or
the minification filter is neither NEAREST nor LINEAR.

So, make sure your texture wrap mode is CLAMP_TO_EDGE as well. Support for REPEAT and MIRRORED_REPEAT wrap modes are provided by the OES_texture_npot extension. It may be that your device doesn't support that extension.

Or you could just try to avoid using NPOT textures.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top