6

我正在编写一个特定的 OpenGL 应用程序,我特别想在其中逐步绘制帧。为此,我想禁用我理解的缓冲区的自动清除,这是GLSurfaceView.Renderer#onDrawFrame(). 有人可以帮助我如何做到这一点吗?我需要用 Java 编写应用程序,而不是使用本机 SDK。

我知道我可以通过以下方式做到这一点:-

  1. 在执行时设置属性EGL_SWAP_BEHAVIOR_PRESERVED_BIT位,并且EGL_SURFACE_TYPEeglChooseConfig
  2. 通过调用EGLSurface 对象来设置EGL_SWAP_BEHAVIOR属性EGL_BUFFER_PRESERVEDeglSurfaceAttrib

但是,我从 Khronos 文档中收集到:-

  • EGL_SWAP_BEHAVIOR_PRESERVED_BIT仅当 EGL 版本为 1.4 或更高版本时才受支持。
  • EGL_SWAP_BEHAVIOR仅当 EGL 版本为 1.2 或更高版本时才受支持。

现在,我知道我可以在我的 Android 应用程序中以两种方式访问​​ EGL:-

  1. EGL10使用包中 的 Khronos API 类javax.microedition.khronos.eglEGL11似乎还没有实现)
  2. EGL14在中使用 Android API 类android.opengl package(类似于使用类android.opengl.GLES20

(1) 的问题是版本小于 1.4,所以它不支持我需要的功能。(2) 的问题是,当我在 EGL14 中调用任何方法时,我的应用程序就会崩溃,而且我不确定我应该如何使用它(我找不到一个关于 EGL14 的示例程序/教程应该在应用程序中使用)。特别是,我想学习如何从 EGL14 获取有效的 GL 上下文:在 EGL10 的情况下,我可以通过调用javax.microedition.khronos.egl.EGLContext.getGL(). 但是,我在 class 中没有看到等效的方法android.opengl.EGLContext。事实上,android.opengl除了 EGL14 之外,所有与 EGL 相关的类似乎大部分都是空的。

我最好的选择是遵循与 GLES20 相同的推理方式:仅在方法内部调用GLSurfaceView.Renderer方法:onDrawFrame(), onSurfaceCreated(), onSurfaceChanged(),因为它们提供有效的 GL (GL10) 和 EGL (EGLConfig) 上下文作为参数。所以我在里面放了以下代码onDrawFrame():-

public void onDrawFrame(GL10 gl) {
    ...
    android.opengl.EGLDisplay d = null;
    if ( (d = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)) == EGL14.EGL_NO_DISPLAY) {
        Log.i("Triangle", "EGL14.eglGetDisplay() failed!");
    } else {
        Log.i("Triangle", "EGL14.eglGetDisplay() succeeded!");
    }
    ...
}

我相信我不必在调用上述方法之前实例化 EGL14,因为所有方法都是静态的。但是,调用EGL14.eglGetDisplay()会使应用程序崩溃。

任何帮助将不胜感激,谢谢:)

4

4 回答 4

1

实现的 EGL 版本可能高于您使用的接口。实际版本由 EGL10.eglInitialize() 返回。如果是 [1,4] 或更高,则可以在调用 EGL10.eglChooseConfig() 时传递 [EGL10.EGL_SURFACE_TYPE, EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT]。可以在这里使用 EGL14 的 EGL_SWAP_BEHAVIOR_PRESERVED_BIT 定义——它只是 EGL 规范定义的一个 int。

EGL14.eglGetDisplay() 如何使应用程序崩溃。它是否抛出了未被捕获的异常?可能值得在https://code.google.com/p/android/issues/list提交一个错误(关于你在做什么以及在什么设备上的详细信息)。

于 2014-04-30T22:13:36.727 回答
1

以 Jesse Hall 的解决方案为基础:

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import android.opengl.EGL14;

你可以在你的子类中有一个GLSurfaceView实现 EGLConfigChooser 的内部类:

private static class MyEGLConfigChooser implements GLSurfaceView.EGLConfigChooser {
    public EGLConfig chooseConfig (EGL10 egl, EGLDisplay display) {
        EGLConfig [] configs = new EGLConfig[1];
        int [] num_config = new int[1];
        int [] attrib_list  = new int[] {
            EGL10.EGL_RED_SIZE, 8,
            EGL10.EGL_GREEN_SIZE, 8,
            // ... + anything else you want ...
            EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT | EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT,
            EGL10.EGL_NONE,
        };

        if (egl.eglChooseConfig(display, attrib_list, configs, configs.length, num_config) && num_config[0] > 0) {
            // We just pick the first here, but you could interrogate all
            return configs[0];
        }

        return null;
    }
}

GLSurfaceView子类的构造函数中,添加:

setEGLConfigChooser(new MyEGLConfigChooser());

然后,在您的实现中GLSurfaceView.Renderer,每当表面发生变化时,您都可以在其上设置属性:

public void onSurfaceChanged(GL10 gl, int width, int height) {
    EGL14.eglSurfaceAttrib(EGL14.eglGetCurrentDisplay(),
                           EGL14.getCurrentSurface(EGL14.EGL_DRAW),
                           EGL14.EGL_SWAP_BEHAVIOR,
                           EGL14.EGL_BUFFER_PRESERVED);
}
于 2017-01-17T13:39:55.587 回答
0

您可以扩展 GLSurfaceView 并调用 setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);init,而不是直接使用 EGL。

此设置可防止 GLSurfaceView 框架在您调用 requestRender() 之前被重绘,这对于此示例应用程序更有效。

请参阅 android 文档1,了解如何使用 Java 设置 GLES。

构建 OpenGL ES 环境

于 2013-04-24T16:22:46.043 回答
0

您可以简单地渲染到纹理,然后将该纹理绘制到屏幕上。

于 2015-11-18T10:52:43.907 回答