2010-01-27 13 views
16

Estoy trabajando en un juego en el que quiero crear sombras bajo una serie de sprites en una grilla. Las sombras son más grandes que los propios sprites y los sprites están animados (es decir, se mueven y rotan).¿Es posible lograr MAX (As, Ad) openGL blending?

No puedo simplemente renderizarlos en el sprite png, o las sombras se superpondrán a los sprites adyacentes.

Tampoco puedo simplemente poner sombras en una capa inferior por sí mismas, porque cuando se superponen, crearán bandas oscuras en su intersección.

Estos sprites están animados, por lo que no es posible renderizarlos en masa.

Básicamente, quiero que las sombras de los sprites se combinen de modo que se maximicen en una opacidad establecida. Ejemplo:

enter image description here

creo que esto es equivalente a una mezcla OpenGL de (RS, GS, BS, Max (As, Ds)), donde i no me importa acerca de R, G, y B , ya que siempre será del mismo color en src y dst.

Sin embargo, este no es un modo de fusión OpenGL válido. ¿Hay alguna manera fácil de lograr esto, especialmente en cocos2d-iphone?

Sería capaz de aproximar esto haciendo opacos a los sprites de sombra, luego aplicarlos a un sprite padre y hacer que el sprite padre tenga un 40% de opacidad. Sin embargo, de la forma en que funciona el cocos2d, esto solo establece la opacidad de cada niño en un 40%, en lugar de la imagen de sprite combinada, que da como resultado la misma franja.

Respuesta

16

OK, creo que después de mucha investigación, me doy cuenta del error en mi forma de pensar.

En primer lugar, hay una forma de hacer la mezcla OpenGL de Max Alpha, y eso es usando glBlendEquations. Usted tendría que modificar el método de dibujo para hacer esto (y hacer algo nuevo atributo para un textureNode para cambiar entre estos métodos), y el uso de cualquiera de éstos:

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

El primero utiliza max() para RGBA, mientras el segundo usa adición estándar para RGB y max() para alfa.

Ahora, el problema es que cada sprite, y de los niños, en el orden z, son atraídos a la pantalla . Esto significa que, después de dibujar la primera sombra, es parte del buffer de la pantalla principal. En otras palabras, se cambia su opacidad, y con la mezcla máxima() y un fondo opaco estándar, ahora está pintada en el fondo, por lo que cuando dibuje la siguiente sombra, hará max (As, 1) que es 1, porque el fondo es opaco Entonces no logro la mezcla que quiero. Sería "útil" si mi fondo fuera transparente, pero luego no podría aplicar ningún fondo "detrás" de eso, solo podemos agregar al búfer.

Podría dibujar las sombras primero, usando la combinación máxima() y luego hacer una {ONE_MINUS_DST_ALPHA, DST_ALPHA} glBlend. Esta es una solución correcta, pero tengo otros problemas que dificultan esto.

Ahora, la solución real, finalmente me doy cuenta, es usar una RenderTexture para renderizar las sombras en un buffer separado antes de aplicarlas al fondo. Esto podría tener implicaciones en el rendimiento, así que veremos a dónde va esto.

Actualización:

OK, tengo una solución de trabajo ahora.

Curiosamente, terminé necesitando esta solución después de todo, porque en mi caso particular, la formación de bandas no era lo suficientemente notable como para justificar el esfuerzo, sin embargo esta es la solución que parecía hacer lo que quería:

  1. Primero dibuja un 0% black alpha png en toda la pantalla. (No sé si esto es necesario. No sé cuál es el valor alfa predeterminado de la pantalla).

  2. Dibuja las sombras en la pantalla usando glEquationSeperateOES(GL_ADD, GL_MAX_ENT) y glBlend(GL_ONE, GL_ONE). Esto combinará todas las sombras como se describe, tomando el máximo() de los alfas.

    • Debido a que está la composición de negro, que es equivalente a usar glBlendEquationOES(GL_MAX_ENT). (X + 0 == max (X, 0))

    • glBlend(GL_ZERO, GL_ONE) eliminará la necesidad del paso 1, o al menos el requisito de que esa capa sea 0% negra. GL_ZERO esencialmente lo fuerza a ser 0% negro.

  3. Dibuje el suelo, que será más las sombras, pero el uso glBlend(ONE_MINUS_DST_ALPHA, DST_ALPHA). Esto produce exactamente los mismos resultados que si agregara las sombras al piso con glBlend(SRC_ALPHA, ONE_MINUS_SRC_ALPHA); sin embargo, si lo hizo de esta manera, no sería posible combinar las sombras (lea por qué en la parte superior de la respuesta).

  4. ¡Ya ha terminado! Lo bueno de este método es que los sprites de sombra se pueden animar como de costumbre, sin tener que llamar "visitar" en una textura de representación separada.

El resto:

que también modificó CocosNode que me permita agregar una sombra a una capa, que enlaza con otra CocosNode. De esta forma, la sombra se representa como un elemento secundario del piso (o el elemento de fondo negro 0% para la combinación de sombras), pero está vinculada a otro Nodo de Cocos. Cuando un objeto se mueve, si tiene una sombra, también actualiza la posición de las sombras. Esto me permite tener todas las sombras debajo de todos los objetos en la pantalla, y hacer que las sombras sigan automáticamente al objeto.

Disculpa por la respuesta larga. Tal vez mi solución es kludgy, pero parece funcionar muy bien.

+1

Gracias por dar seguimiento a su pregunta con una respuesta informativa! –

+0

gracias también! Esta información es prácticamente en ninguna otra parte. :) –

Cuestiones relacionadas