2015-08-20 4 views
1

J'ai un fond d'écran animé avec un effet de parallaxe. J'ai basé le code de the openGL Tutorials.Android OpenGL Live Wallpaper créer deux moteurs de rendu

Il a fonctionné pour la plupart sauf lorsque le fond d'écran est prévisualisé alors qu'il est déjà défini comme fond d'écran. Après cela, ma méthode onOffsetsChanged() continue d'être appelée, mais la valeur de mon décalage de caméra dans ma classe de rendu ne change pas. Cela signifie que mon fond d'écran de parallaxe devient statique. L'effet de parallaxe fonctionne à nouveau dès que je définis un fond d'écran différent, puis je reviens à ce fond d'écran.

Mise à jour: Ainsi, il semble que le moteur de rendu soit dessiné et que le moteur de rendu qui reçoit les appels pour onOffsetsChanged soit deux moteurs de rendu distincts. Est-ce que quelqu'un sait pourquoi le nouveau est contrôlé par le WallpaperService pendant que l'ancien est dessiné ou comment résoudre ce problème?

GLWallpaperService:

public abstract class GLWallpaperService extends WallpaperService{ 
public class GLEngine extends Engine{ 
    class WallpaperGLSurfaceView extends GLSurfaceView { 
     private static final String TAG = "WallpaperGLSurfaceView"; 

     WallpaperGLSurfaceView(Context context) 
     { 
      super(context); 
     } 

     public SurfaceHolder getHolder() 
     { 
      return getSurfaceHolder(); 
     } 

     public void onDestroy() 
     { 
      super.onDetachedFromWindow(); 
     } 
    } 

    private WallpaperGLSurfaceView glSurfaceView; 
    private boolean rendererHasBeenSet; 

    @Override 
    public void onCreate(SurfaceHolder surfaceHolder) 
    { 
     super.onCreate(surfaceHolder); 

     glSurfaceView = new WallpaperGLSurfaceView(GLWallpaperService.this); 

     Log.d("onCreate", "was called"); 
    } 

    @Override 
    public void onVisibilityChanged(boolean visible) 
    { 
     super.onVisibilityChanged(visible); 
     if(rendererHasBeenSet) 
     { 
      if (visible) 
      { 
       glSurfaceView.onResume(); 
       //glSurfaceView.requestRender(); 
       Log.d("onResume", "was called"); 
      } else 
      { 
       glSurfaceView.onPause(); 
       Log.d("onPause", "was called"); 
      } 
     } 
    } 

    @Override 
    public void onDestroy() 
    { 
     super.onDestroy(); 
     glSurfaceView.onDestroy(); 
     Log.d("onDestroy", "was called"); 
    } 

    protected void setRenderer(GLSurfaceView.Renderer renderer) 
    { 
     glSurfaceView.setRenderer(renderer); 
     rendererHasBeenSet = true; 
     Log.d("setRenderer", "was called"); 
    } 

    protected void setPreserveEGLContextOnPause(boolean preserve) 
    { 
     if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 
     { 
      glSurfaceView.setPreserveEGLContextOnPause(preserve); 
     } 
    } 

    protected void setEGLContextClientVersion(int version) 
    { 
     glSurfaceView.setEGLContextClientVersion(version); 
    } 
    } 
    } 

OpenGLES2WallpaperService:

public class OpenGLES2WallpaperService extends GLWallpaperService 
{ 

    //set up our main_preferences 
    SharedPreferences preferences; 
    GLRenderer renderer; 
    private SharedPreferences.OnSharedPreferenceChangeListener prefListener; 

    @Override 
    public Engine onCreateEngine() 
    { 
     Log.d("GLES2 onCreateEngine", "engine was created"); 
     return new OpenGLES2Engine(); 
    } 

    class OpenGLES2Engine extends GLWallpaperService.GLEngine 
    { 
     @Override 
     public void onCreate(SurfaceHolder surfaceHolder) 
     { 
      super.onCreate(surfaceHolder); 
      Log.d("GLES2 onCreate", "surface was created"); 

      preferences = PreferenceManager.getDefaultSharedPreferences(OpenGLES2WallpaperService.this); 

      final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 
      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo(); 
      final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000; 

      if (supportsEs2) 
      { 
       setEGLContextClientVersion(2); 

       setPreserveEGLContextOnPause(true); 

       renderer = new GLRenderer(OpenGLES2WallpaperService.this); 

       setRenderer(renderer); 

       //set up preference listener 

       final SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(OpenGLES2WallpaperService.this); 
       prefListener = new SharedPreferences.OnSharedPreferenceChangeListener() 
       { 
        @Override 
        public void onSharedPreferenceChanged(SharedPreferences mprefs, String key) { 
         if(mPrefs.getBoolean("activate_sunset", true)) 
         { 
          renderer.changeColor(1); 
         } 
         else 
         { 
          renderer.changeColor(0); 
         } 

        } 
       }; 
       mPrefs.registerOnSharedPreferenceChangeListener(prefListener); 
      } 
     } 

