You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求在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中添加相机权限:
    <uses-permission android:name="android.permission.CAMERA" />
    
    Android 6.0及以上系统需要动态申请权限,代码中已经处理了这部分逻辑。
  • 自定义OpenGL内容:你可以修改SimpleOverlayRenderer的onDrawFrame方法,替换成任何你需要的OpenGL图形(比如线条、文字、3D模型等)。
  • 性能优化:如果需要更高效的实现,可以直接将Camera预览帧作为纹理传入OpenGL,用GLSurfaceView同时处理预览和叠加,减少View层级开销,但上面的示例更适合入门理解。

内容的提问来源于stack exchange,提问作者Geraldika

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:04:15