0

I have been unable to get the following example code to run properly on my fire 7. When I compile it as is it shows a blank screen like the one below: Texture Failure

I am able to get the example to work on an emulator by inserting the line of code:

public GameView(Context context) 
{
    super(context);

    setEGLContextClientVersion(2);

    //the line below
    setEGLConfigChooser(8, 8, 8, 8, 16, 0);

    gameRenderer = new GameRenderer(context);

    setRenderer(gameRenderer);
}

What would the proper EGLconfig be for my device? or the best way of detecting?

I have tried following approaches:

  1. EGLConfig on HTC Desire, available configuration hangs the device

  2. What is the right way to choose an EGL config in Android?

  3. createWindowSurface failed: EGL_BAD_MATCH?

I still end up empty handed.

For ease of access I've posted some of the code below. The full code is at www.apress.com/downloadable/download/sample/sample_id/1769/

The renderer is as follows:

import android.content.Context;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;


public class GameRenderer implements GLSurfaceView.Renderer {

private static final String TAG = "GameRenderer";
private Context context;
public static float[] mMVPMatrix = new float[16];
public static float[] mProjectionMatrix = new float[16];
public static float[] mViewMatrix = new float[16];
public static float[] mTranslationMatrix = new float[16];

private Starfield starfield;
private Debris debris;
private Hero hero;

float starfieldScroll = 0;
float debrisScroll = 0;

float heroSprite = 0;

float heroMove = 0;

public GameRenderer(Context gameContext) {
    context = gameContext;


}

@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    starfield = new Starfield();
    debris = new Debris();
    hero = new Hero();

    starfield.loadTexture(R.drawable.starfield, context);
    debris.loadTexture(R.drawable.debris, context);
    hero.loadTexture(R.drawable.ships, context);
}

@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
    GLES20.glViewport(0, 0, width, height);

    float ratio = (float) width / height;

    Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);

}

@Override
public void onDrawFrame(GL10 unused) {
    float[] matrix = new float[16];

    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);

    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);

    starfield.draw(mMVPMatrix, starfieldScroll);

    GLES20.glEnable(GLES20.GL_BLEND);
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

    //debris.draw(mMVPMatrix, debrisScroll);
    Matrix.setIdentityM(mTranslationMatrix,0);
    Matrix.translateM(mTranslationMatrix, 0,heroMove,-.5f,0);

    Matrix.multiplyMM(matrix, 0, mMVPMatrix, 0, mTranslationMatrix, 0);

    hero.draw(matrix,0,0);

    GLES20.glDisable(GLES20.GL_BLEND);

    if(starfieldScroll == Float.MAX_VALUE){
        starfieldScroll = 0;
    }
    if(debrisScroll == Float.MAX_VALUE){
        debrisScroll = 0;
    }
    starfieldScroll += .001;
    debrisScroll += .01;


}

public static int loadShader(int type, String shaderCode){

    int shader = GLES20.glCreateShader(type);

    // add the source code to the shader and compile it
    GLES20.glShaderSource(shader, shaderCode);
    GLES20.glCompileShader(shader);

    return shader;
}

public static void checkGlError(String glOperation) {
    int error;
    while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
        Log.e(TAG, glOperation + ": glError " + error);
        throw new RuntimeException(glOperation + ": glError " + error);
    }
}

public void setHeroMove(float movement){
    heroMove = movement;
}
public float getHeroMove(){
    return heroMove;
}
}

The GLsurfaceView is as follows:

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.Display;
import android.view.MotionEvent;



public class GameView extends GLSurfaceView 
{

private final GameRenderer gameRenderer;

public GameView(Context context) {
    super(context);

    setEGLContextClientVersion(2);

    gameRenderer = new GameRenderer(context);

    setRenderer(gameRenderer);

}

@Override
public boolean onTouchEvent(MotionEvent e) {

    float x = e.getX();
    switch (e.getAction()) {
        case MotionEvent.ACTION_DOWN:


            if (x < getWidth() / 2) {
                    gameRenderer.setHeroMove(gameRenderer.getHeroMove() + .1f);
            }

            if (x > getWidth() /2){
                    gameRenderer.setHeroMove(gameRenderer.getHeroMove() - .1f );

            }


    }

    return true;
 }
 }

The Starfield class is as follows:

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.opengles.GL10;


