Android自定义GLSurfaceView
时间:2022-06-10
本文章向大家介绍Android自定义GLSurfaceView,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
当我们需要把同一个场景渲染到不同的Surface
上时,此时系统GLSurfaceView
就不能满足需求了,所以我们需要自己创建EGL环境来实现渲染操作。
注意: OpenGL
整体是一个状态机,通过改变状态就能改变后续的渲染方式,而 EGLContext(EgL上下文)
就保存有所有状态,因此可以通过共享EGLContext
来实现同一场景渲染到不同的Surface
上。
我们通过分析GLSurfaceView
来实现自己的代码
首先需要配置EGL环境(EGLHelper
):Android配置EGL环境
EGL环境配置成功后,定义GLSurfaceView主要为以下步骤:
1、继成SurfaceView,并实现其CallBack回调 2、自定义GLThread线程类,主要用于OpenGL的绘制操作 3、添加设置Surface和EglContext的方法 4、提供和系统GLSurfaceView相同的调用方法
EglSurfaceView.java
package com.zzw.glsurfaceviewdemo;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.lang.ref.WeakReference;
import javax.microedition.khronos.egl.EGLContext;
public class EglSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private Renderer mRenderer;
private EGLThread mEGLThread;
private Surface mSurface;
private EGLContext mEglContext;
public final static int RENDERMODE_WHEN_DIRTY = 0;
public final static int RENDERMODE_CONTINUOUSLY = 1;
private int mRenderMode = RENDERMODE_CONTINUOUSLY;
public EglSurfaceView(Context context) {
this(context, null);
}
public EglSurfaceView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public EglSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
SurfaceHolder holder = getHolder();
holder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (mSurface == null) {
mSurface = holder.getSurface();
}
mEGLThread = new EGLThread(new WeakReference<>(this));
mEGLThread.isCreate = true;
mEGLThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mEGLThread.width = width;
mEGLThread.height = height;
mEGLThread.isChange = true;
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mEGLThread.onDestroy();
mEGLThread = null;
mSurface = null;
mEglContext = null;
}
public void setRenderer(Renderer mRenderer) {
this.mRenderer = mRenderer;
}
public void setRenderMode(int renderMode) {
if (mRenderer == null) {
throw new RuntimeException("must set render before");
}
this.mRenderMode =renderMode;
}
public void requestRender() {
if (mEGLThread != null) {
mEGLThread.requestRender();
}
}
public void setSurfaceAndEglContext(Surface surface, EGLContext eglContext) {
this.mSurface = surface;
this.mEglContext = eglContext;
}
public EGLContext getEglContext() {
if (mEGLThread != null) {
return mEGLThread.getEglContext();
}
return null;
}
private static class EGLThread extends Thread {
EGLThread(WeakReference<EglSurfaceView> eGLSurfaceViewWeakRef) {
this.mEGLSurfaceViewWeakRef = eGLSurfaceViewWeakRef;
}
@Override
public void run() {
super.run();
try {
guardedRun();
} catch (Exception e) {
// fall thru and exit normally
}
}
private void guardedRun() throws InterruptedException {
isExit = false;
isStart = false;
object = new Object();
mEglHelper = new EglHelper();
mEglHelper.initEgl(mEGLSurfaceViewWeakRef.get().mSurface, mEGLSurfaceViewWeakRef.get().mEglContext);
while (true) {
if (isExit) {
//释放资源
release();
break;
}
if (isStart) {
if (mEGLSurfaceViewWeakRef.get().mRenderMode == RENDERMODE_WHEN_DIRTY) {
synchronized (object) {
object.wait();
}
} else if (mEGLSurfaceViewWeakRef.get().mRenderMode == RENDERMODE_CONTINUOUSLY) {
Thread.sleep(1000 / 60);
} else {
throw new IllegalArgumentException("renderMode");
}
}
onCreate();
onChange(width, height);
onDraw();
isStart = true;
}
}
private void onCreate() {
if (!isCreate || mEGLSurfaceViewWeakRef.get().mRenderer == null)
return;
isCreate = false;
mEGLSurfaceViewWeakRef.get().mRenderer.onSurfaceCreated();
}
private void onChange(int width, int height) {
if (!isChange || mEGLSurfaceViewWeakRef.get().mRenderer == null)
return;
isChange = false;
mEGLSurfaceViewWeakRef.get().mRenderer.onSurfaceChanged(width, height);
}
private void onDraw() {
if (mEGLSurfaceViewWeakRef.get().mRenderer == null)
return;
mEGLSurfaceViewWeakRef.get().mRenderer.onDrawFrame();
//第一次的时候手动调用一次 不然不会显示ui
if (!isStart) {
mEGLSurfaceViewWeakRef.get().mRenderer.onDrawFrame();
}
mEglHelper.swapBuffers();
}
void requestRender() {
if (object != null) {
synchronized (object) {
object.notifyAll();
}
}
}
void onDestroy() {
isExit = true;
//释放锁
requestRender();
}
void release() {
if (mEglHelper != null) {
mEglHelper.destoryEgl();
mEglHelper = null;
object = null;
mEGLSurfaceViewWeakRef = null;
}
}
EGLContext getEglContext() {
if (mEglHelper != null) {
return mEglHelper.getEglContext();
}
return null;
}
private WeakReference<EglSurfaceView> mEGLSurfaceViewWeakRef;
private EglHelper mEglHelper;
private int width;
private int height;
private boolean isCreate;
private boolean isChange;
private boolean isStart;
private boolean isExit;
private Object object;
}
interface Renderer {
void onSurfaceCreated();
void onSurfaceChanged(int width, int height);
void onDrawFrame();
}
}
使用和正常的GLSurfaceView一样:
package com.zzw.glsurfaceviewdemo;
import android.opengl.GLES20;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
public class MainActivity extends AppCompatActivity implements EglSurfaceView.Renderer {
private EglSurfaceView eglSurfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
eglSurfaceView = findViewById(R.id.egl_surface_view);
eglSurfaceView = new EglSurfaceView(this);
eglSurfaceView.setRenderer(this);
// eglSurfaceView.setRenderMode(EglSurfaceView.RENDERMODE_CONTINUOUSLY);
eglSurfaceView.setRenderMode(EglSurfaceView.RENDERMODE_WHEN_DIRTY);
eglSurfaceView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
eglSurfaceView.requestRender();
}
});
setContentView(eglSurfaceView);
}
@Override
public void onSurfaceCreated() {
Log.e("zzz", "onSurfaceCreated");
}
@Override
public void onSurfaceChanged(int width, int height) {
Log.e("zzz", "onSurfaceChanged");
GLES20.glViewport(0, 0, width, height);
}
@Override
public void onDrawFrame() {
Log.e("zzz", "onDrawFrame");
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
}
}
- 没想到你是这样的Linux | 终端下有趣的命令合集
- PhEmail:基于Python的开源网络钓鱼测试工具
- 数据库中间件mysql-proxy细节【mysql官方的中间件】
- Office CVE-2017-8570远程代码执行漏洞复现
- Java 并发包中的读写锁及其实现分析
- 深入理解 Spring 事务原理
- Chrome开发者工具的小技巧
- Java Web中JSP中6种动作概况知识点总结——每日一语法学习
- 从Flash到Silverlight进阶教程-用代码来创建动画
- 从Flash到Silverlight进阶教程-Tweener
- silverlight设置浏览器Cookies
- 一个最基本的布局控件-panel
- silverlight项目小结
- oozie 运行demo
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释