Я должен назвать glEnable и glDisable каждым разом, когда я тяну что-то?

Посмотрите на три (упрощенные) строки вашего кода:

for (int a = 0; a < arrays.length; a++) {

    for (int b = a+1; ...) {

        array[b]

Теперь, когда a находится в конце массива, и вы делаете b = a+1, b - после конца массив, и выполнение array[b] вызовет исключение.

Пример:

  • array = [1]
  • a = 0
  • b = 1
  • array [1] ??? вне границ
18
задан Welbog 29 April 2009 в 12:16
поделиться

4 ответа

«Это зависит».

Если все ваше приложение использует только одну комбинацию состояний включения / выключения, то непременно установите его в начале и начинайте.

Большинство реальные приложения должны быть смешаны, и тогда вы вынуждены вызывать glEnable () , чтобы включить некоторые конкретные состояния, делать вызовы отрисовки, затем glDisable () их снова, когда вы закончите «очистить сцену».

Отсюда вытекают сортировка состояний, отслеживание состояний и многие схемы оптимизации, поскольку переключение состояний иногда дорого обходится.

12
ответ дан 30 November 2019 в 07:34
поделиться

Практическое правило, которому меня учили, гласило, что почти всегда дешевле просто включать / отключать по желанию, чем проверять текущее состояние и изменять только при необходимости.

Тем не менее, Марк Ответ должен определенно работать.

0
ответ дан 30 November 2019 в 07:34
поделиться

Прежде всего, какую версию OpenGL вы используете? И какое поколение графического оборудования у вашей целевой группы? Знание этого поможет дать более правильный ответ. В моем ответе предполагается, что OpenGL 2.1.

OpenGL - это конечный автомат, означающий, что всякий раз, когда состояние изменяется, это состояние становится «текущим» до тех пор, пока программист снова не изменит его явно с новым вызовом API OpenGL. Существуют исключения из этого правила, например, вызовы массива состояний клиента, делающие текущий цвет вершины неопределенным. Но это исключения, которые определяют правило.

« один раз в начале приложения » не имеет особого смысла, потому что бывают случаи, когда вам нужно уничтожить свой контекст OpenGL, пока приложение Все еще работает. Я предполагаю, что вы имеете в виду только после каждого создания окна. Это работает для государства, которое вам не нужно менять позже. Пример: если все ваши вызовы отрисовки используют одни и те же данные массива вершин, вам не нужно впоследствии их отключать с помощью glDisableClientState.

Существует много состояний включения / выключения, связанных со старым конвейером фиксированных функций. Легкое искупление для этого: использовать шейдеры! Если вы нацелены на поколение карт, возраст которых не превышает пяти лет, это, вероятно, в любом случае имитирует конвейер фиксированной функции с шейдерами. Используя шейдеры, вы более или менее полностью контролируете то, что происходит на этапах преобразования и растеризации, и вы можете создавать свои собственные «состояния» с помощью униформ, которые очень дешевы для изменения / обновления.

Знание того, что OpenGL является конечный автомат, как я сказал выше, должен прояснить, что нужно стремиться к тому, чтобы изменения состояния были минимальными, пока возможно. Однако, скорее всего, есть другие вещи, которые влияют на производительность гораздо больше, чем включение / отключение вызовов состояния. Если вы хотите узнать о них, прочитайте.


Расход состояния не связан со старыми вызовами состояния фиксированной функции и который не является простым состоянием включения / выключения, может значительно различаться по стоимости. В частности, связывание шейдеров и связывание имен («имен» текстур, программ, объектов буфера) обычно довольно дорого. Вот почему многие игры и приложения использовали для сортировки порядка рисования своих сеток в соответствии с текстурой. Таким образом, им не нужно было связывать одну и ту же текстуру дважды. Однако в настоящее время то же самое относится и к шейдерным программам. Вы не хотите связывать одну и ту же шейдерную программу дважды, если вам это не нужно. Также, не все функции в конкретной версии OpenGL аппаратно ускоряются на всех картах, даже если производители этих карт утверждают, что они соответствуют OpenGL. Быть совместимым означает, что они следуют спецификации, а не то, что они обязательно должны эффективно выполнять все функции. В этом отношении следует помнить некоторые функции, такие как glHistogram и glMinMax из GL__ ARB __imaging.


Вывод: Если нет очевидной причины не использовать шейдеры! Это избавляет вас от множества ненужных вызовов состояния, поскольку вместо этого вы можете использовать униформу. Знаете, шейдеры OpenGL существуют уже около шести лет. Кроме того, издержки включения / выключения изменений состояния могут быть проблемой, но обычно есть много чего выиграть от оптимизации других более дорогих изменений состояния, таких как glUseProgram, glCompileShader, glLinkprogram, glBindBuffer и glBindTexture.

PS: OpenGL 3.0 удалил вызовы включения / выключения состояния клиента. Они неявно включены, поскольку рисовать массивы - единственный способ рисовать в этой версии. Немедленный режим был удален. Также были удалены вызовы gl..Pointer, так как на самом деле нужен только glVertexAttribPointer.

8
ответ дан 30 November 2019 в 07:34
поделиться

Базовый шаблон для такого рода вещей:

Есть поток, запускающий цикл, который обновляет переменную (например, индекс кадра анимированного изображения) и затем вызовы invalidate в поле, которое рисует изображение (а затем спит в течение некоторого периода времени). Недействительный объект поставит в очередь перерисовку поля.

В методе рисования поля прочитайте переменную и нарисуйте соответствующую рамку изображения.

Псевдокод (не полностью полный, но чтобы дать вам идею):

public class AnimatedImageField extends Field implements Runnable {

   private int currentFrame;
   private Bitmap[] animationFrames;

   public void run() {
     while(true) {
       currentFrame = (currentFrame + 1) % animationFrames.length;
       invalidate();
       Thread.sleep(100);
      }
    }

   protected void paint(Graphics g) {
      g.drawBitmap(0, 0, imageWidth, imageHeight, animationFrames[currentFrame], 0, 0);
    }
  }

Также обратите внимание, что здесь я использовал массив растровых изображений, но EncodedImage позволяет обрабатывать анимированный GIF как один объект и включает методы для получения определенных кадров.

РЕДАКТИРОВАТЬ: Для полноты: добавьте это в PopupScreen (как в ответе Фермина) ) или создайте свой собственный диалог, переопределив Screen напрямую.

void drawObject1(){
  glPushAttrib(GL_ENABLE_BIT);

  glEnable(GL_DEPTH_TEST);
  glEnable(GL_LIGHTING);    

  /* Isolated Region 1 */

  glPopAttrib();
}        

void drawObject2(){
  glPushAttrib(GL_ENABLE_BIT);

  glEnable(GL_FOG);
  glEnable(GL_GL_POINT_SMOOTH);    

   /* Isolated Region 2 */

  glPopAttrib();
}    

void drawScene(){
  drawObject1();
  drawObject2();
}

Хотя GL_LIGHTING и GL_DEPTH_TEST установлены в drawObject1, их состояние не сохраняется в drawObject2. В отсутствие glPushAttrib это было бы не так. Также обратите внимание, что нет необходимости вызывать glDisable в конце вызовов функции, glPopAttrib выполняет свою работу.

Что касается производительности, накладные расходы, связанные с вызовами отдельных функций glEnable / glDisable, минимальны. Если вам нужно обрабатывать много состояний, вам, вероятно, потребуется создать свой собственный менеджер состояний или сделать многочисленные вызовы glGetInteger ... и затем действовать соответственно. Дополнительные механизмы и поток управления могут сделать код менее прозрачным, сложным для отладки и более сложным в обслуживании. Эти проблемы могут затруднить другие, более плодотворные оптимизации.

Стек атрибуции может помочь в поддержании слоев абстракции и создании областей изоляции.

Страница руководства glPushAttrib

15
ответ дан 30 November 2019 в 07:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: