2012-05-23 23 views
6

Opengl es 2.0 kullanarak bir Android 2d oyunu programlıyorum. Spriteları arka tarafa gönderdikten sonra ışıkları bir FBO'ya çiziyorum ve tekrar arka tampona karıştırmaya çalışıyorum. FBO'yu framebuffer'a çizdiğimde, herhangi bir renk olmadan trasparent bile olsa, çerçeveler Samsung Galaxy w'de 60'dan 30'a düşer (gpu olarak adreno 205'e sahiptir). Her yerde aradım ve her şeyi denedim, sahnede tek bir sprite çizsem ve çerçevenin düştüğü ekrana bir trasparent FBO yapısını karıştırsam bile. Bu telefonda ışık efektleri ile diğer oyunları denedim ve iyi çalışıyorlar, hemen hemen her oyun bu telefonda iyi, ben de framebuffer kullanıyorlar inanıyorum. Galaxy SII'de (mali 400 gpu) iyi çalışıyor, opengl için oldukça yeniyim, bu yüzden bir yerde hata yaptığımı düşünüyorum, kodumu paylaşıyorum.Framebuffer FBO dokuya çok yavaş, OpenGL ES 2.0 on Android kullanıyor, neden?

// 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); 

Bunu bir kez yüzey oluşturmada yapıyorum. Doğru olup olmadığından emin değilim. İhtiyacım olduğunda doku ve framebuffer kimliklerini kullanmaya devam ediyorum. Benim çizim kodu:

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(); 

Her şey düzgün ekranda oluşturulur, ancak FBO doku çizmek sadece zaman performans mahvolur. Yardımlarınız için çok teşekkür ederim. Bu konuda çok çalıştım ve bir çözüm bulamadım.

+0

Geç cevap, ancak ICS altında bir HD2'ye benzer bir şey yapıyorum ve hemen hemen aynı. 60 fps'de problemsiz bir şey yapabilirim, ama bir FBO kullandığımda, kare hızı 45'e düşer ve başka bir FBO kullanırsam 30'a iner. –

+0

Hmm ... Samsung'da bazı oyunlar gördüm Galaxy w sorunsuz çalışıyor ve 2d ışıkları için bir framebuffer kullanmak görünüyordu, kodum yerine yavaş çalışır. Acaba hata yapıyorum. – mao

+0

galaxy sgx chipset kullanır. küçük gmem ve çini mimarisi ile ilgili daha önce de söylediğim gibi, her zaman eski bir çerçevenin eski bir öğeye kopyalanmasına gerek duyarsınız, eğer bağladıktan sonra ilk çağrı olarak temizlerseniz normalden kopyalanmaya gerek yoktur gmem için mem, bu yüzden adreno 200 özellikle framebuffers yavaş vardır :) adreno cihaz varsa adreno profiler ile framebuffers kullanarak app kontrol edebilirsiniz, sadece takın ve geçerli çerçeve indirin, sonra dokularda fb için kontrol edin. Eğer bir tane bulacağınızdan emin olursanız, – ZZZ

cevap

12

Qualcomm docs'a göre, her glbind framebuffer'dan sonra glclear yapmanız gerekir, bu, kiremit mimarisi ile ilgili bir problemdir, eğer framebacker değiştiriyorsanız, mevcut framebuffer'ı kaydetmek için fastmem'den normal belleğe kopyalanmaya gerek duyarsınız ve slowmem'den yeni birleştirilmiş çerçevenin içeriğini almak için hızlı mem, eğer glmind'den hemen sonra temizlediğinizde hiçbir veri yavaşlamadan fastmem'e kopyalanır ve zamandan tasarruf edersiniz, ancak render pipeline'ınızı yeniden tasarlamanız gerekir, bu yüzden verileri geri okumaktan kaçınır ve yavaş ve hızlı bellek arasında, bu yüzden her bağlantıdan sonra glclear yapmak deneyin ve yardımcı olmalıdır, aynı zamanda sorunlu aramalar hakkında ek bilgi almak için adreno profiler kullanabilirsiniz, ama adreno200 ile yardımcı olacağından şüpheleniyorum çünkü iki arabellek almaya çalışıyorum Bulanıklık ve ben 10fps ile bittim, bindframebuffer çağrı eğer temizlenmemişse, 20msec kadar sürebilir 2ms de biter.

+0

Adreno 205'de ellerimi tekrar alabildiğim zaman bunu deneyeceğim. Qualcomm belgelerini buldum ve onu takip edeceğim. Yardımın için çok teşekkürler! – mao

+0

[Burada] (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%2Fadreno200performanceoptimizationopenglestipsandtricksmarch10 .pdf & ei = DT6IUcaTMYXV4ASEwYHYAQ & usg = AFQjCNFbU3Vf2mT2sf7LTAJQ3xqijdyUAA & sig2 = JMoeTn8G1MQgor9ZGDdFQg & bvm = bv.45960087, d.bGE), Qualcomm belgesidir. –

+1

Çerçeve kıskacının içeriğini korumak istiyorsanız, sadece sorunu gidermek için 'glClear (0); 'komutunu kullanın. – Thomas