【问题标题】:GLSurfaceView.Renderer possible to swap buffers multiple times in onDrawFrame()?GLSurfaceView.Renderer 可以在 onDrawFrame() 中多次交换缓冲区吗?
【发布时间】:2011-06-23 15:47:25
【问题描述】:

在我的 openGL 游戏中,我通常使用 onDrawFrame() 中的 GLSurfaceView.Renderer 类来绘制场景。但是,当我显示加载屏幕时,我想在加载每个数据项后强制屏幕绘制,以便显示加载栏。

是否可以在此绘制调用期间以某种方式强制进行缓冲区交换?我唯一的选择是在多个帧中错开加载,这意味着大量的返工..

我想我想调用的是 eglSwapBuffers() 但我找不到从 GLSurfaceView 或 GLSurfaceView.Renderer 访问 egl 上下文的方法。

感谢您的宝贵时间。

【问题讨论】:

    标签: android opengl-es glsurfaceview egl


    【解决方案1】:

    您也可以将此方法添加到您的 GLSurfaceView.Renderer 类中:

    import javax.microedition.khronos.egl.EGL10;
    import javax.microedition.khronos.egl.EGLDisplay;
    import javax.microedition.khronos.egl.EGLSurface;
    
    public void swapBuffers()
    {
        EGL10 curEgl = (EGL10)EGLContext.getEGL();
    
        EGLDisplay curDisplay = curEgl.eglGetCurrentDisplay();
        if (curDisplay == EGL10.EGL_NO_DISPLAY) { Log.e("myApp","No default display"); return; }    
    
        EGLSurface curSurface = curEgl.eglGetCurrentSurface(EGL10.EGL_DRAW);
        if (curSurface == EGL10.EGL_NO_SURFACE) { Log.e("myApp","No current surface"); return; }
    
        curEgl.eglSwapBuffers(curDisplay, curSurface);
    }
    

    与 OpenUserX03 的答案非常相似,只是在 Java 中。

    【讨论】:

      【解决方案2】:

      不,您不能(或不应该)在渲染器的 onDraw 方法中强制交换缓冲区。

      您应该做的是在单独的线程中加载数据。您的 onDraw 方法仍将被定期调用,这将让您向加载线程询问加载了多少项目以相应地显示进度条/消息。

      【讨论】:

      • 在单独的线程上加载数据需要从加载线程(glGenTextures 等)调用 gl。据我了解,这不是我应该做的事情..?
      • 如果你使onDraw方法同步,你的glGenTexture调用将在渲染过程之外进行,所以这不是问题。
      • 我通过在一个单独的线程上加载我的所有图像数据来实现这一点。为了保证安全,我实际上在加载数据后在渲染器线程上调用所有 gl 函数,例如 glGenTextures。这非常有效,我现在有一个动画加载栏!
      【解决方案3】:

      答案被接受已经有一段时间了,但您可以(并且没有理由不应该)强制交换渲染器的 onDrawFrame() 方法中的缓冲区。

      我在我的 OpenGL 应用程序中遇到了完全相同的问题 - 我需要在加载数据时呈现加载屏幕。这是我在加载期间调用 eglSwapBuffers() 的伪代码示例(我使用 JNI):

      public void onDrawFrame(GL10 gl)
      {
          MyJNILib.render();
      }
      

      MyJNILib 原生伪代码:

      #include <EGL\egl.h>
      
      ...
      
      void render()
      {
          ...
      
          while (loading)
          {
              // Do loading stuff
              ...
              eglSwapBuffers( eglGetCurrentDisplay(), eglGetCurrentSurface( EGL_DRAW ) );
          }
      
          ...
      }
      

      【讨论】:

        【解决方案4】:

        一个强制的解决方案是让你的自定义版本 GLSurfaceView 类基于the source code of Android

        在源码中可以找到一个叫swap的方法:

        /**
         * Display the current render surface.
         * @return the EGL error code from eglSwapBuffers.
         */
        public int swap() {
            if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
                return mEgl.eglGetError();
            }
            return EGL10.EGL_SUCCESS;
        }
        

        这应该是你想要的。然而不幸的是,它是一个名为EglHelperprivate内部类方法。

        /**
         * An EGL helper class.
         */
        
        private static class EglHelper {
        

        因此,在您的自定义 GLSurfaceView 类(从 Google 的源代码复制)中,将此 EglHelper 类设为 public,您可以使用 EglHelper.swap 方法。

        public static class EglHelper {
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多