gpt4 book ai didi

android - 为什么我的 OpenGL fragment 在更新时停止重绘?

转载 作者:行者123 更新时间:2023-12-02 15:39:59 25 4
gpt4 key购买 nike

我制作了一个初学者 OpenGL 应用程序,它显示了从 obj 文件加载的旋转金牛座。它运行得很好,我给我的 friend 们看了。昨天我打开应用程序, View 不再更新。如果我按下主页按钮,然后再次点击应用程序,它将更新 View ,以便我知道主循环处于 Activity 状态。

我回家并将其插入 android studio 以确认渲染线程正常触发,并且 view.requestRender(); 也被调用。

我不知道为什么它停止工作。

这是我的 Android fragment ,用于加载 View 和渲染器

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
/**
* Inflate the layout for this fragment
*/
View root = inflater.inflate(R.layout.glfragment, container, false);

GLSurfaceView glview = (GLSurfaceView)root.findViewById(R.id.surface_view);

Log.i("Method", "OpenGLFragment::onCreateView()");

Context context = this.getActivity().getApplicationContext();

MyRenderer renderer = new MyRenderer(context);
glview.setEGLContextClientVersion(2);
glview.setRenderer(renderer);
glview.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

loadMeshes(context); // loads obj file into variable tourus

renderer.addToScene(tourus);

update = new GraphicsThread(glview);
update.start();

return root;
}

@Override
public void onDestroyView() {
if(update != null) {
update.quit();
}

super.onDestroyView();
}

这是图形线程:

public class GraphicsThread extends Thread {
private GLSurfaceView.Renderer renderer;
private GLSurfaceView view;

private boolean isRunning;

public GraphicsThread(GLSurfaceView view) {
this.view = view;
this.isRunning = true;
}

@Override
public void run() {
while (this.isRunning) {
view.requestRender(); // I verified this loop is executed just fine
}
}

public void quit() {
this.isRunning = false;
}
}

这是MyRenderer代码

public class MyRenderer implements GLSurfaceView.Renderer {
private int program; // default shader program
private List<Mesh> drawables;
private Context context;
private long lastFrameTime;
private RenderInfo info; // MVP and Light matrices
private Bitmap bg;

public MyRenderer(Context context) {
this.drawables = new ArrayList<>();
this.context = context;
this.lastFrameTime = 0;
this.info = null;
}

@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
info = new RenderInfo(context);

GLES20.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
GLES20.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

GLES20.glEnable(GLES20.GL_CULL_FACE);
}

public void onDrawFrame(GL10 unused){
// Redraw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

float elapsed = getElapsedTime();

float rot = 10.0f*elapsed;

for(Mesh m : drawables) {
m.rotateX(rot);
m.draw(info, elapsed);
}
}

public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);

if(width > 0 && height > 0) {
final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
info.resizePerspective(left, right, 1, -1);
}
}

public void addToScene(Mesh mesh) {
drawables.add(mesh);
}

private float getElapsedTime() {
long currentTime = SystemClock.elapsedRealtime();
float elapsed = (float)(currentTime - lastFrameTime) / 1000.0f; //convert ms to seconds
lastFrameTime = currentTime;

return elapsed;
}
}

最后,这是我绘制网格的方法。 RenderInfo 包含相机 MVP 矩阵和灯光及其矩阵等世界信息。与该问题无关。

