我需要按照我在附件中表示的方式组合三个图像:
1) 一张图片是背景。它是“实心”的,因为它没有 alpha channel 。
2) 另一个是sprite。 Sprite 位于背景上。 Sprite 可能有自己的 alpha channel ,背景必须在 sprite 透明的地方可见。
3) 有很多蒙版:我每帧都对 Sprite 应用新的蒙版。面具不是矩形的。
也就是说,可见像素= 背景像素,如果裁剪蒙版对应的颜色是白色或 Sprite 是透明的; Sprite 的像素否则(例如,对应的掩码的像素是黑色的)。
我正在使用 cocos2d-iphone。我可以与 cocos2d-iphone 或 OpenGL ES 1.1 进行这样的组合吗?如果任何答案是肯定的,工作代码将不胜感激。如果两个答案是否定的,iOS 上是否有另一种技术可以实现我想要的(可能是 Quartz2d 或 OpenGL ES 2.0)?
mask 格式对于 Sprite 不是强制性的黑色,对于背景不是强制性的白色。如果需要,我可以制作所需格式的蒙版,例如背景的透明度和雪碧图的白色。
附言还有另一个未回答的同类问题: Possible to change the alpha value of certain pixels on iPhone?
最佳答案
这是我对 OpenGL 的回答。对于 Quartz,该过程将非常不同。 实际代码非常简单,但要使其完全正确是棘手的部分。我正在使用 1024X1024 的 GL 上下文,原点位于左下角。我没有发布我的代码,因为它使用了 OpenGL|ES 中不可用的即时模式。如果您想要我的绘图代码,请告诉我,我会更新我的答案。
- 在禁用混合的情况下绘制蒙版。
- 启用混合,设置 GLBlendFunc(GL_DST_COLOR, GL_ZERO) 并通过纹理绘制出血。我的面具在应该流血的地方是白色的。在你的问题中它是黑色的。
- 现在要绘制背景,将混合函数设置为 glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_DST_COLOR) 并绘制背景纹理。
编辑 这是我上面描述的代码。请注意,这在 iOS 上不起作用,因为没有即时模式,但您应该能够在 Macintosh 项目中使用它。一旦成功,您可以将其转换为 Macintosh 项目中与 iOS 兼容的内容,然后将该代码移至您的 iOS 项目。
renderMask() 调用是最有趣的部分。 renderTextures() 在顶行绘制样本纹理。
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;
}
这显示了我正常绘制的三个纹理(裁剪、渗透和背景),然后在下面组合。
关于iphone - 如何裁剪带 mask 的图像并将其与 iPhone 上的另一个图像(背景)组合? (首选 OpenGL ES 1.1),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5299452/