2016-10-24 3 views
0

Я использую следующие функции для загрузки текстурПочему текстуры POT работают медленнее, чем не-pot?

public static int loadTexture(Bitmap bmp) 
{ 
    final int[] textureHandle = new int[1]; 

    GLES20.glGenTextures(1, textureHandle, 0); 
    if (textureHandle[0] != 0) 
    { 

     // Bind to the texture in OpenGL 
     GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[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); 
     //GLES20.glGenerateMipmap(textureHandle[0]); 
     //adapt texture to POT 
     int adaptedWidth= (int) Math.pow(2,Math.ceil(Math.log(bmp.getWidth())/Math.log(2d))); 
     int adaptedHeight= (int) Math.pow(2,Math.ceil(Math.log(bmp.getHeight())/Math.log(2d))); 
     Log.d("texture",adaptedWidth+","+adaptedHeight); 

     Bitmap tmp = Bitmap.createScaledBitmap(bmp, adaptedWidth, adaptedHeight, false); 
     Log.d("asize",tmp.getWidth()+","+tmp.getHeight()); 
     // Load the bitmap into the bound texture. 
     GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, tmp, 0); 
     //GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bmp, 0); 
     tmp.recycle(); 
     // Recycle the bitmap, since its data has been loaded into OpenGL. 
     //bmp.recycle(); 
    } 

    if (textureHandle[0] == 0) 
    { 
     throw new RuntimeException("Error loading texture."); 
    } 
    return textureHandle[0]; 
} 

я получил 14-17 кадров в секунду с этим code.Hovever, если я загрузить мою битовую карту (которая не является POT) напрямую, без адаптации к POT.FPS подскакивает до 28-30 . Я думал, что текстуры POT должны работать быстрее, чем неPOT.Есть ли объяснение для этого?

UPD: Rendering Код:

@Override 
public void onDrawFrame(GL10 gl) { 
    //curScale=modelMatrix[SCALE_X]; 
    TimeMeasurer.reset(); 
    long curTS= SystemClock.uptimeMillis(); 
    long frameRenderTime=curTS-ts; 
    //Log.d("renderer","FPS:"+1000.0/frameRenderTime); 
    Log.d("renderer","frame render time:"+frameRenderTime); 
    ts=curTS; 
    GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); 
    if (piecesMesh!=null) { 
     Matrix.setIdentityM(MVPMatrix,0); 
     Matrix.multiplyMM(MVPMatrix,0,projMatrix,0,modelMatrix,0); 
     drawPassivePieces(); 
     drawActivePieces(); 
     if (helper!=null) { 
      drawHelper(); 
     } 
    } 
    TimeMeasurer.measure("onDrawFrame execution time:"); 
} 
private void drawPassivePieces() { 
    //shadows 
    shadowProgram.useProgram(); 
    shadowProgram.setUniforms(MVPMatrix,textureMaskId); 
    shadowMesh.bindPieceData(shadowProgram,false); 
    shadowMesh.drawPieces(false); 
    shadowMesh.disableAttributes(shadowProgram); 
    //pieces 
    piecesProgram.useProgram(); 
    piecesProgram.setUniforms(MVPMatrix, textureImageId, textureMaskId); 
    piecesMesh.bindPieceData(piecesProgram,false); 
    piecesMesh.drawPieces(false); 
    piecesMesh.disableAttributes(piecesProgram); 

} 
private void drawActivePieces() { 
    //shadows 
    shadowProgram.useProgram(); 
    shadowProgram.setUniforms(MVPMatrix,textureMaskId); 
    shadowMesh.bindPieceData(shadowProgram,true); 
    shadowMesh.drawPieces(true); 
    shadowMesh.disableAttributes(shadowProgram); 
    //pieces 
    piecesProgram.useProgram(); 
    piecesProgram.setUniforms(MVPMatrix, textureImageId, textureMaskId); 
    piecesMesh.bindPieceData(piecesProgram,true); 
    piecesMesh.drawPieces(true); 
    piecesMesh.disableAttributes(piecesProgram); 
} 
public void drawHelper() { 
    helperProgram.useProgram(); 
    helper.bindData(helperProgram); 
    helper.draw(); 
    helper.disableAttributes(helperProgram); 
} 

ответ

0

Без подробного анализа производительности на самом деле невозможно сделать больше, чем спекулировать.

Возможно, что ваш рендеринг ограничен полосой пропускания текстуры. Если размер текстуры больше, общий объем доступной памяти больше, что приведет к замедлению.

Или, что связано с вышеизложенным, скорость попадания кэш-памяти для выборки текстуры падает, если выбранные тексели распространяются дальше в памяти, что происходит, когда вы улучшаете текстуру. Более низкая скорость попадания в кеш означает медленную производительность.

Вы действительно не должны искусственно создавать текстуру больше, чем необходимо, если только это не требуется из-за ограниченной поддержки NPOT в ES 2.0, а используемое вами оборудование не рекламирует расширение OES_texture_npot. Я сомневаюсь, что кто-то сделал аппаратное обеспечение, которое предпочитает текстуры POT в течение длительного времени.

+0

Добавлено рендеринг code.Also Я сделал некоторые измерения: NPOT: рамки время рендеринга: 39 OnDraw времени выполнения: 8 POT: рамки время рендеринга: 73 OnDraw времени выполнения: 8 Так что проблема в составлении времени, которое Я предполагаю, что разница между «временем рендеринга кадров» и «временем выполнения onDraw» – undefined

+0

Также я изменил код загрузки текстуры, чтобы он не увеличивал растровое изображение, а просто рисовал мою текстуру в новый более пустой пустой бимап - тот же результат. – undefined

+0

@undefined Все эти наблюдения согласуются с моей теорией. –

0

Есть большие преимущества использования POT текстуры. В OpenGLES 2.0 они позволяют использовать mipmaps и полезные режимы адресации текстур, например repeat. Вы также можете использовать память более эффективно, потому что многие реализации выделяют память так, как если бы ваша текстура была POT в любом случае.

Однако в этом случае, когда вы просто берете текстуру не-POT и масштабируете ее, я ожидаю, что в результате производительность будет немного хуже. Вы упускаете большой потенциальный выигрыш, потому что вы не используете mipmaps. Используя большую текстуру, вы просто запрашиваете больше кеша текстур графического процессора, потому что полезные части изображения теперь более распространены в памяти, чем раньше.

Другой способ взглянуть на это заключается в том, что при отсутствии mipmapping большие текстуры будут работать хуже, чем маленькие текстуры, и ваш процесс масштабирования просто увеличивает вашу текстуру.

Я удивлен, что разница настолько заметна, хотя - вы уверены, что ваша перемасштабирующая кодировка не делает ничего неожиданного, например, слишком большого размера или выбора другого формата текстуры или режима фильтра?

+0

Я использую свое растровое изображение как источник в createScaledBitmap, поэтому формат пикселей должен быть тем же. Фильтры не применяются. Размер моей текстуры: 1792x1536; адаптированный размер: 2048x2048 Я рисую 2220 полигонов с одним фрагментарным шейдером (используя две текстуры), а затем 2220 полигонов с другим фрагментарным шейдером. Его удивление для меня тоже, почему такой же код зависит от размера текстуры так сильно. – undefined

Смежные вопросы