效果如下
主要代码
GLSurfaceView
mGLView = (GLSurfaceView) findViewById(R.id.mGLView);
mGLView.setEGLContextClientVersion(2);
mGLView.setRenderer(mRender);
mGLView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
mGLView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
mRender.setXY(x, y);
mGLView.requestRender();
break;
case MotionEvent.ACTION_MOVE:
if (dis(event.getX() - x, event.getY() - y) > MIN_DISTANCE) {
mRender.setXY(x, y);
mGLView.requestRender();
}
x = event.getX();
y = event.getY();
break;
case MotionEvent.ACTION_UP:
x = event.getX();
y = event.getY();
break;
}
return true;
}
});
Render 纹理
/*
*
* FBORender.java
*
* Created by tyearlin on 2019/03/01
*/
package qt.lin.opengl.zoom;
import java.nio.ByteBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.util.Log;
import qt.lin.opengl.filter.AFilter;
import qt.lin.opengl.filter.NoFilter;
import static android.opengl.GLES20.*;
public class Render implements GLSurfaceView.Renderer {
private String TAG = "Render";
public static final int RADIS = 80; //r
private float x, y;
private int width, hegith;
private Callback mCallback;
private Bitmap mBitmap;
private AFilter mFilter;
private int[] mTextureIds = new int[1];
private ByteBuffer mScaleBuffer;
public Render(Resources res) {
mFilter = new NoFilter(res);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
mFilter.create();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
Log.d(TAG, "onSurfaceChanged:" + width + "h:" + height);
GLES20.glViewport(0, 0, width, height);
this.width = width;
this.hegith = height;
}
@Override
public void onDrawFrame(GL10 gl) {
if (mBitmap != null) {
setUp();
//渲染到纹理
mFilter.setTextureId(mTextureIds[0]);
mFilter.draw();
//获取采样数据
//y反向取
int centX = (int) (x - RADIS / 2);
int centY = (int) ((hegith - y) - RADIS / 2);
Log.d(TAG, "x:" + centX + "y:" + centY);
glReadPixels(centX, centY, RADIS, RADIS, GL_RGBA,
GL_UNSIGNED_BYTE, mScaleBuffer);
if (mCallback != null) {
mCallback.onCall(mScaleBuffer);
}
release();
}
}
public void setCallback(Callback callback) {
this.mCallback = callback;
}
public void setBitmap(Bitmap bitmap) {
this.mBitmap = bitmap;
}
public void setUp() {
//create texture
glGenTextures(1, mTextureIds, 0);
glBindTexture(GL_TEXTURE_2D, mTextureIds[0]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mBitmap, 0);
//buffer
mScaleBuffer = ByteBuffer.allocate(RADIS * RADIS * 4);
}
public void release() {
mScaleBuffer.clear();
mScaleBuffer = null;
glBindTexture(GL_TEXTURE, 0);
glDeleteTextures(1, mTextureIds, 0);
}
public void setXY(float x, float y) {
this.x = x;
this.y = y;
}
interface Callback {
void onCall(ByteBuffer data);
}
}
//AFliter 顶点 纹理坐标
//顶点坐标
private float pos[] = {
-1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, 1.0f,
1.0f, -1.0f,
};
//纹理坐标
private float[] coord={
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
};
加载shader
protected final void createProgram(String vertex,String fragment){
mProgram= uCreateGlProgram(vertex,fragment);
mHPosition= GLES20.glGetAttribLocation(mProgram, "vPosition");
mHCoord=GLES20.glGetAttribLocation(mProgram,"vCoord");
mHMatrix=GLES20.glGetUniformLocation(mProgram,"vMatrix");
mHTexture=GLES20.glGetUniformLocation(mProgram,"vTexture");
}
绘制
//Afilter draw
public void draw(){
//清屏
onClear();
//加载shader
onUseProgram();
//绑定纹理
onBindTexture();
//绘制纹理
onDraw();
}
//激活纹理单元
GLES20.glActiveTexture(GLES20.GL_TEXTURE0+textureType);
//绑定纹理
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,getTextureId());
GLES20.glUniform1i(mHTexture,textureType);
protected void onDraw(){
GLES20.glEnableVertexAttribArray(mHPosition);
GLES20.glVertexAttribPointer(mHPosition,2, GLES20.GL_FLOAT, false, 0,mVerBuffer);
GLES20.glEnableVertexAttribArray(mHCoord);
GLES20.glVertexAttribPointer(mHCoord, 2, GLES20.GL_FLOAT, false, 0, mTexBuffer);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP,0,4);
GLES20.glDisableVertexAttribArray(mHPosition);
GLES20.glDisableVertexAttribArray(mHCoord);
}
glReadPixels(centX, centY, RADIS, RADIS, GL_RGBA, GL_UNSIGNED_BYTE, mScaleBuffer);
获取的图像是上下翻转和左右镜像的 该方法中 起点是 屏幕左下角(纹理坐标系)
Matrix matrix = new Matrix();
Bitmap bitmap = Bitmap.createBitmap(RADIS, RADIS, Bitmap.Config.ARGB_8888);
matrix.postRotate(180);
matrix.postScale(-1, 1);
bitmap.copyPixelsFromBuffer(data);
最好的方法是处理 data