2010-10-17 5 views
2

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

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

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

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

В основном мы хотите, чтобы спрайт отображал только часть тени, которая находится на той же глубине, что и 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.

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

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

+0

Спасибо! Используя ваш подход, я смог получить результат, который мы искали, к сожалению, за счет частоты кадров. Теперь, когда он работает по назначению, я могу начать искать способы оптимизации производительности. – aegzorz