2011-03-14 10 views
6

Necesito combinar tres imágenes de la manera que represento en el archivo adjunto:¿Cómo puedo recortar una imagen con máscara y combinarla con otra imagen (fondo) en el iPhone? (OpenGL ES 1.1 se prefiere)

enter image description here

1) Una imagen es fondo. Es 'sólido' en el sentido de que no tiene un canal alfa.

2) Otro es sprite. Sprite se encuentra en el fondo. Sprite puede tener su propio canal alfa, el fondo debe ser visible en lugares donde Sprite es transparente.

3) Hay varias máscaras: aplico nueva máscara a Sprite en cada cuadro. La máscara no es rectangular

En otras palabras, píxel visible = píxel de fondo, si la máscara de recorte el color correspondiente es blanco O el sprite es transparente; píxel de sprite, de lo contrario (por ejemplo, el píxel de la máscara correspondiente es negro).

Estoy trabajando con cocos2d-iphone. ¿Puedo hacer una combinación de este tipo con cocos2d-iphone o con OpenGL ES 1.1? Si alguna respuesta es SÍ, se agradecerá el código de trabajo. Si ambas respuestas son NO, ¿hay otra tecnología en iOS para hacer lo que quiero (tal vez Quartz2d u OpenGL ES 2.0)?

El formato de la máscara no es obligatorio en negro para Sprite y en blanco para el fondo. Puedo crear la máscara del formato requerido, como transparencia para fondo y blanco para Sprite si es necesario.

P.S. Hay otra pregunta sin respuesta del mismo tipo: Possible to change the alpha value of certain pixels on iPhone?

+0

o cualquiera que esté leyendo esta pregunta. Es bueno darse cuenta de que hay una tecnología de uso diario disponible para hacer esto completamente y completamente SIN usar OpenGL de ninguna manera ... http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/ drawingwithquartz2d/dq_images/dq_images.html – Fattie

Respuesta

8

Aquí está mi respuesta para OpenGL. El procedimiento sería muy diferente para Quartz. El código real es bastante simple, pero hacerlo exactamente es la parte difícil. Estoy usando un contexto GL que es 1024X1024 con el origen en la parte inferior izquierda. No estoy publicando mi código porque usa el modo inmediato que no está disponible en OpenGL | ES. Si quieres mi código de dibujo, házmelo saber y actualizaré mi respuesta.

  1. Dibuje la máscara con la combinación deshabilitada.
  2. Habilite la mezcla, configure GLBlendFunc (GL_DST_COLOR, GL_ZERO) y dibuje el sangrado a través de la textura. Mi máscara es blanca donde debería sangrar. En tu pregunta, era negro.
  3. Ahora, para dibujar el fondo, establezca la función de fusión en glBlendFunc (GL_ONE_MINUS_DST_COLOR, GL_DST_COLOR) y dibuje la textura de fondo.

EDIT Aquí está el código que describo arriba. Tenga en cuenta que esto no funcionará en iOS ya que no hay un modo inmediato, pero debería poder hacerlo funcionar en el proyecto de Macintosh. Una vez que esté funcionando, puede convertirlo a algo compatible con iOS en el proyecto Macintosh y luego mover ese código a su proyecto iOS.

La llamada a renderMask() es donde está la parte más interesante. renderTextures() dibuja las texturas de muestra en la fila superior.

static GLuint color_texture; 
static GLuint mask_texture; 
static GLuint background_texture; 

static float window_size[2]; 

void renderMask() 
{ 
float texture_x=0, texture_y=0; 
float x=0, y=0; 

{ 
    glBindTexture(GL_TEXTURE_2D, mask_texture); 

    glDisable(GL_BLEND); 
    glBegin(GL_QUADS); 
     glTexCoord2f(texture_x,texture_y); 
     glVertex2f(x,y); 

     glTexCoord2f(texture_x+1.0,texture_y); 
     glVertex2f(x+512.0,y); 

     glTexCoord2f(texture_x+1.0,texture_y+1.0); 
     glVertex2f(x+512.0,y+512.0); 

     glTexCoord2f(texture_x,texture_y+1.0); 
     glVertex2f(x,y+512.0); 
    glEnd(); 
} 

{ 
    glBindTexture(GL_TEXTURE_2D, color_texture); 
    glEnable(GL_BLEND); 
    glBlendFunc(GL_DST_COLOR, GL_ZERO); 
    glBegin(GL_QUADS); 
     glTexCoord2f(texture_x,texture_y); 
     glVertex2f(x,y); 

     glTexCoord2f(texture_x+1.0,texture_y); 
     glVertex2f(x+512.0,y); 

     glTexCoord2f(texture_x+1.0,texture_y+1.0); 
     glVertex2f(x+512.0,y+512.0); 

     glTexCoord2f(texture_x,texture_y+1.0); 
     glVertex2f(x,y+512.0); 
    glEnd(); 
} 

{ 
    glBindTexture(GL_TEXTURE_2D, background_texture); 
    glEnable(GL_BLEND); 
    glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_DST_COLOR); 
    glBegin(GL_QUADS); 
     glTexCoord2f(texture_x,texture_y); 
     glVertex2f(x,y); 

     glTexCoord2f(texture_x+1.0,texture_y); 
     glVertex2f(x+512.0,y); 

     glTexCoord2f(texture_x+1.0,texture_y+1.0); 
     glVertex2f(x+512.0,y+512.0); 

     glTexCoord2f(texture_x,texture_y+1.0); 
     glVertex2f(x,y+512.0); 
    glEnd(); 
} 
} 