     @Override 
     public void onOffsetsChanged(float xOffset, float yOffset, float xStep, 
            float yStep, int xPixels, int yPixels) 
     { 
      renderer.setEyeX(xOffset); 
//   Log.d("onOffsetsChanged", "was called"); 
     } 

     //set up gesture detection 
     private android.view.GestureDetector.OnGestureListener gestureListener = new android.view.GestureDetector.OnGestureListener() { 
      @Override 
      public boolean onDown(MotionEvent e) { 
       return false; 
      } 

      @Override 
      public void onShowPress(MotionEvent e) { 
      } 

      @Override 
      public boolean onSingleTapUp(MotionEvent e) { 
       return true; 
      } 

      @Override 
      public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 
//    if(preferences.getBoolean("pref_key_sim_scroll", true)) 
//     renderer.setEyeX(e1.getX() - e2.getX()); 
       return false; 
      } 

      @Override 
      public void onLongPress(MotionEvent e) { 
      } 

      @Override 
      public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { 
       return false; 
      } 
     }; 
     GestureDetector mGestureDetector = new GestureDetector(OpenGLES2WallpaperService.this, gestureListener); 

     @Override 
     public void onTouchEvent(MotionEvent event) 
     { 
      mGestureDetector.onTouchEvent(event); 
     } 

     @Override 
     public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) 
     { 
      super.onSurfaceChanged(holder, format, width, height); 
      Log.d("GLES2 onSurfaceChanged", "the surface was changed"); 
     } 

     @Override 
     public void onSurfaceRedrawNeeded(SurfaceHolder holder) 
     { 
      super.onSurfaceRedrawNeeded(holder); 
      Log.d("GLES2 RedrawNeeded", "the surface was redrawn"); 

     } 

    } 

    GLSurfaceView.Renderer getNewRenderer() 
    { 
     return renderer = new GLRenderer(OpenGLES2WallpaperService.this); 
    } 
} 

classe Renderer (sorte de désordre en ce moment):

public class GLRenderer implements Renderer { 

    // Our matrices 
    private final float[] mtrxProjection = new float[16]; 
    private final float[] mtrxView = new float[16]; 
    private final float[] mMVPMatrix = new float[16]; 
    private float[] mModelMatrix = new float[16]; 
    private int mMVPMatrixHandle; 

    // Geometric variables 
    public static float vertices[]; 
    public static short indices[]; 
    public static float uvs[]; 
    public FloatBuffer vertexBuffer; 
    public ShortBuffer drawListBuffer; 
    public FloatBuffer uvBuffer; 

    // Our screenresolution 
    float mScreenWidth = 1280; 
    float mScreenHeight = 768; 

    // Misc 
    Context mContext; 
    long mLastTime; 
    int mProgram; 

    //set up our main_preferences 
    SharedPreferences preferences; 

    //set up array database 
    ArrayHolder arrayHolder = new ArrayHolder(); 

// Square square, square1; 
    Sprite background, mountains, forest, person; 
    float offsetDifference = 1; 
// Background background; 

    public void setEyeX(float offset) 
    { 
      eyeX = -offset * offsetDifference; 
      lookX = eyeX; 
//  Log.d("setEyeX", "eyeX: " + eyeX); 
    } 

    public GLRenderer(Context c) 
    { 
     mContext = c; 
    } 

