GLKit从jpegs没有alphas掩盖或混合2个纹理

时间:2013-10-23 19:16:49

标签: ios iphone objective-c core-graphics glkit

我正在使用GLKit,并且在24 fps时我需要采用CGImageRef(无alpha图层)并将另一个CGImageRef(无alpha图层)作为遮罩(黑白图像)并将结果渲染为GLKit质地。

起初我尝试了这种方法:

CGImageRef actualMask = CGImageMaskCreate(CGImageGetWidth(maskRef),
                                          CGImageGetHeight(maskRef),
                                          CGImageGetBitsPerComponent(maskRef),
                                          CGImageGetBitsPerPixel(maskRef),
                                          CGImageGetBytesPerRow(maskRef),
                                          CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef masked = CGImageCreateWithMask(imgRef, actualMask);

虽然在将结果UIImage分配给UIImageView时会起作用,但这不能用作GLKit纹理(不会应用蒙版)。但是,如果我使用以下方法重绘图像:

UIImage *maskedImg = [UIImage imageWithCGImage:masked];
UIGraphicsBeginImageContext(maskedImg.size);
[maskedImg drawInRect:CGRectMake(0, 0, maskedImg.size.width, maskedImg.size.height)];
UIImage* resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

生成的图像将被掩盖并在GLKit纹理中正确渲染。但是,这会在iPhone 4S上将性能降低到大约6 fps。

我试过this masking approach但没有成功。

我已尝试在没有Core Graphics的情况下执行此操作并使用this example by Ray Wenderlich中所示的GLKit混合。但是,这需要在面具上使用alpha透明度,这对我来说是一个交易障碍。

我还找到了一个有趣的例子,说明我想用一个名为AVAnimator的库和一个名为KittyBoom的例子。他们在这里手动替换像素。我想用GLKit得到同样的结果。

任何进一步的指导或指导都会对此有所帮助。提前谢谢。

1 个答案:

答案 0 :(得分:2)

GLKit是一个包含四个主要组件的框架,可以一起使用或单独使用:视图/视图控制器,数学库,纹理加载器和效果。我从您的问题中推测您关注的问题GLKBaseEffect

有人可能会说GLKBaseEffect生活中的目的是让日常事务变得简单。它主要是OpenGL ES 1.1固定功能管道的替代品,也是它的一些常见技巧。

你所追求的不是一个例行的固定功能管道任务,所以做得好意味着超越GLKBaseEffect的基本功能并编写你自己的着色器。这是坏消息。好消息是,一旦你进入着色器世界,这很容易。另一个好消息是,您可以期待出色的性能 - 而不是使用CPU进行CoreGraphics混合,您可以在GPU上进行。

“硬”部分,如果您不熟悉OpenGL ES 2.0(或3.0)着色器,则会将GLKBaseEffect提供的客户端OpenGL ES代码和顶点着色器替换为执行相同操作的自定义代码。不过,有很多示例代码和教程。 (由于您一直关注Ray Wenderlich的网站,我相信您会找到some good ones there。)您需要做的主要事情是:

  1. 将用于glDraw命令的坐标空间中的顶点转换为剪辑空间。对于2D内容,这非常简单,因为您可以使用与GLKBaseEffect的{​​{1}}属性相同的矩阵设置。
  2. 加载两个纹理(transform可以在这里帮到你很多)并将它们绑定到两个纹理单元。
  3. 在客户端代码中,将每个顶点与一些纹理坐标相关联。 (你可能已经这样做了。)
  4. 在顶点着色器中,从GLKTextureLoader输入中获取纹理坐标,并将它们传递给uniform输出。 (除非您因某种原因想要转换坐标,否则不必做任何其他事情。)
  5. 完成所有设置之后,实际完成您所效果的部分非常简单,并且它都在您的片段着色器中:

    varying

    另外,既然你提到以24 fps这样做,它表明你正在使用视频。在这种情况下,你可以删除中间人 - 视频帧已经在GPU上处理,并将它们放在CPU上的CGImages中只会减慢你的速度。请查看// texture units bound in client code uniform sampler2D colorTexture; uniform sampler2D maskTexture; // texture coordinate passed in from vertex shader // (and automatically interpolated across the face of the polygon) varying mediump vec2 texCoord; void main() { // read a color from the color texture lowp vec3 color = texture2D(colorTexture, texCoord).rgb; // read a gray level from the mask texture // (the mask is grayscale, so we only need one component // of its color because the others are the same) lowp float maskLevel = texture2D(maskTexture, texCoord).r; // use the gray level from the mask as the alpha value in the output color gl_FragColor = vec4(color, maskLevel); } 类和GLCameraRipple示例代码,以获取将视频转换为纹理的帮助。

相关问题