iphone graphics opengl-es cocos2d-iphone alphablending

iphone - ¿Es posible lograr MAX(como, Ad) openGL blending?



graphics opengl-es (1)

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).

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í mismos, 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 manera que se maximicen a una opacidad establecida. Ejemplo:

Creo que esto es equivalente a una mezcla OpenGL de (Rs, Gs, Bs, Max (As, Ds)), donde realmente no me importa 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 al hacer que los sprites de sombra sean opacos, 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.


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. Tendría que modificar el método de dibujo para hacer esto (y crear un nuevo atributo para un textureNode para cambiar entre estos métodos), y usar cualquiera de estos:

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

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

Ahora, el problema es que cada sprite, y sus hijos, en orden z, se dibujan en 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.

Actualizar:

OK, tengo una solución de trabajo ahora.

Curiosamente, terminé no necesitando esta solución después de todo, porque en mi caso particular, la banda no era lo suficientemente notable como para justificar el esfuerzo, sin embargo, esta es la solución que se me ocurrió que parecía hacer lo que yo 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á compuesto por negro, 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 esa capa para ser 0% negro. GL_ZERO esencialmente lo fuerza a ser 0% negro.

  3. Dibuje el piso, que estará sobre las sombras, pero use glBlend( ONE_MINUS_DST_ALPHA, DST_ALPHA ) . Esto produce exactamente los mismos resultados que si añadieras las sombras al suelo con glBlend( SRC_ALPHA, ONE_MINUS_SRC_ALPHA ) ; sin embargo, si lo glBlend( SRC_ALPHA, ONE_MINUS_SRC_ALPHA ) esta manera, no podrías combinar las sombras (lee por qué en la parte superior de la respuesta) .

  4. ¡Estás listo! 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:

También modifiqué CocosNode para permitirme agregar una sombra a una capa, que se vincula a otro 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.

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