    @Override 
    public void onSurfaceCreated(GL10 gl, EGLConfig config) 
    { 
     //Load in Preferences 
     preferences = PreferenceManager.getDefaultSharedPreferences(mContext); 
     // Generate Textures, if more needed, alter these numbers. 
     int[] textureNames = new int[4]; 
     GLES20.glGenTextures(4, textureNames, 0); 

     //set the scene color from preferences 
     float[] sceneColor; 
     if(preferences.getBoolean("activate_sunset", false)) 
     { 
      sceneColor = arrayHolder.sunsetColor; 
     } 
     else 
     { 
      sceneColor = arrayHolder.normalColor; 
     } 

     //create the sprites 
     person = new Sprite(arrayHolder.vertices1, sceneColor); 
     forest = new Sprite(arrayHolder.vertices2, sceneColor); 
     mountains = new Sprite(arrayHolder.vertices3, sceneColor); 
     background = new Sprite(arrayHolder.vertices4, sceneColor); 

     // Set the clear color to white 
     GLES20.glClearColor(0.9f, 0.9f, 0.9f, 0); 

     // Create the shaders, solid color 
     int vertexShader = riGraphicTools.loadShader(GLES20.GL_VERTEX_SHADER, riGraphicTools.vs_SolidColor); 
     int fragmentShader = riGraphicTools.loadShader(GLES20.GL_FRAGMENT_SHADER, riGraphicTools.fs_SolidColor); 

     riGraphicTools.sp_SolidColor = GLES20.glCreateProgram();    // create empty OpenGL ES Program 
     GLES20.glAttachShader(riGraphicTools.sp_SolidColor, vertexShader); // add the vertex shader to program 
     GLES20.glAttachShader(riGraphicTools.sp_SolidColor, fragmentShader); // add the fragment shader to program 
     GLES20.glLinkProgram(riGraphicTools.sp_SolidColor);     // creates OpenGL ES program executables 

     // Create the shaders, images 
     vertexShader = riGraphicTools.loadShader(GLES20.GL_VERTEX_SHADER, riGraphicTools.vs_Image); 
     fragmentShader = riGraphicTools.loadShader(GLES20.GL_FRAGMENT_SHADER, riGraphicTools.fs_Image); 

     riGraphicTools.sp_Image = GLES20.glCreateProgram();    // create empty OpenGL ES Program 
     GLES20.glAttachShader(riGraphicTools.sp_Image, vertexShader); // add the vertex shader to program 
     GLES20.glAttachShader(riGraphicTools.sp_Image, fragmentShader); // add the fragment shader to program 
     GLES20.glLinkProgram(riGraphicTools.sp_Image);     // creates OpenGL ES program executables 

     // Set our shader program 
     GLES20.glUseProgram(riGraphicTools.sp_Image); 

     setupImages(); 
    } 

    @Override 
    public void onSurfaceChanged(GL10 gl, int width, int height) { 

     // We need to know the current width and height. 
     mScreenWidth = width; 
     mScreenHeight = height; 
     GLES20.glViewport(0, 0, width, height); 


     float ratio; 
     if(height > width) 
     { 
      ratio = (float) width/height; 
      Matrix.frustumM(mtrxProjection,0, -ratio, ratio, -1, 1, 3, 7); 
      offsetDifference = 1; 
     } 
     else 
     { 
      ratio = (float) height/width; 
      Matrix.frustumM(mtrxProjection,0, -1, 1, -ratio, ratio, 3, 7); 
      offsetDifference = 0.5f; 
     } 

    } 

    // Position the eye in front of the origin. 
    float eyeX = 0.0f; 
    float eyeY = 0.0f; 
    float eyeZ = -4.0f; 
    // We are looking toward the distance 
    float lookX = 0.0f; 
    float lookY = 0.0f; 
    float lookZ = 0.0f; 
    // Set our up vector. This is where our head would be pointing were we holding the camera. 
    float upX = 0.0f; 
    float upY = 1.0f; 
    float upZ = 0.0f; 

    boolean colorIsRed; 

    @Override 
    public void onDrawFrame(GL10 unused) { 

     // Set the camera position (View matrix) 
     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 

     mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "u_MVPMatrix"); 

//  Log.d("onDrawFrame", "eyeX: " + eyeX); 
     Matrix.setLookAtM(mtrxView, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ); 


     // Calculate the projection and view transformation 
//  Matrix.multiplyMM(mMVPMatrix, 0, mtrxProjection, 0, mtrxView, 0); 
     Matrix.setIdentityM(mModelMatrix, 0); 
     Matrix.translateM(mModelMatrix, 0, eyeX, 0.0f, 1.0f); 
     Matrix.multiplyMM(mMVPMatrix, 0, mtrxView, 0, mModelMatrix, 0); 
     Matrix.multiplyMM(mMVPMatrix, 0, mtrxProjection, 0, mMVPMatrix, 0); 
     background.draw(mMVPMatrix, uvBuffer, 0); 

