所以我的 opengl es 游戏中有一个纹理(在帧缓冲区中),我一直想模糊它。我一直在尝试多种方法来看看哪种方法可以获得最佳 FPS,因为这需要实时发生,因为纹理不断变化。
我到底如何获取 opengles 纹理并将其发送到 coreImage,然后返回到 opengles 进行显示?
这是一些代码,基本上您放入 UIImage 中,它返回一个模糊的图像。我陷入困境的地方是将纹理获取到 UIImage,我想知道它们是否是比每次加载新 UIImage 更好的方法。
- (UIImage *)blurredImageWithImage:(UIImage *)sourceImage{
// Create our blurred image
CIContext *context = [CIContext contextWithOptions:nil];
CIImage *inputImage = [CIImage imageWithCGImage:sourceImage.CGImage];
// Setting up Gaussian Blur
CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
[filter setValue:inputImage forKey:kCIInputImageKey];
[filter setValue:[NSNumber numberWithFloat:15.0f] forKey:@"inputRadius"];
CIImage *result = [filter valueForKey:kCIOutputImageKey];
/* CIGaussianBlur has a tendency to shrink the image a little, this ensures it matches
* up exactly to the bounds of our original image */
CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]];
UIImage *retVal = [UIImage imageWithCGImage:cgImage];
return retVal;
}
最佳答案
如果您还没有尝试过并注意到,您引用的方法将杀死性能 - 要从 GL 纹理创建 UIImage
,您需要读取一堆像素从 GPU 转移到 CPU 内存中。然后,CoreImage 可能会将其发送到 GPU 来执行其效果,但由于您从中获取了 UIImage,因此在将图像发送回 GPU 之前,您将再次从 GPU 读回用作纹理。每帧有四次数据传输,而且每一次数据传输都很昂贵。
相反,将 Core Image 保留在 GPU 上,并且不要使用中间 UIImage
。
您需要保留一个
CIContext
进行渲染,因此请尽早从 GL 上下文中使用contextWithEAGLContext:
创建一个 CIContext。并捕获它。使用
imageWithTexture:size:flipped:colorSpace:
从 GL 纹理创建一个CIImage
。当您想要将过滤器链的结果渲染到 GL 纹理时,请将其与
glBindFramebuffer
绑定(bind)(就像您制作自己的渲染到纹理 channel 一样) ),并使用drawImage:inRect:fromRect:
在您的CIContext
中绘制过滤器的输出CIImage
。 (并且在使用该纹理执行其他 GL 渲染之前,不要忘记重新绑定(bind)该纹理。)
早在 2012 年的 WWDC 演讲中就对此进行了很好的阐述:Core Image Techniques 。讨论于 40:00 左右开始,代码和演示持续到 46:05 左右。但请继续听完剩下的演讲,您将获得更多演示、灵感、代码和架构技巧,了解您可以使用 GL 中的 CoreImage 做的有趣事情,使游戏看起来很棒。
此外,如果您使用 Metal (🤘) 进行渲染,则有相应的 CoreImage API 可用于执行相同的工作流程(contextWithMTLDevice:
和 imageWithMTLTexture:
)。
关于ios - 如何通过 opengl es 使用 Apples Core Image,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34712915/