我有一个初学者的OpenGL应用,它显示了从obj文件加载的旋转的金牛座。一切正常,我向我的朋友们展示了。昨天我打开了该应用程序,视图不再更新。如果我按下主屏幕按钮,然后再次点击该应用程序,它将更新视图,因此我知道主循环处于活动状态。
我回家并将其插入android studio中,以确认渲染线程能够正常触发,并且还调用了view.requestRender();
。
我不知道为什么它停止工作。
这是我的Android片段,用于加载视图和渲染器
@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帧时才会重新绘制。不知道为什么。
您未发布所有代码,因此无法重现此情况。我能为您提供的所有建议就是一些建议。
首先,最好告诉GLView使用setPreservceEGLContext保存设置的OpenGL上下文。如果仍不能解决问题,最好使用setDebugFlas方法在OpenGL ES上下文中启用DEBUG跟踪。
@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错误的行..某些东西)。
我怀疑您重新打开了该活动,OpenGL上下文尝试使用不再有效的资源(因为OpenGL上下文已被破坏)。在上下文重新创建期间需要管理的典型资源示例是纹理和着色器程序。
只需向图形线程添加一些日志调试信息:
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上的日志信息将帮助您检查线程是否按方面工作。
希望我的建议能对您有所帮助。