public class Starfield {

static float squareCoords[] = {
        -1f,  1f, 0.0f,   // top left
        -1f, -1f, 0.0f,   // bottom left
        1f, -1f, 0.0f,   // bottom right
        1f,  1f, 0.0f }; // top right

private final short drawOrder[] = { 0, 1, 2, 0, 2, 3 };


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

private final String fragmentShaderCode =
        "precision mediump float;" +
        "uniform vec4 vColor;" +
        "uniform sampler2D TexCoordIn;" + //
        "uniform float scroll;" + //
        "varying vec2 TexCoordOut;" + //
        "void main() {" +
        //" gl_FragColor = vColor;"+
        " gl_FragColor = texture2D(TexCoordIn, vec2(TexCoordOut.x ,TexCoordOut.y + scroll));" + //
        "}";
private float texture[] = {
        -1f, 1f,
        -1f, -1f,
        1f, -1f,
        1f, 1f,
};

private int[] textures = new int[1]; //
private final FloatBuffer vertexBuffer;
private final ShortBuffer drawListBuffer;
private final FloatBuffer textureBuffer; //
private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;

static final int COORDS_PER_TEXTURE = 2; //
static final int COORDS_PER_VERTEX = 3;
private final int vertexStride = COORDS_PER_VERTEX * 4;
public static int textureStride = COORDS_PER_TEXTURE * 4; //

public void loadTexture(int texture, Context context) {
    InputStream imagestream = context.getResources().openRawResource(texture);
    Bitmap bitmap = null;

    android.graphics.Matrix flip = new android.graphics.Matrix();
    flip.postScale(-1f, -1f);


    try {

        bitmap = BitmapFactory.decodeStream(imagestream);

    }catch(Exception e){

    }finally {
        try {
            imagestream.close();
            imagestream = null;
        } catch (IOException e) {
        }
    }

    GLES20.glGenTextures(1, textures, 0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);

    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);

    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
    GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);

    GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

    bitmap.recycle();
}
public Starfield() {
    ByteBuffer bb = ByteBuffer.allocateDirect(squareCoords.length * 4);
    bb.order(ByteOrder.nativeOrder());
    vertexBuffer = bb.asFloatBuffer();
    vertexBuffer.put(squareCoords);
    vertexBuffer.position(0);

    bb = ByteBuffer.allocateDirect(texture.length * 4); //
    bb.order(ByteOrder.nativeOrder()); //
    textureBuffer = bb.asFloatBuffer(); //
    textureBuffer.put(texture); //
    textureBuffer.position(0); //

    ByteBuffer dlb = ByteBuffer.allocateDirect(drawOrder.length * 2);
    dlb.order(ByteOrder.nativeOrder());
    drawListBuffer = dlb.asShortBuffer();
    drawListBuffer.put(drawOrder);
    drawListBuffer.position(0);

    int vertexShader = GameRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
    int fragmentShader = GameRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

    mProgram = GLES20.glCreateProgram();
    GLES20.glAttachShader(mProgram, vertexShader);
    GLES20.glAttachShader(mProgram, fragmentShader);
    GLES20.glLinkProgram(mProgram);
}

public void draw(float[] mvpMatrix, float scroll) {

    GLES20.glUseProgram(mProgram);

    mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");

    GLES20.glEnableVertexAttribArray(mPositionHandle);

    int vsTextureCoord = GLES20.glGetAttribLocation(mProgram, "TexCoordIn"); //


    GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
            GLES20.GL_FLOAT, false,
            vertexStride, vertexBuffer);


    GLES20.glVertexAttribPointer(vsTextureCoord, COORDS_PER_TEXTURE,
            GLES20.GL_FLOAT, false,
            textureStride, textureBuffer);

    GLES20.glEnableVertexAttribArray(vsTextureCoord);

    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
    int fsTexture = GLES20.glGetUniformLocation(mProgram, "TexCoordOut");
    int fsScroll = GLES20.glGetUniformLocation(mProgram, "scroll");
    GLES20.glUniform1i(fsTexture, 0);
    GLES20.glUniform1f(fsScroll, scroll);
    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
    GameRenderer.checkGlError("glGetUniformLocation");
    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
    GameRenderer.checkGlError("glUniformMatrix4fv");
    GLES20.glDrawElements(GLES20.GL_TRIANGLES, drawOrder.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);

    GLES20.glDisableVertexAttribArray(mPositionHandle);
}


}
Community
  • 1
  • 1
  • It's not clear to me if it fails to find a valid configuration, or if your problem is with texture rendering. For example, if you set the clear color to something other than black, do you see the window cleared to the specified color? – Reto Koradi Mar 01 '16 at 22:02
  • Yes, the window is cleared to specific color eg. setting GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); in the renderer's onSurfaceCreated shows gray instead of black. So far it appears this device's approach to classes that fail is to remove it from the renderer. – hobblethepirate Mar 01 '16 at 22:13
  • If the clear color shows, the problem is most likely not with the config selection. You'll need to post the relevant setup and rendering code. – Reto Koradi Mar 02 '16 at 06:26
  • The full code link is: http://www.apress.com/downloadable/download/sample/sample_id/1769/ – hobblethepirate Mar 02 '16 at 19:13
  • It seems more device specific, because I can get the same code to run on samsung galaxy tab 4 with no changes. – hobblethepirate Mar 02 '16 at 19:30
  • What's the size of the texture? In ES 2.0, the `GL_REPEAT` wrap mode is only supported for textures with sizes that are powers of 2. – Reto Koradi Mar 03 '16 at 04:38

0 Answers0