I need to combine three images the way I represent in attached file:
1) One image is background. It is 'solid' in sense it has no alpha channel.
2) Another one is sprite. Sprite lies upon background. Sprite may have its own alpha channel, background has to be visible in places where sprite is transparent.
3) There's a number of masks: I apply new mask to Sprite every frame. Mask isn't rectangular.
In other words, visible pixel = pixel of background, if cropping mask corresponding color is white OR sprite is transparent; pixel of sprite otherwise (for example, corresponding mask's pixel is black).
I'm working with cocos2d-iphone. Can I make such combination with cocos2d-iphone or with OpenGL ES 1.1? If any answer is YES, working code would be appreciated. If both answers is NO, is there another technology on iOS to make what I want (maybe Quartz2d or OpenGL ES 2.0) ?
Mask format is not obligatory black for Sprite and white for Background. I can make Mask of required format, such as transparency for Background and white for Sprite if needed.
P.S. There's another unanswered question of same kind: Possible to change the alpha value of certain pixels on iPhone?
Here is my answer for OpenGL. The procedure would be very different for Quartz. The actual code is pretty simple, but getting it exactly right is the tricky part. I am using a GL context that is 1024X1024 with the origin in the bottom left. I'm not posting my code because it uses immediate mode which isn't available in OpenGL|ES. If you want my drawing code, let me know and I'll update my answer.
EDIT Here is the code I describe above. Please note that this will not work on iOS since there is no immediate mode, but you should be able to get this working in Macintosh project. Once that is working you can convert it to something iOS compatible in the Macintosh project and then move that code over to your iOS project.
The renderMask() call is where the most interesting part is. renderTextures() draws the sample textures in the top row.
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;
}
This shows the my three textures drawn normally (crop, bleed through, and background) and then combined below.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With