У меня есть приложение для начинающих 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 кадр. Понятия не имею, почему.