How do I clip an image in OpenGL ES on Android?

| | August 8, 2015

My game involves “wiping off” an image by touch:

before wipe

After moving a finger over it, it looks like this:

after wipe

At the moment, I’m implementing it with Canvas, like this:

9Paint pTouch;
9int X = 100;
9int Y = 100;
9Bitmap overlay;
9Canvas c2;
9Rect dest;

    pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);         
    pTouch.setXfermode(new PorterDuffXfermode(Mode.SRC_OUT)); 
    pTouch.setColor(Color.TRANSPARENT);
    pTouch.setMaskFilter(new BlurMaskFilter(15, Blur.NORMAL));

    overlay = BitmapFactory.decodeResource(getResources(),R.drawable.wraith_spell).copy(Config.ARGB_8888, true); 

    c2 = new Canvas(overlay);

    dest = new Rect(0, 0, getWidth(), getHeight());
    Paint paint = new Paint();9       
    paint.setFilterBitmap(true);

    ...

    @Override
    protected void onDraw(Canvas canvas) {
        ...

        c2.drawCircle(X, Y, 80, pTouch);
        canvas.drawBitmap(overlay, 0, 0, null);

        ...
    }

    @Override
9public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE: {
                X = (int) event.getX();
                Y = (int) event.getY();9 
                invalidate();
                c2.drawCircle(X, Y, 80, pTouch);9               
                break;
            }   
        }
return true;
...

What I’m essentially doing is drawing transparency onto the canvas, over the red ball image.

Canvas and Bitmap feel old… Surely there is a way to do something similar with OpenGL ES. What is it called? How do I use it?

[EDIT]

I found that if I draw an image and above new image with alpha 0, it goes to be transparent, maybe that direction?

Something like:

gl.glColor4f(0.0f, 0.0f, 0.0f, 0.01f);

2 Responses to “How do I clip an image in OpenGL ES on Android?”

  1. OK, that’s waaaaay too much to ask in such a brief QA format, but here’s a super-condensed answer:

    • Create a GLSurfaceView

    see platform documentation: http://developer.android.com/training/graphics/opengl/environment.html#glsurfaceview

    • Create an orthogonal camera that runs from 0,0 to 1,1
      (see docs again)

    • Load your foreground image (the one you want to erase) into a texture
      (see docs again)

    • Load your background image into a texture

    • Create a single-channel off-screen texture with glBindTexture backed by a ByteBuffer. Set the format to alpha.

    • In the touch event of the GLSurfaceView, transform the touch coordinates from screen space to the dimensions of your alpha texture. Change the color in the byte array in the byte buffer, then refresh the contents of the alpha texture with the byte buffer data. While you can do this by off-screen render-to-texture, if all you are doing is drawing circles I’d just slam the bytes into the array as scan-lines at least until you have more experience with GL. e.g. System.arraycopy

    • Turn OFF z-buffering and ON alpha blending in your render states.

    • Render 2 full-screen quads to your surface view: your background, then your foreground with your foreground texture bound in the diffuse channel (texture unit 1) and the off-screen alpha texture bound in the alpha channel (texture unit 2).
      (see docs for GLSL shader, change from rgb to rgba on fragment shader)


    Alternative: You can use the stencil buffer instead of the alpha channel. It is designed for masking, but either will get the job done.

    If you want anti-aliased edges, stick with alpha. Since you’re new to OpenGL, you are more likely to find simple examples with alpha. Stencil examples are likely to get into shadow mapping and slightly more advanced topics.

    Unfortunately, OpenGL does have a learning curve and what you’re asking for is a lot more than a simple answer. There’s no component that “just does” what you are asking although you may find a wrapper to do so.

    I hope that helps!

  2. There are many ways to go about doing this I suppose in openGL.

    • First, you could make a sprite sheet of every step of the covering of the ball and by using

      glTranslatef();

    on the

    GL10.GL_TEXTURE
    
    • Second, and probably better you could make a second black ball texture that moves over it with the persons figure in your Render loop.

      glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);

    • You could use geometry to do it.

    • You can also do it in canvas like this with the same idea as number 2:

    http://www.javacodegeeks.com/2011/07/android-game-development-moving-images.html

Leave a Reply