2012-03-20 61 views
4

我希望有人可以幫我指明瞭一些紋理基準我做的OpenGL ES 2.0的一些進展和iPhone 4優化OpenGL ES 2.0的2D紋理輸出和幀率

我有一個包含精靈的數組對象。渲染循環遍歷每個紋理的所有精靈,並檢索其所有紋理座標和頂點座標。它使用退化的頂點和索引將它們添加到一個巨大的交織陣列中,並將它們發送給GPU(我嵌入的代碼是底部)。這一切都是按照紋理完成的,所以我將紋理綁定一次,然後創建我的交錯數組,然後繪製它。一切都很好,屏幕上的結果正是他們應該做的。

因此,我的基準測試是通過在不同的不透明度下添加25個新的精靈,並在更新上更改它們的頂點,以便在應用程序上旋轉並運行OpenGL ES分析器時,它們在屏幕周圍彈跳。

繼承人,我希望有一些幫助.... 我可以達到約275個32x32精靈與不同的不透明度在60 fps的屏幕上跳動。到400我下降到40幀/秒。當我運行OpenGL ES Performance Detective時,它會告訴我...

應用程序渲染受三角形柵格化的限制 - 將三角形轉換爲像素的過程。所有正在渲染的三角形的總面積(以像素爲單位)太大。要以更快的幀率繪製,請通過減少三角形的數量,其大小或兩者的大小來簡化場景。

的是我剛颳起了測試在cocos2d使用CCSpriteBatchNode使用相同的紋理和創建800個透明精靈和幀率爲60fps的容易。

下面是一些代碼,可能是中肯......

Shader.vsh(矩陣在成立伊始一次)

void main() 
{ 
    gl_Position = projectionMatrix * modelViewMatrix * position; 
    texCoordOut = texCoordIn; 
    colorOut = colorIn; 
} 

Shader.fsh(colorOut用於calc下不透明度)

void main() 
{ 
    lowp vec4 fColor = texture2D(texture, texCoordOut); 
    gl_FragColor = vec4(fColor.xyz, fColor.w * colorOut.a); 
} 

VBO設置

glGenBuffers(1, &_vertexBuf); 
    glGenBuffers(1, &_indiciesBuf); 
    glGenVertexArraysOES(1, &_vertexArray); 

    glBindVertexArrayOES(_vertexArray); 

    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuf); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(TDSEVertex)*12000, &vertices[0].x, GL_DYNAMIC_DRAW); 
    glEnableVertexAttribArray(GLKVertexAttribPosition); 
    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(TDSEVertex), BUFFER_OFFSET(0)); 

    glEnableVertexAttribArray(GLKVertexAttribTexCoord0); 
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(TDSEVertex), BUFFER_OFFSET(8)); 

    glEnableVertexAttribArray(GLKVertexAttribColor); 
    glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(TDSEVertex), BUFFER_OFFSET(16)); 

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indiciesBuf); 
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(ushort)*12000, indicies, GL_STATIC_DRAW); 

    glBindVertexArrayOES(0); 

更新代碼

/* 

     Here it cycles through all the sprites, gets their vert info (includes coords, texture coords, and color) and adds them to this giant array 
     The array is of... 
     typedef struct{ 
      float x, y; 
      float tx, ty; 
      float r, g, b, a; 
     }TDSEVertex; 
    */ 

    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuf); 
    //glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices[0])*(start), sizeof(TDSEVertex)*(indicesCount), &vertices[start]); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(TDSEVertex)*indicesCount, &vertices[start].x, GL_DYNAMIC_DRAW); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 

渲染代碼

GLKTextureInfo* textureInfo = [[TDSETextureManager sharedTextureManager].textures objectForKey:textureName]; 
    glBindTexture(GL_TEXTURE_2D, textureInfo.name); 

    glBindVertexArrayOES(_vertexArray); 
    glDrawElements(GL_TRIANGLE_STRIP, indicesCount, GL_UNSIGNED_SHORT, BUFFER_OFFSET(start)); 
    glBindVertexArrayOES(0); 

下面有在400只小精靈(三角形800 800 +退化三角形)的屏幕截圖,得到不透明分層作爲紋理被移動的一個想法... 再次,我應該注意的是,一個VBO正在創建和發送每個紋理,所以我綁定,然後每幀只繪製兩次(因爲只有兩個紋理)。

screenshot showing layering of sprites

很抱歉,如果這是壓倒性的,但在這裏它的我的第一篇,想徹底。 任何幫助將不勝感激。

PS,我知道我可以使用Cocos2D而不是從頭開始編寫所有的東西,但是在那兒玩的樂趣(和學習)?!

UPDATE#1 當我我的片段着色器切換到僅是

gl_FragColor = texture2D(texture, texCoordOut); 

它到達802個在精靈50fps的(4804三角形包括退化三角形),儘管設置子畫面不透明度丟失..任何建議到如何仍然可以在我的着色器中處理不透明度而不以1/4的速度運行?

UPDATE#2 因此,我放棄了GLKit的View和View控制器,並編寫了一個從AppDelegate加載的自定義視圖。 902不透明的精靈& 60fps的透明度。

