iphone - 如何裁剪带 mask 的图像并将其与 iPhone 上的另一个图像(背景)组合? (首选 OpenGL ES 1.1)

标签 iphone objective-c ios opengl-es cocos2d-iphone

我需要按照我在附件中表示的方式组合三个图像:

enter image description here

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 中不可用的即时模式。如果您想要我的绘图代码,请告诉我,我会更新我的答案。

  1. 在禁用混合的情况下绘制蒙版。
  2. 启用混合,设置 GLBlendFunc(GL_DST_COLOR, GL_ZERO) 并通过纹理绘制出血。我的面具在应该流血的地方是白色的。在你的问题中它是黑色的。
  3. 现在要绘制背景,将混合函数设置为 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;
}

这显示了我正常绘制的三个纹理(裁剪、渗透和背景),然后在下面组合。

image

关于iphone - 如何裁剪带 mask 的图像并将其与 iPhone 上的另一个图像(背景)组合? (首选 OpenGL ES 1.1),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5299452/

相关文章:

iphone - iOS : Create one sideded dropshadow

iPhone - 在屏幕上绘图以响应触摸事件

iphone - 从 Objective-C 中的 for 循环迭代获取数组

ios - 一次调用多个deleteRowsAtIndexPaths

iphone - CoreBluetoothFramework - 它是否在 IOS 应用程序不运行时启动它

ios - 为什么 NSDictionary 实现为类簇?

iphone - 有什么方法可以访问 objective c 运行时中任何类的私有(private)实例变量的地址吗?

iphone - UIDatepicker 日期只显示星期一的日期

ios - 添加带有后退按钮的 UINavigationController

iphone - UITableViewCell 分隔符未显示