Reload opengl textures after onResume() in GLSurfaceView
I have an android application with 2 activities, A and B. The application starts with A, then I tap the screen to switch to B. B appears correctly, then i press the back button on my phone to switch back to A. Now the activity runs correctly, except i can't see my textures. The activity's onResume method calls the GLSurfaceView's onResume method, it calls my renderer's on onSurfaceCreated, then the onSurfaceChanged. After this onDrawFrame called on every frame, but it only clears the screen with the given color. I know that GLSurfaceView's onPause destroys it's content, and onResume should rebuild it, but it wouldn't work for me:(
My code:
The renderer:
public class GlRenderer implements Renderer {
private Context context;
private CScene scene;
long mLastTime;
public GlRenderer(Context context, CScene scene) {
this.context = context;
this.scene=scene;
}
@Override
public void onDrawFrame(GL10 gl) {
long now = System.currentTimeMillis();
if (mLastTime > now) return;
float dt = (float) ((now - mLastTime) / 1000.0);
mLastTime = now;
scene.Update(dt);
scene.Draw(gl);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
if(height == 0) { //Prevent A Divide By Zero By
height = 1; //Making Height Equal One
}
gl.glViewport(0, 0, width, height); //Reset The Current Viewport
gl.glLoadIdentity(); //Reset The Projection Matrix
gl.glMatrixMode(GL10.GL_PROJECTION); //Select The Projection Matrix
GLU.gluOrtho2D(gl, 0, width, height, 0);
gl.glMatrixMode(GL10.GL_MODELVIEW); //Select The Modelview Matrix
gl.glLoadIdentity(); //Reset The Modelview Matrix
scene.LoadTextures(gl);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glEnable(GL10.GL_TEXTURE_2D); //Enable Texture Mapping ( NEW )
gl.glShadeModel(GL10.GL_SMOOTH); //Enable Smooth Shading
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //Black Background
gl.glClearDepthf(1.0f); //Depth Buffer Setup
gl.glEnable(GL10.GL_DEPTH_TEST); //Enables Depth Testing
gl.glDepthFunc(GL10.GL_LEQUAL); //The Type Of Depth Testing To Do
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
}
}
My Sprite class:
public class Sprite {
private FloatBuffer vertexBuffer; // buffer holding the vertices
private FloatBuffer textureBuffer; // buffer holding the texture coordinates
private float texture[] = new float[8];
/** The texture pointer */
private int[] textures = new int[1];
private float width;
private float height;
private float x;
private float y;
public Sprite(float _width, float _height, float xpos, float ypos){
this(_width,_height,xpos,ypos,1.0f,1.0f);
}
public Sprite(float _width, float _height, float xpos, float ypos, float tex_width, float tex_height) {
//.......
}
public void loadGLTexture(GL10 gl, Context c, Bitmap bitmap) {
// generate one texture pointer
gl.glGenTextures(1, textures, 0);
// ...and bind it to our array
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
// create nearest filtered texture
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
// Use Android GLU开发者_StackOverflow社区tils to specify a two-dimensional texture image from our bitmap
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
// Clean up
bitmap.recycle();
}
public void draw(GL10 gl) {
// bind the previously generated texture
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
// Point to our buffers
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Set the face rotation
gl.glFrontFace(GL10.GL_CW);
// Point to our vertex buffer
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
gl.glLoadIdentity();
gl.glTranslatef((float)x, (float)y, 0);
// Draw the vertices as triangle strip
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0,4);
//Disable the client state before leaving
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
}
My Scene class:
public class CScene{
Context context;
public String name;
protected Activity activity;
public CScene(Context _context, Activity activity, String name){
context=_context;
this.name=name;
this.activity=activity;
}
public void Update(float dt){
}
public void Draw(GL10 gl){
}
public boolean TapControl(MotionEvent event)
{
return true;
}
public void LoadTextures(GL10 gl) {
}
}
The structure of my application: Each activity has one GLSurfaceView, and every GLSurfaceView contains a custom Scene. The activity first creates the Scene, which calls the constructor of the sprites. Then the activity creates the GLSurfaceView, which calls the scene's LoadTextures method (from onSurfaceChagned), where its load the bitmap for the sprites on the scene with loadGLTexture. Then the renderer of the GlSurfaceView call the scene's Draw method in onDrawFrame, and the scene's Draw method calls the Sprite's Draw method.
// Sorry for my poor english
I finally figured out, these lines in the renderer's onSurfaceChanged mehotd are out of order:
gl.glLoadIdentity(); //Reset The Projection Matrix
gl.glMatrixMode(GL10.GL_PROJECTION); //Select The Projection Matrix
If i change their order everything works great.
精彩评论