     float[] scratch2 = new float[16]; 
////  Matrix.multiplyMM(scratch, 0, mtrxProjection, 0, mtrxView, 0); 
     Matrix.setIdentityM(mModelMatrix, 0); 
     Matrix.translateM(mModelMatrix, 0, eyeX * 0.9f, 0.0f, 1.0f); 
     Matrix.multiplyMM(scratch2, 0, mtrxView, 0, mModelMatrix, 0); 
     Matrix.multiplyMM(scratch2, 0, mtrxProjection, 0, scratch2, 0); 
     mountains.draw(scratch2, uvBuffer, 3); 


     float[] scratch1 = new float[16]; 
     Matrix.setIdentityM(mModelMatrix, 0); 
     Matrix.translateM(mModelMatrix, 0, eyeX * 0.5f, 0.0f, 1.0f); 
     Matrix.multiplyMM(scratch1, 0, mtrxView, 0, mModelMatrix, 0); 
     Matrix.multiplyMM(scratch1, 0, mtrxProjection, 0, scratch1, 0); 
     forest.draw(scratch1, uvBuffer, 1); 


     if(!preferences.getBoolean("pref_key_remove_layer", true)) 
     { 
      float[] scratch = new float[16]; 
////  Matrix.multiplyMM(scratch, 0, mtrxProjection, 0, mtrxView, 0); 
      Matrix.setIdentityM(mModelMatrix, 0); 
      Matrix.translateM(mModelMatrix, 0, -0.5f, 0.3f, 1.0f); 
      Matrix.multiplyMM(scratch, 0, mtrxView, 0, mModelMatrix, 0); 
      Matrix.multiplyMM(scratch, 0, mtrxProjection, 0, scratch, 0); 
      person.draw(scratch, uvBuffer, 2); 
     } 
    } 

    public void changeColor(int colorCode) 
    { 
     float[] newColor = arrayHolder.normalColor; 
     switch(colorCode){ 
      case 0: newColor = arrayHolder.normalColor; 
       break; 
      case 1: newColor = arrayHolder.sunsetColor; 
       break; 
     } 

     person.changeColor(newColor); 
     forest.changeColor(newColor); 
     mountains.changeColor(newColor); 
     background.changeColor(newColor); 
    } 

    private void setupImages() 
    { 
     // Create our UV coordinates. 
     uvs = new float[] { 
       0.0f, 0.0f, 
       0.0f, 1.0f, 
       1.0f, 1.0f, 
       1.0f, 0.0f 
     }; 

     // The texture buffer 
     ByteBuffer bb = ByteBuffer.allocateDirect(uvs.length * 4); 
     bb.order(ByteOrder.nativeOrder()); 
     uvBuffer = bb.asFloatBuffer(); 
     uvBuffer.put(uvs); 
     uvBuffer.position(0); 

     // Generate Textures, if more needed, alter these numbers. 
     int[] texturenames = new int[4]; 
     GLES20.glGenTextures(4, texturenames, 0); 


     // Temporary create a bitmap 
     Bitmap bmp = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.squaresky); 
     // Bind texture to texturename 
     GLES20.glActiveTexture(GLES20.GL_TEXTURE0); 
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturenames[0]); 
     // Set filtering 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
     // Load the bitmap into the bound texture. 
     GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0); 

     bmp = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.squareground); 
     GLES20.glActiveTexture(GLES20.GL_TEXTURE1); 
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturenames[1]); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
     GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0); 

     bmp = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.squareperson); 
     GLES20.glActiveTexture(GLES20.GL_TEXTURE2); 
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturenames[2]); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
     GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0); 

     bmp = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.squaremountains); 
     GLES20.glActiveTexture(GLES20.GL_TEXTURE3); 
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texturenames[3]); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); 
     GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); 
     GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0); 

     bmp.recycle(); 
    } 
} 
+0

pouvez-vous publier la classe GLrenderer? –

+0

C'est publié. Dites-moi si vous avez besoin de regarder quelque chose d'autre. –

+0

onVisibilityChanged, essayez de supprimer l'appel requestRender, Il n'est pas nécessaire d'appeler cela si votre rendu rend toujours –

Répondre

0

Alors, il semble que je devais définir le bon renderer à la nouvelle vue Surface. Je l'ai fait en déplaçant le moteur de rendu GLRenderer à GLWallpaperService et en changeant setRenderer() à ceci:

 protected void setRenderer(GLSurfaceView.Renderer renderer) 
    { 
     this.renderer = (GLRenderer)renderer; //this line was missing 
     glSurfaceView.setRenderer(renderer); 
     rendererHasBeenSet = true; 
    }