Android:恢复应用程序后 GLSurfaceView 变黑

发布于 2024-12-16 16:27:31 字数 3183 浏览 3 评论 0原文

根据标题,GLSurfaceView 从暂停状态恢复后为空白。渲染器的 onSurfaceCreatedonSurfaceChangedonDrawFrame 在恢复后被调用,但屏幕仍然是空白!

这是相关的代码:

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    gl.glShadeModel(GL10.GL_SMOOTH);
    gl.glClearDepthf(1.0f);
    gl.glEnable(GL10.GL_DEPTH_TEST);
    gl.glDepthFunc(GL10.GL_LEQUAL);

    boxWidth = 0.5f;
    boxHeight = 0.5f;
    boxCenter = new float[] { 0.5f, 0.5f };

    Log.v("resume", "onSurfaceCreated");
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {      
    gl.glViewport(0, 0, width, height);
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    gl.glOrthof(0, 1, 0, 1, -5, 5);
    gl.glMatrixMode(GL10.GL_MODELVIEW);

    viewHeight = height;
    viewWidth = width;

    Log.v("resume", "onSurfaceChanged");
}

@Override
public void onDrawFrame(GL10 gl) {
    gl.glLoadIdentity();

    float halfW = boxWidth/2.0f;
    float halfH = boxHeight/2.0f;

    float left = Math.max(boxCenter[0]-halfW, 0.001f);
    float right = Math.min(boxCenter[0]+halfW, 0.999f);
    float top = Math.min(boxCenter[1]+halfH, 0.999f);
    float bottom = Math.max(boxCenter[1]-halfH, 0.001f);

    boxHeight = Math.max(top - bottom, 0.05f);
    boxWidth = Math.max(right - left, 0.05f);
    boxCenter[0] = left + boxWidth/2.0f;
    boxCenter[1] = bottom + boxHeight/2.0f;

    float vertices[] = {
            left, top, 0.0f,
            left, bottom, 0.0f,
            right, bottom, 0.0f,
            right, top, 0.0f
    };

    ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    vertexBuffer = byteBuf.asFloatBuffer();
    vertexBuffer.put(vertices);

    gl.glTranslatef(0.001f, -0.001f, -3.0f);

    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | 
            GL10.GL_DEPTH_BUFFER_BIT);

    vertexBuffer.position(0);

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, 
            vertexBuffer);

    gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

    gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, 4);
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

    Log.v("resume", "drawing");
}

我读到您需要在 onSurfaceChanged 中重新创建 GL 上下文,但我不确定如何,或者在调用 onSurfaceCreated 时是否已经这样做了。

请帮忙!

编辑: 这是包含 GLSurfaceView 的 Activity 中的 onResume 代码:(此处称为 GLSurface)

public void onResume() {
   super.onResume();
   if (mGLSurface != null) {
   if (mRenderer != null) {
      float[] center = new float[2];
      center[0] = settings.getFloat("renderer_boxCenter0", 0.5f);
      center[1] = settings.getFloat("renderer_boxCenter1", 0.5f);
      mRenderer.setBoxCenter(center);
      mRenderer.setBoxWidth(settings.getFloat("renderer_boxWidth", 0.5f));
      mRenderer.setBoxHeight(settings.getFloat("renderer_boxHeight", 0.5f));
   }
   mGLSurface.onResume();
}

我在 GLSurfaceView 的 onResume 中没有做太多事情,并且我没有找到任何建议我需要的文档做任何特别的事情来恢复我的 EGL 上下文。

编辑2: 不幸的是,我还想指出,在 GLSurfaceView 的构造函数中调用 setPreserveEGLContextOnPause(true) 并没有解决我的问题。

As per the title, the GLSurfaceView is blank after resuming from a paused state. The Renderer's onSurfaceCreated, onSurfaceChanged, and onDrawFrame get called after it resumes, but the screen is still blank!

Here's the relevant code:

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    gl.glShadeModel(GL10.GL_SMOOTH);
    gl.glClearDepthf(1.0f);
    gl.glEnable(GL10.GL_DEPTH_TEST);
    gl.glDepthFunc(GL10.GL_LEQUAL);

    boxWidth = 0.5f;
    boxHeight = 0.5f;
    boxCenter = new float[] { 0.5f, 0.5f };

    Log.v("resume", "onSurfaceCreated");
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {      
    gl.glViewport(0, 0, width, height);
    gl.glMatrixMode(GL10.GL_PROJECTION);
    gl.glLoadIdentity();
    gl.glOrthof(0, 1, 0, 1, -5, 5);
    gl.glMatrixMode(GL10.GL_MODELVIEW);

    viewHeight = height;
    viewWidth = width;

    Log.v("resume", "onSurfaceChanged");
}

@Override
public void onDrawFrame(GL10 gl) {
    gl.glLoadIdentity();

    float halfW = boxWidth/2.0f;
    float halfH = boxHeight/2.0f;

    float left = Math.max(boxCenter[0]-halfW, 0.001f);
    float right = Math.min(boxCenter[0]+halfW, 0.999f);
    float top = Math.min(boxCenter[1]+halfH, 0.999f);
    float bottom = Math.max(boxCenter[1]-halfH, 0.001f);

    boxHeight = Math.max(top - bottom, 0.05f);
    boxWidth = Math.max(right - left, 0.05f);
    boxCenter[0] = left + boxWidth/2.0f;
    boxCenter[1] = bottom + boxHeight/2.0f;

    float vertices[] = {
            left, top, 0.0f,
            left, bottom, 0.0f,
            right, bottom, 0.0f,
            right, top, 0.0f
    };

    ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    vertexBuffer = byteBuf.asFloatBuffer();
    vertexBuffer.put(vertices);

    gl.glTranslatef(0.001f, -0.001f, -3.0f);

    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | 
            GL10.GL_DEPTH_BUFFER_BIT);

    vertexBuffer.position(0);

    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, 
            vertexBuffer);

    gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

    gl.glDrawArrays(GL10.GL_LINE_LOOP, 0, 4);
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

    Log.v("resume", "drawing");
}

