2010-07-29 33 views
2

我想在iPhone上用OpenGL ES畫點精靈。它可能有很多(1000)和64像素寬(也許這是我的問題 - 有沒有限制,或我可以使用太多的內存?)爲什麼glClear()在iPhone上的點精靈速度緩慢?

我正在使用CADisplayLink到時間框架。會發生什麼情況是,當點數過高或點的大小太大時,第一個gl繪圖函數往往會延遲或失速。在我的例子中,glClear()是第一個繪圖函數,它可以從0.02秒到0.2秒的任何地方運行。如果我只是註釋掉glClear,那麼glDrawArrays就變成了慢速函數(否則它運行得非常快)。

這個例子是我已經剝離我的代碼,以隔離問題。它只是在同一個地方畫出一堆點紋,沒有紋理。我使用VBOs來存儲所有精靈數據(位置,顏色,大小)。這個例子看起來似乎有些過火,但我當然有意在稍後修改這些數據。

這是視圖的初始化函數(減去樣板GL設置):

glDisable(GL_DEPTH_TEST); 
glDepthMask(GL_FALSE); 

glDisable(GL_LIGHTING); 
glDisable(GL_FOG); 

glEnable(GL_TEXTURE_2D); 
glEnable(GL_BLEND); 

glBlendEquationOES(GL_FUNC_ADD_OES); 

glClearColor(0.0, 0.0, 0.0, 0.0); 

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE); 
glEnable(GL_POINT_SPRITE_OES); 

glEnableClientState(GL_VERTEX_ARRAY); 
glEnableClientState(GL_POINT_SIZE_ARRAY_OES); 
glEnableClientState(GL_COLOR_ARRAY); 

glBlendFunc(GL_SRC_ALPHA, GL_ONE); 

glEnable(GL_POINT_SMOOTH); 

glGenBuffers(1, &vbo);     // vbo is an instance variable 
glBindBuffer(GL_ARRAY_BUFFER, vbo); 

glMatrixMode(GL_PROJECTION); 
glOrthof(0.0, [self frame].size.width, 0.0, [self frame].size.height, 1.0f, -1.0f); 
glViewport(0, 0, [self frame].size.width, [self frame].size.height); 
glMatrixMode(GL_MODELVIEW); 

glTranslatef(0.0f, [self frame].size.height, 0.0f); 
glScalef(1.0f, -1.0f, 1.0f); 

這是渲染功能:

- (void)render 
{ 
    glClear(GL_COLOR_BUFFER_BIT); // This function runs slowly! 

    int pointCount = 1000; 

    // fyi... 
    // typedef struct { 
    // CGPoint point; 
    // CFTimeInterval time; 
    // GLubyte r, g, b, a; 
    // GLfloat size; 
    // } MyPoint; 

    glBufferData(GL_ARRAY_BUFFER, sizeof(MyPoint)*pointCount, NULL, GL_DYNAMIC_DRAW); 
    MyPoint * vboBuffer = (MyPoint *)glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES); 

    for (int i = 0; i < pointCount; i++) { 
     vboBuffer[i].a = (GLubyte)0xFF; 
     vboBuffer[i].r = (GLubyte)0xFF; 
     vboBuffer[i].g = (GLubyte)0xFF; 
     vboBuffer[i].b = (GLubyte)0xFF; 
     vboBuffer[i].size = 64.0; 
     vboBuffer[i].point = CGPointMake(200.0, 200.0); 
    } 

    glUnmapBufferOES(GL_ARRAY_BUFFER); 

    glPointSizePointerOES(GL_FLOAT, sizeof(MyPoint), (void *)offsetof(MyPoint, size)); 
    glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(MyPoint), (void *)offsetof(MyPoint, r)); 
    glVertexPointer(2, GL_FLOAT, sizeof(MyPoint), (void *)offsetof(MyPoint, point)); 

    glDrawArrays(GL_POINTS, 0, pointCount); 

    [context presentRenderbuffer:GL_RENDERBUFFER_OES]; 
} 

爲什麼glClear功能停滯?它不僅延遲隨機數量 - 取決於點數或大小,它傾向於隨機延遲相同的時間間隔(例如0.015秒,0.030秒,0.045秒等)。我注意到的另外一件奇怪的事是,如果我切換到glBlendMode(GL_ZERO,GL_ONE),它運行得很好(儘管這不會是我之後的視覺效果)。其他glBlendMode值也會改變速度 - 通常情況下會更好。這讓我覺得這不是一個記憶問題,因爲這與VBO無關(對吧?)。

我承認我在OpenGL上有點新,可能會誤解有關VBO或其他東西的基本概念。任何幫助或指導,非常感謝!

回答

0

如果glClear()很慢,您可以嘗試繪製一個完全覆蓋視口區域的大型空白四邊形。

+0

我確實嘗試過,但它看起來並不像glClear那麼慢。它似乎是第一個gl繪圖函數。如果我擺脫glClear並繪製一個空白四邊形,它只會減慢glDrawArrays()。 – 2010-07-30 00:50:34

0

您是否使用同步(或啓用了它?)。您看到的延遲可能與CPU和GPU並行運行有關,因此測量各個GL調用的時間沒有意義。

如果您使用的是VSync(或者GPU負載過重),SwapBuffers調用中可能會有一些延遲,因爲某些驅動程序會導致繁忙循環等待VBlank。

但首先考慮你不應該爲每個GL調用調用時間,因爲大多數GL調用只是設置GPU的某種狀態或寫入命令緩衝區,所以命令執行是異步執行的。

+0

這對於不對GL個別GL調用進行計時是有意義的 - 這可能解釋了爲什麼它不一致地運行緩慢。不過,這個問題正在導致FPS的大幅下降(有時低至15fps),所以它不僅僅是測量執行時間的錯誤。 我沒有明確啓用或禁用VSync。這是我應該做的事嗎? – 2010-07-31 17:09:52

相關問題