我使用OpenGL ES爲iPhone 4S上的每一幀繪製了2560個非常纖細的多邊形。問題是,我得到30左右的幀速率,這對我的口味來說不夠流暢。我認爲它應該比這更快。iPhone 4S,OpenGL ES似乎太慢了。怎麼了?
是嗎?
請幫我找出可以改進的地方。
更新:我在主線程渲染。有沒有關於執行渲染操作的線程的建議?
有點背景: 我試圖做一個平穩滾動(目標是60 FPS)在iPhone視圖座標尺寸320×200的波形,視網膜顯示屏上,這樣640x400像素的。 我的測試設備是iPhone 4S。使用iOS 6和6.1,我可以通過普通的UIKit繪圖操作輕鬆實現這一點。但是,由於我將設備更新爲iOS 7,速度變慢了,所以我決定使用OpenGL ES,因爲我讀了很多次,它允許更快的2D繪圖。
我實現了用OpenGL ES 2.0繪製波形,但現在它只比UIKit稍快一些。和UIKit一樣,速度在很大程度上取決於正在繪製的像素數量,這讓我想知道發生了什麼。
波形是由條形/矩形組成的,每一個都是正好1個像素的寬度。我爲每個像素列繪製兩個條,每個條都由兩個多邊形組成,這意味着我爲每個幀繪製1280個條或2560個多邊形。多邊形非常纖細。它們每個最多隻有1個像素寬。我認爲用OpenGL ES以60FPS繪製這應該不成問題。
我繪製一個杆是這樣的:
- (void) glFillRect: (Float32)x0 : (Float32)y0 : (Float32)x1 : (Float32)y1 {
glEnableVertexAttribArray(GLKVertexAttribPosition);
GLfloat vertices[8];
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, vertices);
GLfloat* vp = vertices;
*vp++ = x0; *vp++ = y0;
*vp++ = x1; *vp++ = y0;
*vp++ = x0; *vp++ = y1;
*vp++ = x1; *vp++ = y1;
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(GLKVertexAttribPosition);
}
的代碼調用上述方法如下。 _maxDrawing
和_ avgDrawing
是我的效果,這是在應用程序啓動時由這樣的:
_maxDrawing = [[GLKBaseEffect alloc] init];
_maxDrawing.useConstantColor = GL_TRUE;
_maxDrawing.constantColor = GLKVector4Make(0.075f, 0.1f, 0.25f, 1.0f);
使得我的繪圖與我的視圖的視圖座標,座標的OpenGL ES排隊我稍後調整投影矩陣,其,afaik,是2D繪圖的標準方法。
[_maxDrawing prepareToDraw];
x_Cu = [self transformViewXToWaveformX:rect.origin.x];
for (Float32 x_Vu = rect.origin.x; x_Vu < viewEndX_Vu; x_Vu += onePixelInViewUnits) {
x_Cu += onePixelInContentUnits;
if (x_Cu < 0 || x_Cu >= waveformEndX_Cu) {
continue;
}
SInt64 frameIdx = (SInt64) x_Cu;
CBWaveformElement element;
element = [self.dataSource getElementContainingFrame:frameIdx];
prevMax = curMax;
curMax = futureMax;
futureMax = element.max;
smoothMax = prevMax * 0.25 + curMax * 0.5 + futureMax * 0.25;
if (smoothMax < curMax)
smoothMax = curMax;
Float32 barHeightHalf = smoothMax * heightScaleHalf;
Float32 barY0 = viewHeightHalf - barHeightHalf;
Float32 barY1 = viewHeightHalf + barHeightHalf;
[self glFillRect: x_Vu : barY0 : x_Vu + onePixelInViewUnits : barY1];
}
[_avgDrawing prepareToDraw];
x_Cu = [self transformViewXToWaveformX:rect.origin.x];
for (Float32 x_Vu = rect.origin.x; x_Vu < viewEndX_Vu; x_Vu += onePixelInViewUnits) {
x_Cu += onePixelInContentUnits;
if (x_Cu < 0 || x_Cu >= waveformEndX_Cu) {
continue;
}
SInt64 frameIdx = (SInt64) x_Cu;
CBWaveformElement element;
element = [self.dataSource getElementContainingFrame:frameIdx];
Float32 barHeightHalf = element.avg * heightScaleHalf;
Float32 barY0 = viewHeightHalf - barHeightHalf;
Float32 barY1 = viewHeightHalf + barHeightHalf;
[self glFillRect: x_Vu : barY0 : x_Vu + onePixelInViewUnits : barY1];
}
當我拿出所有的OpenGL調用,一幀的執行時間爲1毫秒左右,這意味着理論上可以上升到1000 FPS。所有其他時間(大約33ms)都花費在繪圖上。
您需要爲動畫使用着色器和矩陣。對不起,但在glDrawArrays看起來之前計算頂點... – SAKrisT
如果我讀了這個權利,你正在爲這些盒子中的每一個做一個'glDrawArrays()'調用?這將在通話中引入很多開銷。相反,你可以創建一個動態更新的VBO與所有的頂點,並繪製每幀一次? –
@BradLarson,這提供了8倍的性能增益。謝謝!!! –