Игра для 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), но на практике вы получите все виды странностей округления, если вы сделаете это.
Предполагая, что вы можете использовать значения глубины для этой цели, если у вас есть десять объектов, я бы посоветовал вам:
- установите glClearDepth в 0, прежде чем glClear; это заполнит буфер глубины ближайшим сохраняемым значением, чтобы при нормальной буферизации глубины больше ничего не рисовалось.
- отключите глубину и нарисуйте тени так, чтобы они падали на заднюю плоскость; в этот момент ваш буфер глубины будет по-прежнему заполнен ближайшим возможным значением.
- включите тест глубины, но установите для glDepthFunc значение GL_ALWAYS. Затем нарисуйте все ваши сплошные прямоугольники в обратном порядке с соответствующими значениями глубины.
- установите glDepthFunc в GL_LESS и нарисуйте тени, которые должны падать на другие спрайты, каждый из которых расположен дальше, чем спрайт, с которым они связаны, но перед спрайтом позади.
К тому времени, как вы перейдете к шагу 4, вы будете иметь правильную информацию о глубине везде, где был нарисован спрайт, и у вас будет максимально возможное значение, установленное независимо от фона. Поэтому обычное тестирование глубины будет работать с промежуточными тенями - они будут рисовать поверх всего, что нарисовано на шаге 3, но не поверх всего, что нарисовано на шаге 2.
Вы как бы используете буфер глубины в качестве суррогатного трафарета, который старые айфоны не поддерживают.
Если вы не можете позволить себе использовать буфер глубины для этой задачи, то все, о чем я могу думать, - это проецировать тени как текстуры во втором текстурном блоке, используя первую для текстуры маски (или нет, если вы на самом деле рисуете прямоугольники, но я думаю, что вы, вероятно, нет) и делать один проход рендеринга на спрайт за каждую тень, которая падает на него. Это сносное решение?