miércoles, 12 de diciembre de 2012

La sombra de la esfera

Para la sombra de la esfera decidí usar lo que en el libro: "Pro OpenGL ES  for Android" llaman una "Blob Shadows", que no es otra cosa que colocar una sombra con forma de círculo justo debajo del modelo. Como mi modelo era una esfera esta sombra le iba como un guante, y así de paso me evitaba estar jugando con el Stencil Buffer y con lo shaders, simplemente tenía que colocar un polígono debajo de la esfera con una textura con transparencias, con el dibujo de una esfera negra con los bordes difuminados, y listo.


Pero no contaba con el z-fighting que se produce cuando el polígono con la textura de la sombra es colocado en el mismo plano que el suelo, y la textura empieza a parpadear. El openGL se hace un lio con el z-buffer y no sabe que téxtura pintar por delante de la otra.

Al principio solucioné el problema usando:

gl.glEnable(GL11.GL_POLYGON_OFFSET_FILL);
gl.glPolygonOffset( -1f, 0f );

Éstas funciones habilitan un desplazamiento u offset de los pixels con respecto a la cámara, es decir a lo largo del eje z, datos negativos acercan el pixel a la cámara y positivos lo alejan. Y lo hacen "engañando" al z-buffer mintiendo sobre la posición de los pixels, de esta forma hay desempate en la lucha por la posición, pero no se modifica la posición real del polígono. Algo fantástico. De hecho me funcionaba perfectamente en mi móvil samsung ace, pero cuando lo probé en mi archos 70 me salió esto:



Por algún extraño motivo el desplazamiento de la función glPolygonOffset funcionaba diferente en diferentes dispositivos y como supuestamente al ser todo openGL debería funcionar igual y no era así, pues me dejó descolocado.

Hubiera preferido que no funcionara en ninguno de los Android que tengo, a que funcionara en uno si y en el otro no... después de casi dos días viendo posibles causas, ajustando parámetros y viendo alternativas opté por deshabilitar el test de profundidad justo antes de dibujar la sombra y volver a activarlo justo después.

gl.glDisable(GL11.GL_DEPTH_TEST);
sombra.render(GL11.GL_TRIANGLES);
gl.glEnable(GL11.GL_DEPTH_TEST);

Y asunto "arreglado". Ahora se ve bien en los dos Androids. Eso si, en cuando la esfera salte por rampas, o cosas así el truco va a cantar. Espero que para las exigencias del juego me sirva con esta solución.

Ya casi estaba dispuesto a aprender shaders y pasarme al opengl ES 2.0 o probar con las técnicas del Stencil Buffer. Y viendo lo visto para el siguiente juego me paso al opengl ES 2.0.

No hay comentarios:

Publicar un comentario