// Draw small versions of the textures. 
void renderTextures() 
{ 
float texture_x=0, texture_y=0; 
float x=0, y=532.0; 
float size = 128; 

{ 
    glBindTexture(GL_TEXTURE_2D, mask_texture); 

    glDisable(GL_BLEND); 
    glBegin(GL_QUADS); 
     glTexCoord2f(texture_x,texture_y); 
     glVertex2f(x,y); 

     glTexCoord2f(texture_x+1.0,texture_y); 
     glVertex2f(x+size,y); 

     glTexCoord2f(texture_x+1.0,texture_y+1.0); 
     glVertex2f(x+size,y+size); 

     glTexCoord2f(texture_x,texture_y+1.0); 
     glVertex2f(x,y+size); 
    glEnd(); 
} 

{ 
    glBindTexture(GL_TEXTURE_2D, color_texture); 
    x = size + 16; 

    glBegin(GL_QUADS); 
     glTexCoord2f(texture_x,texture_y); 
     glVertex2f(x,y); 

     glTexCoord2f(texture_x+1.0,texture_y); 
     glVertex2f(x+size,y); 

     glTexCoord2f(texture_x+1.0,texture_y+1.0); 
     glVertex2f(x+size,y+size); 

     glTexCoord2f(texture_x,texture_y+1.0); 
     glVertex2f(x,y+size); 
    glEnd(); 
} 

{ 
    glBindTexture(GL_TEXTURE_2D, background_texture); 
    x = size*2 + 16*2; 
    glBegin(GL_QUADS); 
     glTexCoord2f(texture_x,texture_y); 
     glVertex2f(x,y); 

     glTexCoord2f(texture_x+1.0,texture_y); 
     glVertex2f(x+size,y); 

     glTexCoord2f(texture_x+1.0,texture_y+1.0); 
     glVertex2f(x+size,y+size); 

     glTexCoord2f(texture_x,texture_y+1.0); 
     glVertex2f(x,y+size); 
    glEnd(); 
} 
} 

void init() 
{ 
GLdouble bounds[4]; 

glGetDoublev(GL_VIEWPORT, bounds); 

window_size[0] = bounds[2]; 
window_size[1] = bounds[3]; 

glClearColor(0.0, 0.0, 0.0, 1.0); 

glShadeModel(GL_SMOOTH); 

// Load our textures... 
color_texture = [[NSImage imageNamed:@"colors"] texture]; 
mask_texture = [[NSImage imageNamed:@"mask"] texture]; 
background_texture = [[NSImage imageNamed:@"background"] texture]; 


// Enable alpha blending. We'll learn more about this later 
glEnable(GL_BLEND); 

glEnable(GL_TEXTURE_2D); 
} 

void draw() 
{ 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

glColor3f(1.0, 1.0, 1.0); 

renderMask(); 
renderTextures(); 
} 

void reshape(int width, int height) 
{ 
glViewport(0, 0, width, height); 

glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
gluOrtho2D(0.0, width, 0.0, height); 
glMatrixMode(GL_MODELVIEW); 

window_size[0] = width; 
window_size[1] = height; 
} 

Esto muestra la mis tres texturas extraídas normalmente (de cultivos, sangrar a través de, y fondo) y luego se combinan a continuación.

image

+0

Parece que no está funcionando :(Solo imagina la mancha negra en Sprite: después de 2) obtendríamos dos tipos de negro: negro de mancha negra en Sprite y negro en el área sin máscara. ENCENDIDO 3) El fondo aparecerá en todas partes DST_COLOR es NEGRO. –

+0

Quiero decir que los píxeles NEGROS de Sprite, si están dentro de la máscara, deberían permanecer NEGROS, no de fondo. –

+0

La máscara debe ser blanca por donde pasa. La mezcla en el paso 2 multiplica el valor del color de la máscara por el valor del sangrado a través de la textura. si la máscara es negra (0,0,0) el resultado de la multiplicación es cero. Entonces cropping_mask.png debe ser blanco en el pentágono y transparente fuera del pentágono. – Mark

Cuestiones relacionadas