0


私は約30〜80のテクスチャ平面(正方形)を描画しています-背景、プレーヤー、敵、弾丸など。
すべての平面は移動および拡大縮小し、一部は+回転し、一部はアニメーション化されたテクスチャを備えています。

CPUやGPUにとってはそれほど難しいことではないと思いますが、低速/古いデバイスでは、パフォーマンスが比較的低くなります(Galaxy ACEなど)。

どうか、私のコードを見ていただけますか、私は何を間違っているのか、汚いのですか?または、何を最適化できますか?
ありがとうございました。

これは私のonSurfaceCreated、onSurfaceChanged、onDrawFrameです。

public void onSurfaceCreated(GL10 glUnused, EGLConfig config) { 
  ..
  // load and prepare all textures 
  ..

  GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);  
  GLES20.glEnable(GLES20.GL_CULL_FACE);             
  GLES20.glDisable(GLES20.GL_DEPTH_TEST);       
  GLES20.glEnable(GLES20.GL_TEXTURE_2D);            

  GLES20.glDisable(GL10.GL_DITHER);
  GLES20.glDisable(GL10.GL_LIGHTING);
  final float eyeX = 0.0f; final float eyeY = 0.0f; final float eyeZ = 1.5f;       
  final float lookX = 0.0f; final float lookY = 0.0f; final float lookZ = -3.0f;
  final float upX = 0.0f; final float upY = 1.0f; final float upZ = 0.0f;
  Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);  

  mProgramHandle = GLES20.glCreateProgram();    

  final String vertexShader =
  "uniform mat4 u_MVPMatrix;         \n"                       
  + "attribute vec4 a_Position;      \n"                            
  + "attribute vec2 a_TexCoordinate; \n"    
  + "attribute float a_AlphaValue;   \n"
  + "varying vec2 v_TexCoordinate;   \n"            
  + "varying float v_AlphaValue;     \n"
  + "void main()                     \n"                                
  + "{                               \n"                          
  + "   v_TexCoordinate = a_TexCoordinate;      \n"  
  + "   v_AlphaValue = a_AlphaValue;            \n"
  + "   gl_Position = u_MVPMatrix * a_Position; \n"
  + "}                                          \n";        

  final String fragmentShader =
  "precision lowp float;                \n"         
  + "uniform sampler2D u_Texture;       \n"     
  + "varying vec2 v_TexCoordinate;      \n"     
  + "varying float v_AlphaValue;        \n"             
  + "void main()                        \n"     
  + "{                                  \n"
  + "   gl_FragColor = texture2D(u_Texture, v_TexCoordinate); \n"             
  + "   gl_FragColor.a *= v_AlphaValue; \n"
  + "}                                  \n";            

  final int vertexShaderHandle = ShaderHelper.compileShader(GLES20.GL_VERTEX_SHADER, vertexShader);     
  final int fragmentShaderHandle = ShaderHelper.compileShader(GLES20.GL_FRAGMENT_SHADER, fragmentShader);       
  mProgramHandle = ShaderHelper.createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, new String[] {"a_Position", "a_TexCoordinate", "a_AlphaValue"});

  GLES20.glUseProgram(mProgramHandle);  
  mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix");
  mMVMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVMatrix");
  mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
}   

public void onSurfaceChanged(GL10 glUnused, int width, int height) {    
  GLES20.glViewport(0, 0, width, height);
  float ratio = (float) width / height;
  Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 1, 1000);
}   

public void onDrawFrame(GL10 glUnused) {
  GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
  GLES20.glEnable(GLES20.GL_BLEND); 
  GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
  updateGame();

  // all planes are saved in Vector<Mesh> children          
  int size = children.size();
  for (int i = 0; i < size; i++)
  {
    children.get(i).Draw(renderer);
  }
}



そして、'plane'オブジェクトのDraw(Renderer):

public void Draw(Renderer renderer)
{                       
  if (!Visible) return; // no visible object, no need draw
  mTextureCoordinateHandle = GLES20.glGetAttribLocation(renderer.mProgramHandle, "a_TexCoordinate");
  GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBrickDataHandle); 
  mAlphaHandle = GLES20.glGetAttribLocation(renderer.mProgramHandle, "a_AlphaValue");       
  GLES20.glVertexAttrib1f(mAlphaHandle, alpha);

  // texture animation
  renderer.mPlaneTextureCoords[(byte)indexAnim].position(0); 
  GLES20.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES20.GL_FLOAT, false, 0, renderer.mPlaneTextureCoords[(byte)indexAnim]);
  indexAnim++;

  renderer.mPlanePositions.position(0); 
  GLES20.glVertexAttribPointer(Renderer.mPositionHandle, renderer.mPositionDataSize, GLES20.GL_FLOAT, false, 0, renderer.mPlanePositions);        
  GLES20.glEnableVertexAttribArray(Renderer.mPositionHandle);                       

  if (angleZ == 0) // no rotating plane -> no need setRotateM
  {
    Matrix.setIdentityM(renderer.mModelMatrix, 0);
    Matrix.translateM(renderer.mModelMatrix, 0, x, y, z);
    Matrix.scaleM(renderer.mModelMatrix, 0, scaleX, scaleY, 1);
  }
  else // rotating plane
  {
    float[] mt = new float[16];
    Matrix.setIdentityM(mt, 0);
    Matrix.translateM(mt, 0, x, y, z);
    Matrix.scaleM(mt, 0, scaleX, scaleY, 1);
    Matrix.setRotateM(mRotZMatrix, 0, angleZ, 0, 0, 1);
    Matrix.multiplyMM(renderer.mModelMatrix, 0, mt, 0, mRotZMatrix, 0);
  }

  Matrix.multiplyMM(renderer.mMVPMatrix, 0, renderer.mViewMatrix, 0, renderer.mModelMatrix, 0);   
  GLES20.glUniformMatrix4fv(renderer.mMVMatrixHandle, 1, false, renderer.mMVPMatrix, 0);                

  //Matrix.multiplyMM(renderer.mMVPMatrix, 0, renderer.mProjectionMatrix, 0, renderer.mMVPMatrix, 0);
  Matrix.multiplyMM(renderer.mTemporaryMatrix, 0, renderer.mProjectionMatrix, 0, renderer.mMVPMatrix, 0); // little bit faster (?)
  System.arraycopy(renderer.mTemporaryMatrix, 0, renderer.mMVPMatrix, 0, 16);

  GLES20.glUniformMatrix4fv(renderer.mMVPMatrixHandle, 1, false, renderer.mMVPMatrix, 0); // pass in the combined matrix
  GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle);        
  GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);  
}   
4

