2012-05-23 116 views
6

我正在使用opengl es 2.0編寫Android 2d遊戲。在將我的精靈繪製到後緩衝器之後,我將燈光吸引到FBO並嘗試再次將其融合到後緩衝器。 當我將FBO繪製到幀緩衝區,甚至是沒有任何顏色的透明區域時,在Samsung Galaxy w(其具有adreno 205作爲gpu)時,幀率從60降低到30。我到處搜索並嘗試了所有內容,即使我在場景中繪製單個精靈,並將透明的FBO紋理融合到幀速率下降的屏幕上。我在那款手機上嘗試了其他帶有照明效果的遊戲,並且運行良好,幾乎在該手機上每場比賽都很順利,我相信他們也使用了幀緩衝。 關於Galaxy SII(mali 400 gpu)運行良好,我對opengl相當陌生,所以我相信我在某處犯了一個錯誤,我分享了我的代碼。Framebuffer FBO渲染紋理很慢,在Android上使用OpenGL ES 2.0,爲什麼?

// Create a framebuffer and renderbuffer 
GLES20.glGenFramebuffers(1, fb, offset); 
GLES20.glGenRenderbuffers(1, depthRb, offset); 

// Create a texture to hold the frame buffer 
GLES20.glGenTextures(1, renderTex, offset); 
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, renderTex[offset]); 

GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, 
        screenWidth, screenHeight, 0, 
        GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, 
        null); 


GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, 
         GLES20.GL_CLAMP_TO_EDGE); 
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, 
         GLES20.GL_CLAMP_TO_EDGE); 
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, 
         GLES20.GL_LINEAR); 
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, 
         GLES20.GL_LINEAR); 

//bind renderbuffer 
GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRb[offset]); 

GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, 
          screenWidth, screenHeight); 

// bind the framebuffer 
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fb[offset]); 

// specify texture as color attachment 
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, 
           GLES20.GL_TEXTURE_2D, renderTex[offset], 0); 

// specify depth_renderbufer as depth attachment 
GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, 
           GLES20.GL_RENDERBUFFER, depthRb[0]); 

// Check FBO status. 
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); 

if (status == GLES20.GL_FRAMEBUFFER_COMPLETE) 
{ 
    Log.d("GLGame framebuffer creation", "Framebuffer complete"); 
} 


// set default framebuffer 
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); 

我在表面創建時做了一次。不確定是否正確。當我需要時,我保持紋理和framebuffer ID切換到它們。 我的繪製代碼:

GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId); 
ShaderProgram program = glgame.getProgram(); 

//put vertices in the floatbuffer 
mTriangleVertices.put(vertices, 0, len); 
mTriangleVertices.flip(); 

GLES20.glVertexAttribPointer(program.POSITION_LOCATION, 2, GLES20.GL_FLOAT, false, 
          TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); 

//preparing parameter for texture position 
mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); 
GLES20.glEnableVertexAttribArray(program.POSITION_LOCATION); 

//preparing parameter for texture coords 
GLES20.glVertexAttribPointer(program.TEXTURECOORD_LOCATION, 2, GLES20.GL_FLOAT, 
          false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, 
          mTriangleVertices); 

//set projection matrix 
GLES20.glEnableVertexAttribArray(program.TEXTURECOORD_LOCATION); 
GLES20.glUniformMatrix4fv(program.MATRIX_LOCATION, 1, false, matrix, 0); 

//draw triangle with indices to form a rectangle 
GLES20.glDrawElements(GLES20.GL_TRIANGLES, numSprites * 6, GLES20.GL_UNSIGNED_SHORT, 
         indicesbuf); 

//clear buffers 
mTriangleVertices.clear(); 
mVertexColors.clear(); 

一切呈現在屏幕上正確,但就在我畫FBO的質感表現也毀了。 非常感謝您的幫助。我非常努力地工作,並沒有找到解決方案。

+0

遲到的答案,但我在ICS下的HD2上做了類似的事情,它幾乎是一樣的。我可以在60fps下渲染任何沒有問題的東西,但是當我使用FBO時,幀速率會降低到45,如果我使用另一個FBO,它會下降到30. – 2012-06-04 22:22:00

+0

嗯......我見過三星銀河運行沒有問題,他們似乎使用2D緩衝幀緩衝,我的代碼運行緩慢,而不是。我想知道我是否犯錯。 – mao

+0

星系使用sgx芯片組。就像我之前說過的與小gmem和平鋪架構相關的那樣,每次你改變framebuffer舊的需要複製到正常的mem,如果你在綁定之後將它作爲第一個調用清除掉,它不需要從正常的複製回來mem到gmem,這就是爲什麼幀緩衝器特別是在adreno 200上慢):如果你有adreno設備,只需插入並下載當前幀,然後檢查紋理中的fb,就可以檢查是否使用帶有adreno profiler的幀緩衝器。如果你會發現一個,你會確定, – ZZZ

回答

12

根據qualcomm文檔,您需要在每個glbindframebuffer後面glclear,這是一個與平鋪架構相關的問題,如果您切換幀緩衝區,則需要將數據從fastmem複製到正常內存以保存當前幀緩衝區,並從slowmem快速mem來獲取新綁定幀的內容,以防在glbind之後清除沒有數據從slowmem複製到fastmem,並且您節省了時間,但您需要經常重新設計渲染管道,以避免讀取數據並避免在慢速和快速內存之間,因此嘗試在每次綁定之後執行glclear並且它應該有所幫助,您還可以使用adreno分析器獲取有關有問題的調用的其他信息,但我懷疑它會幫助adreno200我試圖獲得兩個緩衝區模糊,我以10fps結束,bindframebuffer調用可能需要20毫秒,如果它不清除,如果它是笑最終在2ms結束。

+0

只要我能再次獲得adreno 205的幫助,我會盡快嘗試。我找到了高質量的文檔,我會遵循它。非常感謝您的幫助! – mao

+0

[Here](https://www.google.sk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CDEQFjAA&url=https%3A%2F%2Fdeveloper.qualcomm.com%2Fdownload%2Fadreno200performanceoptimizationopelestipsandtricksmarch10 .pdf&ei = DT6IUcaTMYXV4ASEwYHYAQ&usg = AFQjCNFbU3Vf2mT2sf7LTAJQ3xqijdyUAA&sig2 = JMoeTn8G1MQgor9ZGDdFQg&bvm = bv.45960087,d.bGE)是高質量的文檔。 –

+1

如果你想保留framebuffer的內容,只需執行'glClear(0);',這似乎也解決了這個問題。 – Thomas