I've read that you need to recreate the GL context inside onSurfaceChanged, but I'm not sure how, or if I already did when onSurfaceCreated was called.

Please help!

Edit:
Here's the onResume code from the Activity that contains the GLSurfaceView: (called GLSurface here)

public void onResume() {
   super.onResume();
   if (mGLSurface != null) {
   if (mRenderer != null) {
      float[] center = new float[2];
      center[0] = settings.getFloat("renderer_boxCenter0", 0.5f);
      center[1] = settings.getFloat("renderer_boxCenter1", 0.5f);
      mRenderer.setBoxCenter(center);
      mRenderer.setBoxWidth(settings.getFloat("renderer_boxWidth", 0.5f));
      mRenderer.setBoxHeight(settings.getFloat("renderer_boxHeight", 0.5f));
   }
   mGLSurface.onResume();
}

I didn't do much in the onResume for the GLSurfaceView, and I didn't find any documentation that suggested that I need to do anything in particular to get my EGL context back either.

Edit 2:
I would also like to note that calling setPreserveEGLContextOnPause(true) in the constructor of my GLSurfaceView did not, unfortunately, solve my problem.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

晒暮凉 2024-12-23 16:27:31

setPreserveEGLContextOnPause(true)
仅在 Android 3.X 及更高版本的设备上受支持。 (即使如此,是否支持也取决于设备)

您寻找的解决方案是在 GlSurfaceView 的父活动中,您在活动的 onPause 方法中调用 GlSurfaceView.onPause() ,在 onResume 方法中调用 GlSurfaceView.onResume()活动。

请注意,这会导致所有纹理和缓冲区丢失。此时您需要重新加载它们。

setPreserveEGLContextOnPause(true)
is only supported on devices with Android 3.X and up. (even then it is device specific whether it is supported)

The solution your looking for is in the parent activity of the GlSurfaceView you call GlSurfaceView.onPause() in the onPause method of the activity and GlSurfaceView.onResume() in the onResume method of the activity.

Note this causes all of your textures and buffers to be lost. You need to reload them at this point.

-小熊_ 2024-12-23 16:27:31

这有点遥远,但是您是否尝试控制方向或配置更改(即您是否有 public void onConfigurationChanged(Configuration config) 覆盖您的活动)?

我发现如果我在我的活动中重写了 onConfigurationChanges() 并在清单文件中重写了 android:screenOrientation="landscape" 但没有重写 android:configChanges="orientation “ 我得到了类似于你所描述的内容

This is a bit of a long shot, but do you try to control orientation or config changes (i.e. do you have public void onConfigurationChanged(Configuration config) in overridden your activity)?

I found that if I have onConfigurationChanges() overriden in my activity and android:screenOrientation="landscape" in my manifest file but not android:configChanges="orientation" I get something like what you describe

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文