Хорошо, я думаю, что после долгих исследований я осознаю ошибку в своем мышлении.
Во-первых, есть способ сделать смешивание Max Alpha openGL, и для этого используется 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 для рендеринга теней в отдельный буфер перед применением их к фону. Это может повлиять на производительность, поэтому посмотрим, к чему это приведет.
Обновление:
ОК, у меня есть рабочее решение.
Как ни странно, мне в конце концов не понадобилось это решение, потому что в моем конкретном случае полосатость была недостаточно заметна, чтобы оправдать усилия, однако это решение, которое я придумала, казалось, делало то, что я хотел: 1024 *
Сначала нарисуйте 0% черный альфа-PNG на весь экран. (Я не знаю, если это необходимо. Я не знаю, какова стандартная альфа экрана).
Нарисуйте тени на экране, используя 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. Когда спрайт перемещается, если у него есть тень, он также обновляет положение теней. Это позволяет мне располагать все тени под всеми объектами на экране, и чтобы тени автоматически следовали за объектом.
Извините за длинный ответ. Может быть, мое решение клудгое, но, похоже, оно отлично работает.