Сохраняйте самые большие значения из источника И назначения (побитовое ИЛИ) в OpenGL ES 2.0.

Позвольте мне немного объяснить название. В буфере кадра у меня есть несколько значений цвета (для простоты я буду ссылаться только на один цветовой канал в двоичном формате, например, 00000001 в конкретном пикселе). Затем в этом конкретном значении я собираюсь написать новое значение. OpenGL должен проверять входящее значение и значение, которое уже существует в этом пикселе, и сохранять максимум обоих. Другими словами, я хочу, чтобы он выполнял ПОБИТОВОЕ ИЛИ между входящим и существующим значением. Таким образом, если существующее значение равно 00000001, а входящее — 00000010, то результатом должно быть 00000011.

Я думаю, что в OpenGL ES 1.1 это было легко достигнуто с помощью функции glLogicOp (http://www.opengl.org/sdk/docs/man/xhtml/glLogicOp.xml). Но это НЕ поддерживается в OpenGL ES 2.0 (ПОЧЕМУ, ПОЧЕМУ, ПОЧЕМУ они его удалили?? :( ), и я не могу придумать функцию смешивания, которая может добиться аналогичного результата (я думаю, что это невозможно с помощью смешивания). Должен ли я использовать буфер трафарета или другой трюк для достижения моей цели?

Можете ли вы описать шаги для этого?

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

Заранее спасибо.


person Summon    schedule 05.01.2012    source источник
comment
Обратите внимание на побитовые операции в шейдерах, они не поддерживаются в шейдерах OpenGl ES. Им требуется версия #130. Ваше здоровье   -  person Maurizio Benedetti    schedule 05.01.2012
comment
@MaurizioBenedetti - Почему же тогда PowerVR перечисляет логические операторы как поддерживаемые в шейдерах OpenGL ES на своем оборудовании (используемом в текущих устройствах iOS)? imgtec.com/powervr/insider/docs/   -  person Brad Larson    schedule 05.01.2012


Ответы (3)


Я думаю, вам придется использовать шейдер для этого.

1) Создайте два renderTargets[2], которые будут использоваться для обмена с swapIndex.

2) Рендеринг в один renderTarget[swapIndex] и использование другого renderTarget[1-swapIndex] в качестве эталонной текстуры, из которой вы будете сэмплировать в шейдере GLSL.

3) В шейдере фрагмента (так называемого пикселя) вы должны взять образец из своей текстуры (он же renderTarget [1-swapIndex]) и установить для «gl_FragColor» значение max (texture, someColor).

4) Переверните swapIndex {swapIndex = 1-swapIndex;} и начните сначала.

person zezba9000    schedule 05.01.2012
comment
Спасибо, @zezba9000! Что касается шага 3, как я могу выполнить побитовую логическую операцию ИЛИ? Знаете ли вы или кто-либо другой более быстрый подход с точки зрения кода (меньше кода) и производительности? В OpenGL ES 1.1 это можно было сделать одной строкой кода, что, на мой взгляд, намного быстрее. - person Summon; 05.01.2012

Должен признаться, я не был так ясен в своем вопросе. В любом случае, я уточню проблему и представлю ее решение здесь.

У меня есть много разных произвольных форм (пользователь может создать столько из них, сколько захочет, и безумно деформировать их), и я хочу разработать метод для определения по цвету пикселя на экране, сколько фигур выбрал пользователь. (пользователь только что коснулся этого пикселя).

Итак, я раскрашиваю формы, скажем, с помощью идентификаторов цветов. Я работаю на двоичном уровне: первая фигура на экране имеет идентификатор цвета 00000001, вторая фигура имеет идентификатор 00000010 и так далее. Итак, с помощью байта (скажем, в красном канале) я могу хранить до 8 различных цветовых идентификаторов. Максимальное количество фигур — 32, если я использую формат RGBA8888.

Алгоритм, который я первоначально разработал, выполнял смешивание между идентификатором исходного цвета и идентификатором целевого цвета с помощью glBlendFunc(GL_ONE, GL_ONE), и все, казалось, работало нормально. То есть, если коснулся пиксель цвета 00010101, то это означало, что были затронуты первая, третья и пятая фигуры. НО, есть некоторые невыпуклые формы (если это правильное слово для складных фигур), которые может создать пользователь. В этом случае, если фигура с идентификатором цвета 00000001 свернута пользователем, то перекрывающиеся пиксели получат идентификатор 00000010, потому что фигура записывает 00000001, когда она впервые рисуется в буфере кадра, а затем перекрывающиеся пиксели той же формы добавляют еще 00000001 из-за к смешиванию.

Итак, если бы я каким-то образом мог сделать ПОБИТОВОЕ ИЛИ (НЕ логическое, как я изначально упомянул в своем вопросе) между идентификаторами цвета, которые были записаны в фреймбуфере, проблема была бы решена. Действительно, это относится к OpenGL ES 1.1 при использовании функции glLogicOp(GL_OR). К сожалению, это недоступно в OpenGL ES 2.0, и снова необходимо создать один шейдер, еще один проход и т. д., что я считаю излишним и сложным в обслуживании.

Решение для OpenGL ES 2.0 таково:

  1. Очистите цвет RenderTexture B до glClearColor(0,0,0,0)
  2. ДЛЯ каждой формы
  3. Очистите цвет Rendertexture A до glClearColor(0,0,0,0)
  4. Нарисуйте фигуру на Rendertexture A, используя фрагментный шейдер, который записывает в качестве цвета его идентификатор цвета.
  5. Смешайте с GL_ONE, GL_ONE Rendertexture A с содержимым Rendertexture B
  6. КОНЕЦ ДЛЯ
  7. RenderTexture B содержит всю необходимую нам информацию.
  8. Когда пользователь прикасается к экрану, сэмплируйте соответствующий пиксель из RenderTexture B с помощью glReadPixel и определяйте из двоичного кода затронутые фигуры.

Лучший

person Summon    schedule 06.01.2012

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

Так или иначе:

Пункт 1: я на 100% уверен, что вы не можете выполнять побитовое и/или/сдвиг в шейдерах, так как мне пришлось потратить около 2 недель программирования из-за этой оплошности только в прошлом месяце. :) :)

Пункт 2: Посмотрите эту статью в Википедии о GLSL (раздел Операторы):

Побитовые операторы были добавлены в версии 1.30.

О. Если вы попытаетесь добавить в свой шейдер версию #130, он не скомпилируется. B. Если вы попытаетесь добавить побитовую операцию, такую ​​как A & B (обратите внимание на одиночное &), A | B, A ‹‹ 2, B >> 2 и т. д., он не будет компилироваться.

Почитав разные книги/форумы/SDK, я нашел такое же подтверждение.

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

Маурицио Бенедетти

person Maurizio Benedetti    schedule 06.01.2012
comment
Спасибо, что указали на это @Maurizio. Я это уже знал. Я думаю, что побитовые операции поддерживаются только на самых последних графических процессорах для настольных ПК, и на мобильных устройствах об этом пока не может быть и речи. Спасибо, в любом случае - person Summon; 06.01.2012