2

I want to write an app which displays text for exactly 1/60 seconds (framerate = 60 Hz) on a device.

What is the best way to manage this task ?

I first tried it without OpenGL by using an ImageView, but the time management isn't easy that way, because I haven't access on the renderer. Or is there a way how to have access on the renderer ?

My following code doesn't display "T E S T I N G" with OpenGL and I don't know why.

public class MainActivity extends AppCompatActivity implements GLSurfaceView.Renderer {

// The texture pointer
private int[] textures = new int[1];

private Bitmap bitmap;
private Canvas canvas;
private Drawable background;
private Paint textPaint;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);


    GLSurfaceView glSurfaceView = new GLSurfaceView(this);

    // OpenGL Version 2
    glSurfaceView.setEGLContextClientVersion(2);
    // bits for the channels of output image (red, green, blue, alpha, depth, stencil)
    glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
    // Activity acts as the Renderer
    glSurfaceView.setRenderer(this);
    // update on demand
    glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);


    // our bitmap
    bitmap = Bitmap.createBitmap(256, 256, Bitmap.Config.ARGB_4444);
    // get a canvas to paint over the bitmap
    canvas = new Canvas(bitmap);
    bitmap.eraseColor(0);

    // get a background image from resources
    // note the image format must match the bitmap format
    background = this.getApplicationContext().getResources().getDrawable(R.drawable.background);
    background.setBounds(0, 0, 256, 256);
    // draw the background to our bitmap
    background.draw(canvas);

    // draw the text
    textPaint = new Paint();
    textPaint.setTextSize(32);
    textPaint.setAntiAlias(true);
    textPaint.setARGB(0xff, 0x00, 0x00, 0x00);
    // draw the text centered
    canvas.drawText("T E S T I N G", 16, 112, textPaint);
}

// when OpenGL starts up
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    // default state to background color light grey state
    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

// called as often as possible => high frame rate
@Override
public void onDrawFrame(GL10 gl) {

    // clear the color buffer (bitmaps)
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

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

    // 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();
}

// for resizing purposes
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {

    // when size of the GLSurfaceView changes we also want to change the size of the rendering view port to be the same
    GLES20.glViewport(0, 0, width, height);
}}
  • 1
    Possible duplicate of [Draw text in OpenGL ES (Android)](http://stackoverflow.com/questions/1339136/draw-text-in-opengl-es-android) – Andreas Oct 11 '16 at 15:42

1 Answers1

2

You will find a good place to start with a GLSurfaceView here:

https://developer.android.com/training/graphics/opengl/environment.html

However, for text, simply draw text to a texture and render the texture. See this answer for how to do just that: https://stackoverflow.com/a/4336679/2979092

To ensure the use of GLES 2.0 add this to your manifest

<uses-feature android:glEsVersion="0x00020000" android:required="true" />

Extend the GLSurfaceView

class MyGLSurfaceView extends GLSurfaceView {

    private final MyGLRenderer mRenderer;

    public MyGLSurfaceView(Context context){
        super(context);
        setEGLContextClientVersion(2);
        mRenderer = new MyGLRenderer(); // extended GLSurfaceView.Renderer
        setRenderer(mRenderer);
    }
}

Your renderer skeleton

public class MyGLRenderer implements GLSurfaceView.Renderer {

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

    public void onDrawFrame(GL10 unused) {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    }

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

To update on demand set

setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

Render text to a texture using a Bitmap (copied from linked answer)

Bitmap bitmap = Bitmap.createBitmap(256, 256, Bitmap.Config.ARGB_4444);
// get a canvas to paint over the bitmap
Canvas canvas = new Canvas(bitmap);
bitmap.eraseColor(0);

// get a background image from resources
// note the image format must match the bitmap format
Drawable background = context.getResources().getDrawable(R.drawable.background);
background.setBounds(0, 0, 256, 256);
background.draw(canvas); // draw the background to our bitmap

// Draw the text
Paint textPaint = new Paint();
textPaint.setTextSize(32);
textPaint.setAntiAlias(true);
textPaint.setARGB(0xff, 0x00, 0x00, 0x00);
// draw the text centered
canvas.drawText("Hello World", 16,112, textPaint);

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

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

You will also need to bind a shader program before rendering if you're using GLES 2.0.

Community
  • 1
  • 1
WLGfx
  • 1,169
  • 15
  • 31
  • Thank you WLGfx for your really detailed answer. It helped me a lot. I still have a few questions though. –  Oct 13 '16 at 20:34
  • Where does the code from the linked answer go to ? In the constructor MyGLSurfaceView ? In the method onDrawFrame ? Do I have to create a .png background file in R.drawable myself ? –  Oct 13 '16 at 20:37
  • And where is the textures array from ? How can I bind a shader program before rendering ? –  Oct 13 '16 at 20:40
  • You can ready the bitmap anywhere in your code but when it comes to using it you usually upload the texture in the onDraw method. GLES 2.0 shaders are another subject and it's usually a good start to learn 2D shaders first. Also for backgrounds rendering, you can upload any loaded in bitmap to the GPU and render a quad with the texture. Shaders consist of a vertex shader and a fragment shader. – WLGfx Oct 13 '16 at 21:23
  • Thanks. I have edited my question above to show my code. Unfortunately it still doesn't display any text. –  Oct 13 '16 at 22:06
  • You still need to render something which means setting up a quad as a vertex array. Have a look here for an example: https://developer.android.com/training/graphics/opengl/shapes.html – WLGfx Oct 14 '16 at 07:57
  • Plus you can create the texture in the onSurfaceCreated method, otherwise you will end up with an OOM error. And check out using texture coordinates. It may seem like a lot of ground work but the difference in speed is so worth it. – WLGfx Oct 14 '16 at 07:59
  • how can I use it with Grafika recording sample? - https://github.com/google/grafika/blob/master/app/src/main/java/com/android/grafika/CameraCaptureActivity.java – user924 Jul 17 '18 at 13:56
  • what type of image can be set in drawable ? @WLGfx – Yesha Shah Feb 24 '21 at 10:54