Почему glClear () так медленно работает с точечными спрайтами на iPhone? - PullRequest
2 голосов
/ 30 июля 2010

Я пытаюсь рисовать точечные спрайты с помощью OpenGL ES на iPhone.Возможно, их может быть очень много (1000) и шириной до 64 пикселей (может, в этом моя проблема - есть ли ограничение или я могу использовать слишком много памяти?)

Я использую CADisplayLinkвремя кадры.Что происходит, так это то, что первая функция рисования gl имеет тенденцию задерживать или останавливаться, когда либо количество точек слишком велико, либо когда размер точек слишком велик.В моем примере ниже, glClear () - первая функция рисования, и ее запуск может занять от 0,02 до 0,2 секунды.Если я просто закомментирую glClear, glDrawArrays станет медленной функцией (в противном случае она работает очень быстро).

В этом примере я сократил свой код, чтобы изолировать проблему.Он просто рисует кучу точечных спрайтов без текстуры в одном месте.Я использую VBO для хранения всех данных спрайта (позиция, цвет, размер).Для примера это может показаться излишним, но, конечно, у меня есть намерения изменить эти данные позже.

Это функция инициализации представления (за исключением настройки 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 или других вещах.,Любая помощь или руководство с благодарностью!

Ответы [ 2 ]

0 голосов
/ 30 июля 2010

Используете ли вы синхронизацию (или она включена?).Задержка, которую вы видите, может быть связана с тем, что CPU и GPU работают параллельно, поэтому измерение времени отдельных вызовов GL не имеет смысла.

Если вы используете VSync (или GPU сильно загружен), может быть некоторая задержка в вызове SwapBuffers, так как некоторые драйверы делают циклы занятости для ожидания VBlank.

Но сначала учтите, что вы НЕ должны синхронизировать отдельные вызовы GL, поскольку большинство вызовов GL просто устанавливают некоторое состояниеGPU или запись в буфер команд, выполнение команды происходит асинхронно.

0 голосов
/ 30 июля 2010

Если glClear() медленный, вы можете попробовать нарисовать большой пустой квад, который полностью покрывает область просмотра.

...