Подтвердить что ты не робот

Можно ли достичь MAX (As, Ad) сглаживания openGL?

Я работаю над игрой, где хочу создать тени под серией спрайтов на сетке. Тени больше, чем сами спрайты, а спрайты анимированы (т.е. Перемещаются и вращаются).

Я не могу просто сделать их в sprite png, или тени будут перекрывать соседние спрайты.

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

Эти спрайты анимированы, поэтому их массово не представляется возможным.

В принципе, я хочу, чтобы тени спрайтов смешались друг с другом так, чтобы они максимизировались при заданной непрозрачности. Пример:

введите описание изображения здесь

Я считаю, что это эквивалентно смешиванию openGL (Rs, Gs, Bs, Max (As, Ds)), где мне действительно не нравятся R, G и B, так как это всегда будет одно и то же цвет в src и dst.

Однако это не допустимый режим смешивания openGL. Есть ли простой способ сделать это, особенно в cocos2d-iphone?

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

4b9b3361

Ответ 1

Хорошо, я думаю, что после долгих исследований я понимаю ошибку в своих мыслях.

Во-первых, есть способ сделать Max Alpha openGL blending, и это использует glBlendEquations. Вам нужно будет изменить метод draw для этого (и создать новый атрибут для функции textureNode для переключения между этими методами) и использовать любой из них:

 glBlendEquationOES( GL_MAX_EXT );
 glBlendEquationSeparateOES( GL_FUNC_ADD_OES, GL_MAX_EXT );

Первый использует max() для RGBA, а второй использует стандартное дополнение для RGB и max() для альфа.

Теперь проблема заключается в том, что каждый спрайт и его дети в z-порядке обращаются к экрану . Это означает, что после создания первой тени она является частью основного экранного буфера. Другими словами, его непрозрачность изменяется и с max() смешиванием и стандартным непрозрачным фоном, теперь она нарисована на фоне, поэтому, когда вы рисуете следующую тень, она будет делать max (As, 1), которая равна 1, потому что фон непрозрачен. Поэтому я не достигаю того, что хочу. Он "работал", если бы мой фон был прозрачным, но тогда я не мог применить какой-либо фон "позади", который мы можем добавить только в буфер.

Сначала я мог бы нарисовать тени, используя комбинацию max(), а затем выполнить {ONE_MINUS_DST_ALPHA, DST_ALPHA} glBlend. Это обходное решение, но у меня есть другие проблемы, которые затрудняют это.

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

Update:

ОК, теперь у меня есть рабочее решение.

Как ни странно, мне все-таки не понадобилось это решение, потому что в моем конкретном случае полоса не была достаточно заметной, чтобы оправдать усилия, однако это решение, которое я придумал, казалось, делал то, что я хотел:/p >

  • Сначала нарисуйте 0% черный альфа файл на весь экран. (Я не знаю, нужно ли это. Я не знаю, что такое альфа-версия по умолчанию на экране).

  • Нарисуйте тени на экране с помощью glEquationSeperateOES( GL_ADD, GL_MAX_ENT) и glBlend( GL_ONE, GL_ONE ). Это будет смешивать все тени вместе, как описано, принимая max() альфы.

    • Поскольку вы составляете композицию на черный, это эквивалентно использованию glBlendEquationOES( GL_MAX_ENT ). (X + 0 == max (X, 0))

    • glBlend( GL_ZERO, GL_ONE ) устраняет необходимость в шаге 1 или, по крайней мере, требование того, чтобы этот слой был 0% черного. GL_ZERO по существу заставляет его быть 0% черного.

  • Нарисуйте пол, который будет поверх теней, но используйте glBlend( ONE_MINUS_DST_ALPHA, DST_ALPHA ). Это приводит к точно таким же результатам, как если бы вы добавили тени к полу с помощью glBlend( SRC_ALPHA, ONE_MINUS_SRC_ALPHA ), однако, если бы вы сделали это таким образом, вы не смогли бы смешать тени вместе (прочитайте, почему в верхней части ответа).

  • Вы закончили! Самое приятное в этом методе заключается в том, что теневые спрайты можно анимировать, как обычно, без необходимости называть "посещение" на отдельной рендеринговой текстуре.

Остальное:

Я также модифицировал CocosNode, чтобы я мог добавить тень к слою, который ссылается на другой CocosNode. Таким образом, тень отображается как ребенок пола (или 0% черного фонового спрайта для смешивания теней), но связана с другим CocosNode. Когда спрайт перемещается, если он имеет тень, он также обновляет положение теней. Это позволяет мне иметь все тени под всеми объектами на экране, а тени автоматически следовать за объектом.

Извините за длинный ответ. Возможно, мое решение является kludgy, но, похоже, он отлично работает.