Android OpenGL 2.0 с низким FPS
Я делаю приложение в OpenGL 2.0, и у меня проблема с очень низким FPS около 20 кадров в секунду. Я сделал для каждого зла новый объект, который рисует с:
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D,texture);
int mPositionHandle =
GLES20.glGetAttribLocation(riGraphicTools.sp_Image, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_FLOAT, false,
0, vertexBuffer);
int mTexCoordLoc = GLES20.glGetAttribLocation(riGraphicTools.sp_Image,
"a_texCoord" );
GLES20.glEnableVertexAttribArray ( mTexCoordLoc );
GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT,
false,
0, uvBuffer);
int mtrxhandle = GLES20.glGetUniformLocation(riGraphicTools.sp_Image,
"uMVPMatrix");
GLES20.glUniformMatrix4fv(mtrxhandle, 1, false, m, 0);
int mSamplerLoc = GLES20.glGetUniformLocation (riGraphicTools.sp_Image,
"s_texture" );
GLES20.glUniform1i ( mSamplerLoc, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);
GLES20.glFlush();
GLES20.glFinish();
Теперь у меня всего четыре спрайта и около 20 кадров в секунду, но я собираюсь добавить около 10-15 спрайтов. Это будет глючить.
1 ответ
Есть ряд вещей, которые, вероятно, помогут вашей производительности. Начиная с пары простых вещей:
Как @dari также указал, избавиться от тех,
glFlush()
а такжеglFinish()
звонки. Вы должны очень редко нуждаться в них. излишнийglFlush()
звонки почти всегда вредны для производительности, иglFinish()
действительно очень плохо. Одним словом, одним из основных принципов графических API, таких как OpenGL, является то, что они позволяют графическому процессору работать асинхронно с процессором.glFinish()
вызывает полную синхронизацию между процессором и графическим процессором, вместо того, чтобы позволить им работать параллельно, что крайне нежелательно.Вы должны сделать все эти
glGetAttribLocation()
а такжеglGetUniformLocation()
вызывает один раз после компиляции шейдера и сохраняет места, как правило, в переменных-членах вашего класса. Тогда просто используйте значения этих переменных вместо того, чтобы делать избыточные вызовы каждый раз, когда вы рисуете. Например, один раз после связывания шейдера вы выполняете эти операторы, гдеmPositionLoc
а такжеmMatrixLoc
являются переменными-членами:mPositionLoc = GLES20.glGetAttribLocation(riGraphicTools.sp_Image, "vPosition"); mMatrixLoc = GLES20.glGetUniformLocation(riGraphicTools.sp_Image, "uMVPMatrix");
Затем, когда вы рисуете, вы используете эти переменные для настройки ваших атрибутов и униформы:
GLES20.glEnableVertexAttribArray(mPositionLoc); GLES20.glVertexAttribPointer(mPositionLoc, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer); ... GLES20.glUniformMatrix4fv(mMatricLoc, 1, false, m, 0);
Эти двое уже могут сделать вам большой шаг вперед. Помимо этого, вы должны изучить использование объектов Vertex Buffer (VBO). Они позволяют хранить ваши вершины и индексировать данные в буферах, а не передавать их glVertexAttribPointer()
а также glDrawElements()
каждый раз. Это особенно полезно, если данные вершин изменяются не часто. Вы должны быть в состоянии найти множество учебников и примеров кода для их использования. Они будут использовать вызовы API, такие как glGenBuffers()
, glBindBuffer()
, так далее.
Если пойти еще дальше, если этого недостаточно для достижения целевых показателей производительности, вы можете рассмотреть возможность хранения данных вершин для всех ваших спрайтов в одном буфере вместо отдельного буфера для каждого. Таким образом, вам не нужно будет так много glBindBuffer()
Можно glVertexAttribPointer()
звонки.