public class CameraGLSurfaceFragment extends Fragment {
private final BaseCamera mCamera;
private final byte[] grayData; // 这里应该是你的灰度图像数据
private final int width;
private final int height;
private final int[] textureId_yuv = new int[3];
private ByteBuffer y;
private final ByteBuffer u;
private final ByteBuffer v;
private int sampler_y;
private int sampler_u;
private int sampler_v;
private int program_yuv;
private final FloatBuffer vertexBuffer;
private final FloatBuffer textureBuffer;
private int avPosition_yuv;
private int afPosition_yuv;
private static final String VERTEX_SHADER =
"attribute vec4 av_Position;\n" +
"attribute vec2 af_Position;\n" +
"varying vec2 v_texCord;\n" +
"void main() {\n" +
"gl_Position = av_Position;\n" +
"v_texCord = af_Position;\n" +
"}\n";
private static final String FRAGMENT_SHADER =
"precision mediump float;\n" +
"uniform sampler2D sampler_y;\n" +
"uniform sampler2D sampler_u;\n" +
"uniform sampler2D sampler_v;\n" +
"varying vec2 v_texCord;\n" +
"void main() {\n" +
"vec4 c = vec4((texture2D(sampler_y, v_texCord).r - 16./255.) * 1.164);\n" +
"vec4 U = vec4(texture2D(sampler_u, v_texCord).r - 128./255.);\n" +
"vec4 V = vec4(texture2D(sampler_v, v_texCord).r - 128./255.);\n" +
"c += V * vec4(1.596, -0.813, 0, 0);\n" +
"c += U * vec4(0, -0.392, 2.017, 0);\n" +
"c.a = 1.0;\n" +
"gl_FragColor = c;\n" +
"}\n";
ScheduledFuture<?> scheduledFuture;
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
public CameraGLSurfaceFragment(BaseCamera camera) {
mCamera = camera;
width = camera.getWidth();
height = camera.getHeight();
grayData = new byte[width * height];
byte[] uData = new byte[width * height / 4];
Arrays.fill(uData, (byte) 128);
u = ByteBuffer.wrap(uData);
byte[] vData = new byte[width * height / 4];
Arrays.fill(vData, (byte) 128);
v = ByteBuffer.wrap(vData);
//顶点坐标
float[] vertexData = {
-1f, -1f,
1f, -1f,
-1f, 1f,
1f, 1f
};
vertexBuffer = ByteBuffer.allocateDirect(vertexData.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(vertexData);
vertexBuffer.position(0);
//纹理坐标
float[] textureData = {
0f, 1f,
1f, 1f,
0f, 0f,
1f, 0f
};
textureBuffer = ByteBuffer.allocateDirect(textureData.length * 4)
.order(ByteOrder.nativeOrder())
.asFloatBuffer()
.put(textureData);
textureBuffer.position(0);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCamera.open();
}
@Override
public void onDestroy() {
super.onDestroy();
mCamera.close();
if (scheduledFuture != null) scheduledFuture.cancel(false);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_camera_gl_surface, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
GLSurfaceView glSurfaceView = view.findViewById(R.id.preview_gl);
glSurfaceView.setEGLContextClientVersion(2);
glSurfaceView.setRenderer(new GLSurfaceView.Renderer() {
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//创建一个渲染程序
program_yuv = createProgram();
//得到着色器中的属性
avPosition_yuv = GLES20.glGetAttribLocation(program_yuv, "av_Position");
afPosition_yuv = GLES20.glGetAttribLocation(program_yuv, "af_Position");
sampler_y = GLES20.glGetUniformLocation(program_yuv, "sampler_y");
sampler_u = GLES20.glGetUniformLocation(program_yuv, "sampler_u");
sampler_v = GLES20.glGetUniformLocation(program_yuv, "sampler_v");
//创建纹理
GLES20.glGenTextures(3, textureId_yuv, 0);
for (int i = 0; i < 3; i++) {
//绑定纹理
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[i]);
//设置环绕和过滤方式
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
}
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// 设置视口大小
GLES20.glViewport(0, 0, width, height);
}
@Override
public void onDrawFrame(GL10 gl) {
//
mCamera.getData(grayData);
//Log.d("GLSurface", "onDrawFrame " + mCamera.getFrameIndex());
// 加载灰度图像数据到纹理中
y = ByteBuffer.allocateDirect(grayData.length);
y.put(grayData);
y.position(0);
// 清除屏幕
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glUseProgram(program_yuv);
GLES20.glEnableVertexAttribArray(avPosition_yuv);//使顶点属性数组有效
GLES20.glVertexAttribPointer(avPosition_yuv, 2, GLES20.GL_FLOAT, false, 8, vertexBuffer);//为顶点属性赋值
GLES20.glEnableVertexAttribArray(afPosition_yuv);
GLES20.glVertexAttribPointer(afPosition_yuv, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[0]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, width, height, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, y);//
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[1]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, width / 2, height / 2, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, u);
GLES20.glActiveTexture(GLES20.GL_TEXTURE2);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId_yuv[2]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, width / 2, height / 2, 0, GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, v);
GLES20.glUniform1i(sampler_y, 0);
GLES20.glUniform1i(sampler_u, 1);
GLES20.glUniform1i(sampler_v, 2);
// 绘制几何体(例如一个矩形覆盖整个屏幕)
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
});
glSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY);
scheduledFuture = executor.scheduleAtFixedRate(glSurfaceView::requestRender, 300, 50, TimeUnit.MILLISECONDS);
}
private int createProgram() {
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
return linkProgram(vertexShader, fragmentShader);
}
private static int loadShader(int type, String shaderSource) {
int shader = glCreateShader(type);
glShaderSource(shader, shaderSource);
glCompileShader(shader);
return shader;
}
private static int linkProgram(int verShader, int fragShader) {
int program = glCreateProgram();
glAttachShader(program, verShader);
glAttachShader(program, fragShader);
// 创建OpenGL ES程序可执行文件
glLinkProgram(program);
//告诉OpenGL ES使用此program
glUseProgram(program);
return program;
}
}