0
votes

I'm trying to render a simple 3D scene. It's basically a surface wrapped in a texture. I've tested it on 4 devices and only one (Galaxy Note 4) renders the texture properly. The other three phones (HTC Evo 3D, LG G2, Sony Xperia Z1) render the texture with all texels in one color, which seems to be an average color of the texture. E.g.: original image and rendered texture.

My first guess was there's something wrong with my fragment shader. But it's very basic and copied from a book "OpenGL ES 2 for Android":

private final String vertexShaderCode =
        "uniform mat4 uMVPMatrix;"+
                "attribute vec4 vPosition;"+
                "attribute vec2 a_TextureCoordinates;"+
                "varying vec2 v_TextureCoordinates;"+
                "void main()"+
                "{"+
                "v_TextureCoordinates = a_TextureCoordinates;"+
                "gl_Position = uMVPMatrix * vPosition;"+
                "}";

private final String fragmentShaderCode =
        "precision mediump float;"+
                "uniform sampler2D u_TextureUnit;"+
                "varying vec2 v_TextureCoordinates;"+
                "void main()"+
                "{"+
                "gl_FragColor = texture2D(u_TextureUnit, v_TextureCoordinates);"+
                "}";

Loading texture:

texCoordHandle = glGetAttribLocation(program, "a_TextureCoordinates");
texUnitHandle = glGetUniformLocation(program, "u_TextureUnit");

texHandle = new int[1];
glGenTextures(1, texHandle, 0);

BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),
                       R.drawable.way_texture_pink_square_512, opt);

glBindTexture(GL_TEXTURE_2D, texHandle[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
glGenerateMipmap(GL_TEXTURE_2D);
bitmap.recycle();
glBindTexture(GL_TEXTURE_2D, 0);

I hold the vertices and texture coords in different float buffers, and draw them in a loop:

glUseProgram(program);
glUniformMatrix4fv(mvpMatrixHandle, 1, false, vpMatrix, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texHandle[0]);
glUniform1i(texUnitHandle, 0);
glEnableVertexAttribArray(positionHandle);
WaySection[] ws = waySects.get(currWaySect);

for( int i = 0 ; i < ws.length ; i++ ) {
    glVertexAttribPointer(
            positionHandle, COORDS_PER_VERTEX,
            GL_FLOAT, false,
            vertexStride, ws[i].vertexBuffer);

    glVertexAttribPointer(texCoordHandle, COORDS_PER_TEX_VER,
            GL_FLOAT, false,
            texStride, ws[i].texBuffer);

    glDrawArrays(GL_TRIANGLE_FAN, 0,
            ws[i].vertices.length / COORDS_PER_VERTEX);
}

glDisableVertexAttribArray(positionHandle);

What I've done:

  • Changed textures, tried different sizes (power of two and not), different alpha.
  • Tried switching on/off different options, like: GL_CULL_FACE, GL_BLEND, GL_TEXTURE_MIN(MAG)_FILTER, GL_TEXTURE_WRAP...
  • Checked for OpenGL errors in every possible place. glGetError() returns no error.
  • Checked the code in debugger. The textures converted into Bitmap looked fine before and after loading them into OpenGL.

Help, please :)

1
What values are you using for the texture coordinates? If they're a long way from zero, then some GPUs might struggle with precision issues. - Columbo
I've checked it for 0, 0.5 and 1. Eventually, instead of 1, there will be a higher integer. - fijau

1 Answers

0
votes

Problem solved. Erratic behavior was caused by the lack of glEnableVertexAttribArray(texCoordHandle); call in onDraw(). Note 4 was ok with that; it required only the positionHandle (vertices) to be enabled. Other phones apparently weren't to happy. Maybe because Note 4 supports GL ES 3.1? Thanks for your time.