Игра для iPhone 2d тени

Мы находимся в процессе создания игры для iPhone с использованием cocos2d. Мы пытаемся наложить несколько спрайтов друг на друга и заставить их отбрасывать тени.

Прямо сейчас тени отображаются как спрайты, которые по большей части работают нормально. Но мы хотим, чтобы тени попали в ближайший слой.

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

И вот что мы имеем на данный момент:

По сути, мы хотим, чтобы спрайт отображал только ту часть тени, которая находится на той же глубине, что и z-буфер.

Мы поиграли с glDepthFunc а также GL_DEPTH_TEST но ничего не работает.

Вот как мы рендерим теневой спрайт (в подклассе CCSprite):

- (void)draw {

    glDisable( GL_BLEND );

    glEnable( GL_DEPTH_TEST );
    glDepthFunc( GL_LESS );

    glDepthMask( GL_FALSE );
    [super draw];
    glDepthMask( GL_TRUE );

    glDisable( GL_DEPTH_TEST );

    glEnable( GL_BLEND );
}

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

Все спрайты, которые не являются тенями, используют glDepthMask( GL_TRUE ) и мы очищаем буфер глубины на каждом кадре.

Любая помощь приветствуется!

1 ответ

Решение
glDepthFunc(GL_LESS)

на самом деле значение по умолчанию; это означает "рисовать пиксель, только если объект, находящийся в данный момент в буфере глубины, находится дальше". Если бы вы хотели точно равного, вы бы использовали glDepthFunc(GL_EQUAL), но на практике вы получите все виды странностей округления, если вы сделаете это.

Предполагая, что вы можете использовать значения глубины для этой цели, если у вас есть десять объектов, я бы посоветовал вам:

  1. установите glClearDepth в 0, прежде чем glClear; это заполнит буфер глубины ближайшим сохраняемым значением, чтобы при нормальной буферизации глубины больше ничего не рисовалось.
  2. отключите глубину и нарисуйте тени так, чтобы они падали на заднюю плоскость; в этот момент ваш буфер глубины будет по-прежнему заполнен ближайшим возможным значением.
  3. включите тест глубины, но установите для glDepthFunc значение GL_ALWAYS. Затем нарисуйте все ваши сплошные прямоугольники в обратном порядке с соответствующими значениями глубины.
  4. установите glDepthFunc в GL_LESS и нарисуйте тени, которые должны падать на другие спрайты, каждый из которых расположен дальше, чем спрайт, с которым они связаны, но перед спрайтом позади.

К тому времени, как вы перейдете к шагу 4, вы будете иметь правильную информацию о глубине везде, где был нарисован спрайт, и у вас будет максимально возможное значение, установленное независимо от фона. Поэтому обычное тестирование глубины будет работать с промежуточными тенями - они будут рисовать поверх всего, что нарисовано на шаге 3, но не поверх всего, что нарисовано на шаге 2.

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

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

Другие вопросы по тегам