J'ai actuellement un problème de performance dans mon programme OpenGL ES. Je pensais que cela fonctionnerait bien - en utilisant VBO, textureatlas, peu de liaisons pour chaque tirage au sort et ainsi de suite. Mais lorsque vous utilisez plusieurs sprites en même temps, la performance chute beaucoup. J'ai trouvé que le goulot d'étranglement est lié au processeur (un peu surpris). Plus précisément - le goulot d'étranglement pourrait être dervied à une méthode qui calcule l'écran pour chaque rectangles quatre vertitudes - x1, y1, x2, y2, x3, y3, x4, y4. Ceci est utilisé pour la détection de collision. Ce que je fais dans cette méthode est de répéter ce qui est fait dans les shaders et je pense que de nombreux cpu-cycles sont causés par les multiplications MV.OpenGL ES: Récupère les sommets transformés à partir du shader
Matrix.multiplyMV(resultVec, 0, mModelMatrix, 0, rhsVec, 0);
le rhsVec est un tableau flottant qui stocke les sommets comme décrit ci-dessus.
Puisque cela semble être le goulot d'étranglement, je me demande comment j'ai pu accéder au même vecteur dans le shader lorsque, par exemple, les coordonnées de clip sont calculées? Clip-coordonne ou même mieux les coordonnées produites par il shaders plus bas dans la ligne de pipe.
le sommet shader
uniform mat4 u_MVPMatrix;
uniform mat4 u_MVMatrix;
varying vec2 v_TexCoordinate;
attribute vec4 position;
void main()
{
v_TexCoordinate = a_TexCoordinate
gl_Position = u_MVPMatrix * a_Position;
}
extrait de onSurfaceCreated
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_Color", "a_Normal", "a_TexCoordinate"});
textureHandle = TextureHelper.loadTexture(context);
GLES20.glUseProgram(mProgramHandle);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix");
mMVMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVMatrix");
//mColorHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Color");
mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_TexCoordinate");
mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
la méthode qui permet la transformation de sommet (goulot d'étranglement)
private void calcPos(int index) {
int k = 0;
for (int i = 0; i < 18; i += 3) {
rhsVec[0] = vertices[0 + i];
rhsVec[1] = vertices[1 + i];
rhsVec[2] = vertices[2 + i];
rhsVec[3] = 1;
// *** Step 1 : Getting to eye coordinates ***
Matrix.multiplyMV(resultVec, 0, mModelMatrix, 0, rhsVec, 0);
// *** Step 2 : Getting to clip coordinates ***
float[] rhsVec2 = resultVec;
Matrix.multiplyMV(resultVec2, 0, mProjectionMatrix, 0, rhsVec2, 0);
// *** Step 3 : Getting to normalized device coordinates ***
float inv_w = 1/resultVec2[3];
for (int j = 0; j < resultVec2.length - 1; j++) {
resultVec2[j] = inv_w * resultVec2[j];
}
float xPos = (resultVec2[0] * 0.5f + 0.5f) * game_width;
float yPos = (resultVec2[1] * 0.5f + 0.5f) * game_height;
float zPos = (1 + resultVec2[2]) * 0.5f;
SpriteData sD = spriteDataArrayList.get(index);
switch (k) {
case 0:
sD.xPos[0] = xPos;
sD.yPos[0] = yPos;
break;
case 1:
sD.xPos[2] = xPos;
sD.yPos[2] = yPos;
break;
case 2:
sD.xPos[3] = xPos;
sD.yPos[3] = yPos;
break;
case 3:
sD.xPos[1] = xPos;
sD.yPos[1] = yPos;
break;
}
k++;
if (i == 3) {
i += 9;
}
}
Cette méthode est appelée pour chaque image-objet - donc pour 100 sprites, il a répété 100 fois. Probablement les multiplications MV atteint la performance?
Cette opération ne peut probablement pas être trop lente dans votre cas. C'est 400 multiplications matricielles et vectorielles? Bien que possible, vous ne devez pas utiliser de GPU pour les collisions de sprites, vous devrez transférer les données de GPU à CPU, ce qui devrait dans votre cas être beaucoup plus lent. Si cette multiplication est vraiment trop lente, elle doit être buggée alors créez plutôt la vôtre. –
@MaticOblak - merci pour votre commentaire. En fait, je l'ai en quelque sorte résolu - au lieu d'utiliser une fonction de bibliothèque j'ai fait une multiplication manuelle de la matrice avec les vertices et volia - le framerate a augmenté et le problème semble être résolu - au moins partiellement.Thouh j'ai encore utilisé pas plus de 55 - 60 sprites dans l'attention des appareils plus lents. Mon Galaxy S7 peut gérer plus de 100 sprites mais pas l'onglet galaxie – java
En plus de la réponse déjà fournie, [* toujours * mesurer la performance en ms pas fps] (https://www.mvps.org/directx/articles/fps_versus_frame_time .htm). –