title: Magnify on long tap using opengles
body: <p>I want to implement magnify on long tap. On long press a circle will be appeared where tapped area will show as zoom. I need to use opengles.</p>
  <p>I have created a circle using opengles. It also move with finger. Code like as below:</p>
  <p>Calling circle onDrawFrame:</p>
  <pre><code>public void onDrawFrame(GL10 gl) {
      GLES20.glClearColor(0.53333f, 0.53333f, 0.53333f, 1.0f);
      GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | glES20.GL_DEPTH_BUFFER_BIT);
  
      if(mMagnifyCircle != null &amp;&amp; bLongPressed) {
          mMagnifyCircle.draw();
      }
  }
  </code></pre>
  <p>Drawing circle as below:</p>
  <pre><code>public class GLCircle {
  
  private float[] mColor;
  private int mProgram;
  
  private float mCenterX;
  private float mCenterY;
  private float mRadius;
  
  private static final int COORDS_PER_VERTEX = 2;
  private static float VERTEX_COORDINATES[] = {
          -1f,   1f,   // top left
          -1f,  -1f,   // bottom left
           1f,  -1f,   // bottom right
           1f,   1f,   // top right
  };
  
  private FloatBuffer mVertexBuffer;
  private ShortBuffer mDrawListBuffer;
  
  private final short mDrawOrder[] = {0, 1, 2, 0, 2, 3}; // order to draw vertices
  
  public GLCircle(float[] color) {
      mColor = color;
  
      String vertexShaderSource = &quot;&quot; +
              &quot;attribute vec2 aPosition; \n&quot; +
              &quot;void main() \n&quot; +
              &quot;{ \n&quot; +
              &quot;   gl_Position = vec4(aPosition, 0., 1.); \n&quot; +
              &quot;} \n&quot;;
  
      String fragmentShaderSource = &quot;&quot; +
              &quot;precision highp float;\n&quot; +
              &quot;uniform vec2 aCirclePosition;\n&quot; +
              &quot;uniform float aRadius; \n&quot; +
              &quot;uniform vec4 aColor; \n&quot; +
              &quot;const float threshold = 0.005;\n&quot; +
              &quot;void main() \n&quot; +
              &quot;{ \n&quot; +
              &quot;   float d, dist;\n&quot; +
              &quot;   dist = distance(aCirclePosition, gl_FragCoord.xy);\n&quot; +
              &quot;   if(dist == 0.)\n&quot; +
              &quot;       dist = 1.;\n&quot; +
              &quot;   d = aRadius / dist;\n&quot; +
              &quot;   if(d &gt;= 1.)\n&quot; +
              &quot;        gl_FragColor = aColor;\n&quot; +
              &quot;   else if(d &gt;= 1. - threshold) \n&quot; +
              &quot;   {\n&quot; +
              &quot;        float a = (d - (1. - threshold)) / threshold;\n&quot; +
              &quot;        gl_FragColor = vec4(aColor.r, aColor.g, aColor.b, a); \n&quot; +
              &quot;    }\n&quot; +
              &quot;    else\n&quot; +
              &quot;        gl_FragColor = vec4(0., 0., 0., 0.);\n&quot; +
              &quot;} \n&quot;;
  
      int vertexShader = compileVertexShader(vertexShaderSource);
      int fragmentShader = compileFragmentShader(fragmentShaderSource);
      mProgram = linkProgram(vertexShader, fragmentShader);
      if (BuildConfig.DEBUG) {
          validateProgram(mProgram);
      }
  
      ByteBuffer vertexByteBuffer = ByteBuffer.allocateDirect(VERTEX_COORDINATES.length * 4);
      vertexByteBuffer.order(ByteOrder.nativeOrder());
      mVertexBuffer = vertexByteBuffer.asFloatBuffer();
      mVertexBuffer.put(VERTEX_COORDINATES);
      mVertexBuffer.position(0);
  
      ByteBuffer drawByteBuffer = ByteBuffer.allocateDirect(mDrawOrder.length * 2);
      drawByteBuffer.order(ByteOrder.nativeOrder());
      mDrawListBuffer = drawByteBuffer.asShortBuffer();
      mDrawListBuffer.put(mDrawOrder);
      mDrawListBuffer.position(0);
  }
  
  private static int linkProgram(int vertexShaderId, int fragmentShaderId) {
      final int programObjectId = GLES20.glCreateProgram();
      if (programObjectId == 0) {
          return 0;
      }
  
      GLES20.glAttachShader(programObjectId, vertexShaderId);
      GLES20.glAttachShader(programObjectId, fragmentShaderId);
  
      GLES20.glLinkProgram(programObjectId);
  
      final int[] linkStatus = new int[1];
      GLES20.glGetProgramiv(programObjectId, GLES20.GL_LINK_STATUS, linkStatus, 0);
  
      if (linkStatus[0] == 0) {
          // If it failed, delete the program object. glDeleteProgram(programObjectId);
          GLES20.glDeleteProgram(programObjectId);
          return 0;
      }
      return programObjectId;
  }
  
  private static boolean validateProgram(int programObjectId) {
      GLES20.glValidateProgram(programObjectId);
      final int[] validateStatus = new int[1];
      GLES20.glGetProgramiv(programObjectId, GLES20.GL_VALIDATE_STATUS, validateStatus, 0);
      return validateStatus[0] != 0;
  }
  
  private static int compileVertexShader(String shaderCode) {
      return compileShader(GLES20.GL_VERTEX_SHADER, shaderCode);
  }
  
  private static int compileFragmentShader(String shaderCode) {
      return compileShader(GLES20.GL_FRAGMENT_SHADER, shaderCode);
  }
  
  private static int compileShader(int type, String shaderCode) {
      final int shaderObjectId = GLES20.glCreateShader(type);
      if (shaderObjectId == 0) {
          return 0;
      }
      GLES20.glShaderSource(shaderObjectId, shaderCode);
      GLES20.glCompileShader(shaderObjectId);
  
      final int[] compileStatus = new int[1];
      GLES20.glGetShaderiv(shaderObjectId, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
  
      if (compileStatus[0] == 0) {
          GLES20.glDeleteShader(shaderObjectId);
          return 0;
      }
      return shaderObjectId;
  }
  
  public void draw() {
      GLES20.glEnable(GLES20.GL_BLEND);
      GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
      GLES20.glUseProgram(mProgram);
  
      int mPositionHandle = GLES20.glGetAttribLocation(mProgram, &quot;aPosition&quot;);
      GLES20.glEnableVertexAttribArray(mPositionHandle);
      int vertexStride = COORDS_PER_VERTEX * 4;
      GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, mVertexBuffer);
  
      GLES20.glUniform4fv(GLES20.glGetUniformLocation(mProgram, &quot;aColor&quot;), 1, mColor, 0);
      GLES20.glUniform2f(GLES20.glGetUniformLocation(mProgram, &quot;aCirclePosition&quot;), mCenterX, mCenterY);
      GLES20.glUniform1f(GLES20.glGetUniformLocation(mProgram, &quot;aRadius&quot;), mRadius);
      GLES20.glDrawElements(GLES20.GL_TRIANGLES, mDrawOrder.length, GLES20.GL_UNSIGNED_SHORT, mDrawListBuffer);
      GLES20.glDisableVertexAttribArray(mPositionHandle);
  }
  
  public float getCenterX() {
      return mCenterX;
  }
  
  public void setCenterX(float centerX) {
      mCenterX = centerX;
  }
  
  public float getCenterY() {
      return mCenterY;
  }
  
  public void setCenterY(float centerY) {
      mCenterY = centerY;
  }
  
  public float getRadius() {
      return mRadius;
  }
  
  public void setRadius(float radius) {
      this.mRadius = radius;
  }
  </code></pre>
  <p>}</p>
  <p>Moving on finger touch :</p>
  <pre><code>    @Override
  public boolean onTouch(View v, MotionEvent event) {
      boolean bResult = false;
      float x = 0,y = 0;
  
      if (event.getAction() == MotionEvent.ACTION_DOWN){
          x = event.getRawX();
          y = event.getRawY();
      } else if (event.getAction() == MotionEvent.ACTION_UP) {
          bLongPressed = false;
          requestRenderer();
          GLES20.glClearColor(0.53333f, 0.53333f, 0.53333f, 1.0f);
          GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
  
          v.performClick();
      } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
          x = event.getRawX();
          y = event.getRawY();
      }
  
      requestRenderer();
      mMagnifyCircle.setCenterX(x);
      mMagnifyCircle.setCenterY(y);
      mMagnifyCircle.setRadius(200);
      return bResult;
  }
  </code></pre>
  <p><strong>My question is:</strong></p>
  <ol>
  <li>If I move finger on x axis, circle goes with finger. But if I move
  finger on Y axis, circle goes to opposite direction. How can solve
  this?</li>
  <li>Circle is transparent already. But I want to zoom only circle
  area. How can I do this?</li>
  </ol>
  <p>Expected output will look like as below:</p>
  <p><a href="https://i.stack.imgur.com/RJyOS.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/RJyOS.png" alt="Expected feature will be look like below:" /></a></p>