viernes, 22 de abril de 2011

OpenGL-ES2.0 y Monotouch III (AlphaTest y Scissor)

En este tercer tutotrial muestro como realizar AlphaTest y Scissor.

AlphaTest

En la mayoría de motores 3D como sabéis existen dos técnicas a la hora de trabajar con el canal Alpha. Estas son AlphaTest o AlphaBlending.

AlphaTest es la técnica más eficiente y consiste en marcar un umbral para el canal Alpha, si este lo supero el pixel se mostrará y si no lo supera el pixel no se pintará y por lo tanto la imagen será transparente en ese pixel.

AlphaBlending esta técnica es mucho más sofisticada y al mismo tiempo menos eficiente, pero consigue implementar diferentes niveles de alpha de forma que un pixel con alpha 0.7 será más opaco que uno con alpha 0.2.

En este tutorial explico como realizar AlphaTest a través de Fragment shader de OpenGLES2.0.

string fragmentShaderSrc = @"precision mediump float;
varying vec2 vTexCoord;
uniform sampler2D sTexture;
void main()
{
vec4 baseColor = texture2D(sTexture, vTexCoord);

if (baseColor.a < 0.5)
{
discard;
}
else
{
gl_FragColor = vec4(baseColor.xyz,1.0);
}
}";


Lo que hacemos es coger el valor alpha de la textura (que tendrá que ser una textura que albergue canal alpha como PNG) y le hacemos un alphaTest diciendo que si supera nuestro umbral fijado en 0.5f (el canal alpha esta comprendido entre 0 y 1) se le manda al glFragColor y si no se llama a la función discard que descarta el pixel y no lo envia para pintar.

El resultado sería:




Scissor

Scissor es una técnica por la cual le podemos decir al render que no pinte toda la pantalla sino un rectángulo de ella. Un ejemplo sería, imaginaros los tipicos juegos donde tenemos nuestra escena 3d pero esta está rodeada de controles o botones que nos permiten cambiar cosas de la escena. Bien pues la escena 3d no tiene que ocupar toda la pantalla sólo el rectangulo que queda libre dentro del marco de botones.

Para esta técnica sólo necesitamos añadir dos funciones al método de dibujado que nos proporciona la clase iPhoneOSGameView llamado OnRenderFrame.

Primero llamaremos al método GL.Scissor de OpenglES para especificar el rectangulo que limitará el pintado. Y lo segundo que debemos hacer es decirle a OpenglES que active la fase de ScissorTest en el pipeline para que tenga efecto.


...
GL.Scissor(0,0,viewportWidth/2,viewportHeight);
GL.Enable(All.ScissorTest);
...


(Nota. Tener en cuenta que la coordenada (0,0) sería la esquina inferior izquierda de nuestra pantalla)

Resultado sería: