我正在使用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得到同样的结果。
任何进一步的指导或指导都会对此有所帮助。提前谢谢。
答案 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。)您需要做的主要事情是:
glDraw
命令的坐标空间中的顶点转换为剪辑空间。对于2D内容,这非常简单,因为您可以使用与GLKBaseEffect
的{{1}}属性相同的矩阵设置。transform
可以在这里帮到你很多)并将它们绑定到两个纹理单元。GLKTextureLoader
输入中获取纹理坐标,并将它们传递给uniform
输出。 (除非您因某种原因想要转换坐标,否则不必做任何其他事情。)完成所有设置之后,实际完成您所效果的部分非常简单,并且它都在您的片段着色器中:
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示例代码,以获取将视频转换为纹理的帮助。