public void draw(RenderInfo info, float elapsed) {
if(!loaded) {
Log.d("Mesh", "failed to draw");
return;
};

final int program = info.getProgram();

int position = GLES20.glGetAttribLocation(program, "a_Position");
int normal = GLES20.glGetAttribLocation(program, "a_Normal");
int aColor = GLES20.glGetAttribLocation(program, "a_Color");

//int textcoord = GLES20.glGetAttribLocation(program, "a_TexCoordinate");

GLES20.glEnableVertexAttribArray(position);
GLES20.glVertexAttribPointer(position, 3, GLES20.GL_FLOAT, false, 3 * 4, verticesBuffer);

GLES20.glEnableVertexAttribArray(aColor);
GLES20.glVertexAttribPointer(aColor, 4, GLES20.GL_FLOAT, true, 4*4, colorBuffer);

//GLES20.glEnableVertexAttribArray(normal);
//GLES20.glVertexAttribPointer(normal, 3, GLES20.GL_FLOAT, false, 3 * 4, normalBuffer);

float[] modelMatrix = new float[16];

Matrix.setIdentityM(modelMatrix, 0);
Matrix.setRotateM(modelMatrix, 0, rotX , 1.0f, 0.0f, 0.0f);
//Matrix.setRotateM(modelMatrix, 0, rotY , 0.0f, 1.0f, 0.0f);
//Matrix.setRotateM(modelMatrix, 0, rotZ , 0.0f, 0.0f, 1.0f);

float[] mvpMatrix = info.getMVP(modelMatrix);
int MVP = GLES20.glGetUniformLocation(program, "u_MVP");
GLES20.glUniformMatrix4fv(MVP, 1, false, mvpMatrix, 0);

float[] mvMatrix = info.getMV();
int MV = GLES20.glGetUniformLocation(program, "u_MV");
GLES20.glUniformMatrix4fv(MV, 1, false, mvMatrix, 0);

int lightM = GLES20.glGetAttribLocation(program, "u_LightPos");
GLES20.glUniformMatrix4fv(lightM, 1, false, info.getLightMatrix(), 0);

int lightCol = GLES20.glGetAttribLocation(program, "u_LightCol");
GLES20.glUniform4fv(lightCol, 1, info.getLightColor(), 0);
Log.d("boogio", "u_LightCol is: " + Integer.toString(lightCol));


GLES20.glDrawElements(GLES20.GL_TRIANGLES, facesList.size() * 3, GLES20.GL_UNSIGNED_SHORT, facesBuffer);
GLES20.glDisableVertexAttribArray(position);
GLES20.glDisableVertexAttribArray(aColor);
//GLES20.glDisableVertexAttribArray(normal);
}

TL;DR:应用程序渲染良好,并且用于更新良好。突然,应用程序不再在视觉上更新(没有重绘)。仅当应用程序失去并重新获得焦点 1 帧时,它才会重绘。不知道为什么。

最佳答案

您没有发布所有代码,因此无法重现该情况。我所能做的就是向你提出一些建议。

1 - 保留上下文并添加 OpenGL 检查错误

首先,最好告诉 GLView 使用 setPreservceEGLContext 保留设置的 OpenGL 上下文。 。如果这不能解决问题,最好在 OpenGL ES 上下文上启用调试跟踪,使用 setDebugFlas方法。


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
/**
* Inflate the layout for this fragment
*/
View root = inflater.inflate(R.layout.glfragment, container, false);

GLSurfaceView glview = (GLSurfaceView)root.findViewById(R.id.surface_view);

Log.i("Method", "OpenGLFragment::onCreateView()");

Context context = this.getActivity().getApplicationContext();

MyRenderer renderer = new MyRenderer(context);
glview.setEGLContextClientVersion(2);
// added code
glview.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR); // enable log
glview.setPreserveEGLContextOnPause(true); // default is false

glview.setRenderer(renderer);
glview.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

loadMeshes(context); // loads obj file into variable tourus

renderer.addToScene(tourus);

update = new GraphicsThread(glview);
update.start();

return root;
}

这将在 logcat 中向您的应用添加更多调试信息(我希望您已经知道它是什么)。我认为您会发现一些错误(带有 OPEN GL 错误的行..某些内容)。

我怀疑您重新打开该 Activity ,OpenGL上下文尝试使用不再有效的资源(因为OpenGL上下文被破坏)。在上下文重新创建期间需要管理的资源的典型示例是纹理和着色器程序。

2 - 检查图形线程

只需将一些日志调试信息添加到图形线程:

public class GraphicsThread extends Thread {
private GLSurfaceView.Renderer renderer;
private GLSurfaceView view;

private boolean isRunning;

public GraphicsThread(GLSurfaceView view) {
this.view = view;
this.isRunning = true;
Log.i("GraphicsThread", "GraphicsThread::constructor()");
}

@Override
public void run() {
while (this.isRunning) {
Log.i("GraphicsThread", "requestRender");
view.requestRender(); // I verified this loop is executed just fine
}


}

public void quit() {
this.isRunning = false;
Log.i("GraphicsThread", "GraphicsThread::quit()");
}
}

GraphicThread 上的日志信息将帮助您检查线程是否按方面工作。

一些解释

  • glview.setPreserveEGLContextOnPause(true); 在销毁上下文(屏幕旋转或后台 Activity )时保留资源:另一种方法是重新创建并重新加载所有资源。我想这样做是因为,一开始,当 GLView 被销毁时,Android 设备没有内存来保存 GLContext。
  • RENDERMODE_CONTINUOUSLY 告诉 GLView 尽可能绘制场景(据我所知,这是最好的方法)。

希望我的建议可以帮助到您。

关于android - 为什么我的 OpenGL fragment 在更新时停止重绘?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58645491/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com