3 に答える 3

2

遅い操作になる可能性があるため、描画ループ内で glGet* を何度も呼び出す必要はないと思います。

オブジェクト内で属性の場所をローカルにキャッシュすることはできますか? または、すべてのオブジェクトが同じシェーダーを使用しているのに、オブジェクトごとに属性の場所を設定しているのはなぜだろうか。

于 2012-08-26T15:57:32.817 に答える
1

新しいバージョンのAndroidSDK(v16など)で実行している場合は、プロファイラーを使用して、問題のある領域がどこにあるかを見つけることができます。

http://developer.android.com/tools/debugging/debugging-tracing.html

しかし、一見すると、私が見ることができることがいくつかあります。

  1. 別のレスポンダーは、ドローコール内でコールしていることを強調しglGetAttribLocationました。ドローするたびにこれを行う必要はありません。「プログラム」が設定されると、これらの参照を取得でき、そのプログラムが変更されない限り(つまり、シェーダーを変更しない限り)変更されません。同様にへの呼び出しでglEnableVertexAttribArray

  2. テクスチャアトラスの使用を検討してください。を呼び出すたびglBindTextureに、VRAMの状態が変化する可能性があります。これは動作が遅くなります。テクスチャアトラスは、すべて(または多数)またはテクスチャ(スプライトなど)を含む単一の画像です。テクスチャ座標を指定するときは、アトラス内の単一のスプライトの位置を表す0〜1の値を指定するだけです。このアプローチを使用する場合は、スペースを無駄にしないように、アトラスを「ビンパック」する必要があります。これを行うためのツールがいくつかあります(TexturePackerなど)。これは、への呼び出しが少なくなる(おそらく1つだけ)ことを意味しますglBindTexture

  3. MVPマトリックスを2回渡すことになりますが、glUniformMatrix4fvこれは不要です。送信後にシェーダーに送信されるマトリックスを変更しても効果はありません(つまり、初期設定操作が上書きされます)。マトリックスは、シェーダーがへの呼び出しで実行されるときにのみ使用されるためです。glDrawArrays

  4. 私は最近、それsetRotateMがかなり遅いことを発見しました。私が見つける必要がある場所の周りにも選択肢があります!

  5. あなたの最後System.arrayCopyは不要です。温度を必要とせずに、行列の乗算を連鎖させることができます。マトリックス。モデル*ビュー=MV、次にMV*プロジェクション=MVP

まだ読んでいない場合は、このチュートリアルも確認してください。

http://www.learnopengles.com/android-lesson-one-getting-started/

そして、サードパーティのゲームエンジンのルートをたどることを決定した場合、IMOlibgdxはFARによって最高です。

http://libgdx.badlogicgames.com/

これは無料のオープンソースであり、パフォーマンスに重点を置いています。libgdxが提供する幅広い機能を必要としなかったので、私も自分でビルドすることにしましたが、コードのすべての行でこの決定に疑問を投げかけることになります;)

幸運を。

于 2012-10-30T07:26:23.583 に答える
0

以前にゲーム エンジンの使用について検討したことがありますか? それらのかなりの数は、かなり少ないコードでこの種のタスクを処理でき、ストレス = P

ゲーム エンジンを学習するには、最初は少し時間がかかりますが、後で何百時間も節約できます。ゲーム用に設計されているため、通常、古いデバイスでもパフォーマンスを犠牲にすることなく、大量のオブジェクトを適切に処理できます。

これはあなたの質問に対する直接的な解決策ではありませんが、後で役立つかもしれません ^.^ Android 用のゲーム エンジンの膨大なリストを次に示します http://mobilegameengines.com/android/game_engines

オープン ソースのゲーム エンジンが好きなら、これらも気に入るかもしれません。私はこれらのうちのいくつかしか使用したことがありませんが、AndEngine は最も簡単に始めることができ、30 ~ 80 個のオブジェクトを処理するのに十分強力であることは間違いありません。 http://ntt.cc/2011/05/08/8-open-source-android-game-engines.html

于 2012-08-26T15:43:39.143 に答える