寻求在Camera预览视图上层使用OpenGL的简单代码示例
OpenGL叠加Camera预览的Android实现示例
没问题!我给你一个Android平台上把OpenGL叠加在Camera预览上的极简实现示例——核心思路是用TextureView承载Camera预览,再在它上方叠一个透明的GLSurfaceView来渲染OpenGL内容,这种方式直观易懂,适合入门。
1. 布局文件(activity_camera_gl_overlay.xml)
我们用FrameLayout把两个View层叠起来,确保OpenGL层在Camera预览层之上且透明:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- Camera预览底层 --> <TextureView android:id="@+id/camera_preview" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- OpenGL叠加层(设置透明属性) --> <android.opengl.GLSurfaceView android:id="@+id/gl_overlay" android:layout_width="match_parent" android:layout_height="match_parent" android:alpha="1.0" /> </FrameLayout>
2. 核心Activity代码
这里处理Camera的初始化、预览,以及OpenGL渲染器的配置:
import android.Manifest; import android.content.pm.PackageManager; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.opengl.GLSurfaceView; import android.os.Bundle; import android.view.TextureView; import androidx.appcompat.app.AppCompatActivity; import java.io.IOException; public class CameraGLOverlayActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener { private Camera mCamera; private TextureView mCameraPreview; private GLSurfaceView mGLOverlay; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera_gl_overlay); mCameraPreview = findViewById(R.id.camera_preview); mCameraPreview.setSurfaceTextureListener(this); mGLOverlay = findViewById(R.id.gl_overlay); // 配置OpenGL环境:启用透明通道,设置颜色格式 mGLOverlay.setEGLConfigChooser(8, 8, 8, 8, 16, 0); mGLOverlay.getHolder().setFormat(android.graphics.PixelFormat.TRANSLUCENT); // 设置自定义渲染器,持续渲染 mGLOverlay.setRenderer(new SimpleOverlayRenderer()); mGLOverlay.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); } @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { // 动态申请相机权限(Android 6.0+必需) if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.CAMERA}, 100); return; } // 打开后置相机并启动预览 mCamera = Camera.open(); try { mCamera.setPreviewTexture(surface); mCamera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { // 调整相机预览尺寸适配View大小 if (mCamera != null) { Camera.Parameters params = mCamera.getParameters(); params.setPreviewSize(width, height); mCamera.setParameters(params); } } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { // 释放相机资源,避免内存泄漏 if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } return true; } @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { // 预览帧更新回调,这里无需额外处理 } // 自定义OpenGL渲染器:绘制半透明矩形叠加层 private static class SimpleOverlayRenderer implements GLSurfaceView.Renderer { @Override public void onSurfaceCreated(javax.microedition.khronos.opengles.GL10 gl, javax.microedition.khronos.egl.EGLConfig config) { // 启用透明混合模式,让OpenGL内容和Camera预览叠加 gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); // 设置清屏颜色为全透明,保留Camera预览内容 gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); } @Override public void onSurfaceChanged(javax.microedition.khronos.opengles.GL10 gl, int width, int height) { // 设置视口和正交投影,适配屏幕尺寸 gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); gl.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); } @Override public void onDrawFrame(javax.microedition.khronos.opengles.GL10 gl) { // 清屏(仅清除颜色缓冲,保留Camera预览) gl.glClear(GL10.GL_COLOR_BUFFER_BIT); // 绘制一个半透明红色矩形(居中显示) gl.glColor4f(1.0f, 0.0f, 0.0f, 0.5f); // RGBA,最后一位是透明度(0.5=半透明) gl.glBegin(GL10.GL_TRIANGLE_STRIP); gl.glVertex3f(-0.5f, -0.5f, 0.0f); gl.glVertex3f(0.5f, -0.5f, 0.0f); gl.glVertex3f(-0.5f, 0.5f, 0.0f); gl.glVertex3f(0.5f, 0.5f, 0.0f); gl.glEnd(); } } }
3. 关键注意事项
- 权限配置:在
AndroidManifest.xml中添加相机权限:
Android 6.0及以上系统需要动态申请权限,代码中已经处理了这部分逻辑。<uses-permission android:name="android.permission.CAMERA" /> - 自定义OpenGL内容:你可以修改
SimpleOverlayRenderer的onDrawFrame方法,替换成任何你需要的OpenGL图形(比如线条、文字、3D模型等)。 - 性能优化:如果需要更高效的实现,可以直接将Camera预览帧作为纹理传入OpenGL,用
GLSurfaceView同时处理预览和叠加,减少View层级开销,但上面的示例更适合入门理解。
内容的提问来源于stack exchange,提问作者Geraldika
相关产品推荐
相关产品推荐