+0

與其使用OpenGL ES Performance Detective,我更喜歡使用帶有OpenGL ES分析器和OpenGL ES驅動程序工具的儀器。分析器通常會指出更細微的渲染問題,並且驅動程序可以在Tiler(頂點側)和Renderer(片段側)爲您提供百分比負載,以驗證您的瓶頸位置。另外嘗試運行Time Profiler對此。這看起來比應該慢,因爲我把A4的基準定爲1。使用VBOs和簡單的陰影,每秒800萬個三角形,或以60 FPS在屏幕上約30000個三角形。 – 2012-03-20 20:07:13

+0

感謝回覆@BradLarson。儘管有些事情我不太瞭解... Renderer Utiliz:99%,Tiler Utilz:8%,Device Utilz:99%,我儘可能使用Analyzer和Driver。思考? Analyzer中唯一突出的是多餘的調用,但絕大多數來自glView(綁定幀緩衝區等)。 Time Profilier顯示83%來自我綁定和更新VBO(在更新中完成)並繪製。你認爲使用glView是問題的一部分嗎?我認爲這是transp層(即時貼上截圖和我更新的代碼)。謝謝。 – yiannis 2012-03-20 21:23:27

+0

如果您的渲染器利用率確實爲99%,而您的鋪磚機爲8%,那麼顯然您的填充率受限,而不是幾何形狀受限。優化三角形和你的VBO不會對你有什麼好處,你需要專注於繪製更少的像素或更快地繪製像素。你已經在上面的場景中進行了很多混合,[來自經驗](http://stackoverflow.com/q/6051237/19679)如果一堆混合對象堆積在一起,我知道這是非常昂貴的彼此頂部。您可以渲染不透明區域並寫入深度緩衝區,然後在混合半透明區域時從中讀取。 – 2012-03-21 14:43:29

回答

1

晴繁雜的思緒......

如果你是三角形的限制,試着從GL_TRIANGLE_STRIP切換到GL_TRIANGLES。您仍然需要指定完全相同數量的索引 - 每個四個索引相同數量 - 但GPU從未發現四邊形之間的連接三角形退化(即,從不必將它們轉換爲零像素)。您需要進行配置以查看您是否最終支付了不再隱式共享邊緣的成本。

您還應該縮小頂點的佔位面積。我敢想象你可以將x,y,tx和ty指定爲16位整數,將你的顏色指定爲8位整數,而在渲染時不會有明顯變化。這樣可以將每個頂點的佔用空間從32個字節(八個組件,每個四個字節的大小)減少到12個字節(四個雙字節值加上四個單字節值,不需要填充因爲所有內容都已經對齊)那裏63%的內存帶寬成本。

由於你實際上似乎是填充率有限,你也應該考慮你的源紋理。您可以通過修改字節大小來進行任何操作,這將直接幫助紋理提取並填充速率。

它看起來像你使用藝術是有意識的像素,所以切換到PVR可能不是一種選擇。也就是說,人們有時並未意識到PVR紋理的全部好處;如果切換到每像素模式4位,那麼您可以將圖像縮放爲寬度的兩倍和高度的兩倍,以減少壓縮僞影,並且仍然只支付每個源像素上的16位,但可能會得到比16 bpp RGB紋理更好的亮度範圍。

假設您目前使用32 bpp紋理,至少應該使用任何提供的硬件模式來查看普通16 bpp RGB紋理是否足夠(尤其是如果1位alpha和每個顏色通道5位適合您的藝術品,因爲這樣會減少9位色彩信息,同時將帶寬成本降低50%)。

它也看起來像你上傳索引每一幀。僅當您向場景中添加額外對象時,或者上次上傳的緩衝區比所需的大得多時才上傳。您可以將傳遞給glDrawElements的計數限制爲在沒有重新上傳的情況下削減對象。你還應該檢查你是否通過上傳頂點到VBO來獲得任何東西,然後如果他們只是改變每一幀,就重新使用它們。從客戶端內存直接提供它們可能會更快。

+0

謝謝@Tommy。因爲這是從iPhone完成的,我不認爲我可以直接從我的代碼中提供頂點(我假設使用glBegin)。我確實嘗試了GL_TRIANGLES方法,雖然它減少了許多三角形,但它並沒有做太多的工作。我想使用PVR,但是我一直在使用紋理工具。我確實將紋理尺寸從37k縮小到了9k,但仍然沒有區別。我會嘗試將這些圖像轉換爲16bpp,但它只是如此痛苦!儘管如此,再次感謝您的努力。 – yiannis 2012-03-21 05:50:10

+0

使用VBO是直接提供數組的可選替代方案。你必須提供偏移量的原因就像它們是一個指向'glVertexAttribPointer'的指針一樣,只允許你給它一個指向某些客戶端內存的指針。我的建議是,你可以嘗試去掉'_vertexBuf' VBO和相應的'glBufferData'調用。您應該能夠在運行時轉換爲16 bpp; Apple曾經在一些示例項目中提供了一個'Texture2D'類,但我猜想現在GLKit已經在現場消失了...... – Tommy 2012-03-21 18:01:55