Carlos Robles frikiblog

Dibujar sólo parte de una imagen con openGL: dibujar parte de una textura

| 0 comments

Estoy desarrollando un videojuego en Android, en 2D, basado en openGL y me he encontrado con esta situacion: tengo una imagen cargada en una textura, que tengo que imprimir varias veces, pero no siempre completa. Basicamente es una imagen que se repite, hasta rellenar un espacio concreto, al estilo del “rellenar con patron” de photoshop.

Imaginaos algo asi: el circulito es lo que tengo en la textura, y es lo que voy a repetir para rellenar el rectangulo,

pero claro, el rectangulo no tiene un area fija y de hecho cambia practicamente en cada update, asique no nos sirve algo como crear con un editor grafico la imagen definitiva, o crear texturas para la imagen completa y para los distintos tamaños de la recortada, como he visto a gente hacer, seria demasiadas imagenes y una forma muy poco limpia de programarlo.

Asi haciendo un repaso general, se me ocurren unas cuantas cosas. Como trabajando con cosas openFrameworks, y BlackMagic he tenido que pelearme bastante con openGL , y como ademas los que estan haciendo la version  iphone se encontrarán con el mismo problema, la primera opcion que plantee fue en lugar de pensar en android, hacerlo a un nivel lo mas bajo posible, y por suerte OpenGL es muy igual en android, en iphone, y en windows.  En fin, que ahora hay que pensar en la mejor opcion, porque ya sabemos que hablar de openGL es como hablar de matematicas, puedes hacer lo mismo de un monton de formas igual de “divertidas”. Se me ocurrieron varias cosas como calcular una mascara y aventurarme con glBlendFunc, cambiar el viewport y jugar con la posicion y tal vez la escala, o meterle una matriz con la transformacion en el momento concreto, pero la verdad es que nada me parecio tan facil como usar las tijeras, si ya lo dice su nombre!

Os cuento como hacerlo, que no tiene ningun secreto:

La rutina glScissor es una funcion estandar, se puede usar en cualquier entorno, asique siempre esta bien conocerla.  Su descripcion es “define the scissor box”, lo cual no es que sea del todo claro, pero basicamente viene a decir que cuando se usa, a continuacion las funciones de pintado solo afectan a los pixeles que se definen dentro. Es decir, lo demas es como si no existiese.

la especificacion es asi

void glScissor(GLint x, GLint y, GLsizei width, GLsizei height)

tanto GLint y GLsizei son dos typedefs de opengl, y en funcion de la plataforma podeis oir que significan una u otra cosa, pero en cualqueir caso podeis tratarlo de forma segura como si se tratase de un unsigned int

Las coordenadas son sobre la ventana, no sobre la textura. Esto esta bien por cosas como que para un caso como el de el ejemplo, si pintamos todos los ciruculos seguidos, nos sirve con definicir una sola vez el scissor para el area del rectangulo, y no una vez para cada imagen recortada.

Ah, como siempre en openGL las coordenadas empiezan abajo a la izquierda.

la funcion no se puede llamar entre glBegin y glEnd.

Ah, la comprobacion del scissor esta desactivada por defecto, para activarlo debemos llamar glEnable con el argumento   GL_SCISSOR_TEST. Pa volverlo  a desactivar, usamos el mismo argumento en and glDisable. Desactivarlo es como definir el scissor box como toda la pantalla.

Sabiendo como funciona, ahora debemos decidir donde llamarla. En mi caso (que es un poco mas sencillo del ejemplo que he puesto) lo  hago justo antes de drawArrays, he inmediatamente desactivo el scissor test.

Recordando que estamos en android, tengo un objeto de la clase GL10 (javax.microedition.khronos.opengles.GL10) ,   la cosa quedaria asi:

pGL.glEnable(GL10.GL_SCISSOR_TEST);
pGL.glScissor( (int)getX(),(int)getY() ,cropw, croph);
pGL.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);//o la instruccion de dibujado que usemos.
pGL.glDisable(GL10.GL_SCISSOR_TEST);
Facebook Twitter Linkedin Plusone Digg Delicious Reddit Email

Leave a Reply

Required fields are marked *.