OpenGLES渲染
OpenGLES使用GPU渲染图片,不占用CPU,但其使用还是挺复杂的.
先用OpenGLES显示一张图片:
// // ShowViewController.m // OpenGLES // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "ShowViewController.h" #import <GLKit/GLKit.h> #import <CoreImage/CoreImage.h> @interface ShowViewController () @property (nonatomic, strong) GLKView *viewBuffer; @end @implementation ShowViewController - (void)viewDidLoad { [super viewDidLoad]; // 获取OpenGLES渲染环境 EAGLContext *eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; // 根据图片获取尺寸 UIImage *image = [UIImage imageNamed:@"demo.png"]; CIImage *ciimage = [[CIImage alloc] initWithImage:image]; CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height); // 初始化GLKView并指定OpenGLES渲染环境 _viewBuffer = [[GLKView alloc] initWithFrame:rect context:eaglContext]; [self.view addSubview:_viewBuffer]; // 与OpenGLES绑定 [_viewBuffer bindDrawable]; // 定义绘制区域(像素描述) CGRect rectInPixels = \ CGRectMake(0.0, 0.0, _viewBuffer.drawableWidth, _viewBuffer.drawableHeight); // 初始化CIImage的环境,指定在OpenGLES2上操作(此处只在GPU上操作) CIContext *context = \ [CIContext contextWithEAGLContext:eaglContext options:@{kCIContextWorkingColorSpace:[NSNull null]}]; // 开始绘制 [context drawImage:ciimage inRect:rectInPixels fromRect:[ciimage extent]]; // 显示 [_viewBuffer display]; } @end
只是显示一张图片而已,就需要写这么多的代码-_-!!!!
他有什么优势呢?其实,它的优势是实时渲染图片,不卡的.
// // RootViewController.m // OpenGLES // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "RootViewController.h" #import <GLKit/GLKit.h> #import <CoreImage/CoreImage.h> #import <QuartzCore/QuartzCore.h> @interface RootViewController () @property (nonatomic, strong) GLKView *viewBuffer; @property (nonatomic, strong) CIContext *ciContext; @property (nonatomic, strong) CIImage *ciImage; @property (nonatomic, strong) CIFilter *ciFilter; @end @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; // 获取OpenGLES2渲染环境 EAGLContext *eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; // 初始化一个viewBuffer,并指定在OpenGLES2环境渲染 CGRect rect = CGRectMake(0, 0, [UIImage imageNamed:@"demo"].size.width, [UIImage imageNamed:@"demo"].size.height); _viewBuffer = [[GLKView alloc] initWithFrame:rect context:eaglContext]; // 绑定将这个view与OpenGLES2绑定 [_viewBuffer bindDrawable]; [self.view addSubview:_viewBuffer]; // 初始化CIImage的环境,指定在OpenGLES2上操作(此处只在GPU上操作) _ciContext = [CIContext contextWithEAGLContext:eaglContext options:@{kCIContextWorkingColorSpace:[NSNull null]}]; // 获取CIImage _ciImage = [[CIImage alloc] initWithImage:[UIImage imageNamed:@"demo"]]; // 初始化一个CIFilter _ciFilter = [CIFilter filterWithName:@"CISepiaTone"]; [_ciFilter setValue:_ciImage forKey:kCIInputImageKey]; [_ciFilter setValue:@0 forKey:kCIInputIntensityKey]; // 定义绘制区域(像素描述) CGRect rectInPixels = \ CGRectMake(0.0, 0.0, _viewBuffer.drawableWidth, _viewBuffer.drawableHeight); // 开始绘制 [_ciContext drawImage:_ciImage inRect:rectInPixels fromRect:[_ciImage extent]]; [_viewBuffer display]; UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, 400, 320, 20)]; [self.view addSubview:slider]; [slider addTarget:self action:@selector(event:) forControlEvents:UIControlEventValueChanged]; slider.minimumValue = 0; slider.maximumValue = 1; } - (void)event:(UISlider *)slider { [_ciFilter setValue:[NSNumber numberWithFloat:slider.value] forKey:kCIInputIntensityKey]; // 定义绘制区域(像素描述) CGRect rectInPixels = \ CGRectMake(0.0, 0.0, _viewBuffer.drawableWidth, _viewBuffer.drawableHeight); [_ciContext drawImage:[_ciFilter outputImage] inRect:rectInPixels fromRect:[_ciImage extent]]; [_viewBuffer display]; } @end
将这个View封装一下吧.
GPUView.h + GPUView.m
// // GPUView.h // OpenGLES // // Copyright (c) 2014年 Y.X. All rights reserved. // #import <UIKit/UIKit.h> #import <GLKit/GLKit.h> #import <CoreImage/CoreImage.h> @interface GPUView : UIView - (void)drawCIImage:(CIImage *)ciImage; @end
// // GPUView.m // OpenGLES // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "GPUView.h" @interface GPUView () @property (nonatomic, assign) CGRect rectInPixels; @property (nonatomic, strong) CIContext *context; @property (nonatomic, strong) GLKView *showView; @end @implementation GPUView - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // 获取OpenGLES渲染环境 EAGLContext *eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; // 初始化GLKView并指定OpenGLES渲染环境 + 绑定 _showView = [[GLKView alloc] initWithFrame:frame context:eaglContext]; [_showView bindDrawable]; // 添加进图层 [self addSubview:_showView]; // 创建CIContext环境 _context = \ [CIContext contextWithEAGLContext:eaglContext options:@{kCIContextWorkingColorSpace:[NSNull null]}]; // 定义绘制区域(像素描述) _rectInPixels = \ CGRectMake(0.0, 0.0, _showView.drawableWidth, _showView.drawableHeight); } return self; } - (void)drawCIImage:(CIImage *)ciImage { // 开始绘制 [_context drawImage:ciImage inRect:_rectInPixels fromRect:[ciImage extent]]; // 显示 [_showView display]; } @end
实现同样的效果:
// // ShowViewController.m // OpenGLES // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "ShowViewController.h" #import <CoreImage/CoreImage.h> #import "GPUView.h" @interface ShowViewController () @property (nonatomic, strong) CIFilter *ciFilter; @property (nonatomic, strong) GPUView *gpuView; @end @implementation ShowViewController - (void)viewDidLoad { [super viewDidLoad]; // 根据图片获取尺寸 UIImage *image = [UIImage imageNamed:@"demo.png"]; CIImage *ciimage = [[CIImage alloc] initWithImage:image]; CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height); // 初始化GPUView _gpuView = [[GPUView alloc] initWithFrame:rect]; [self.view addSubview:_gpuView]; [_gpuView drawCIImage:ciimage]; // 初始化一个CIFilter _ciFilter = [CIFilter filterWithName:@"CISepiaTone"]; [_ciFilter setValue:ciimage forKey:kCIInputImageKey]; [_ciFilter setValue:@0 forKey:kCIInputIntensityKey]; // 初始化一个UISlider UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(0, 400, 320, 20)]; [self.view addSubview:slider]; [slider addTarget:self action:@selector(event:) forControlEvents:UIControlEventValueChanged]; slider.minimumValue = 0; slider.maximumValue = 1; } - (void)event:(UISlider *)slider { [_ciFilter setValue:[NSNumber numberWithFloat:slider.value] forKey:kCIInputIntensityKey]; [_gpuView drawCIImage:[_ciFilter outputImage]]; } @end
看起来简洁多了.....
来点复杂点的,同时操作两个滤镜
// // ShowViewController.m // OpenGLES // // Copyright (c) 2014年 Y.X. All rights reserved. // #import "ShowViewController.h" #import <CoreImage/CoreImage.h> #import "GPUView.h" @interface ShowViewController () @property (nonatomic, strong) CIFilter *ciFilter1; @property (nonatomic, strong) CIFilter *ciFilter2; @property (nonatomic, strong) GPUView *gpuView; @property (nonatomic, strong) UISlider *slider1; @property (nonatomic, strong) UISlider *slider2; @end @implementation ShowViewController - (void)viewDidLoad { [super viewDidLoad]; // 根据图片获取尺寸 UIImage *image = [UIImage imageNamed:@"demo.png"]; CIImage *ciimage = [[CIImage alloc] initWithImage:image]; CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height); // 初始化GPUView _gpuView = [[GPUView alloc] initWithFrame:rect]; [self.view addSubview:_gpuView]; [_gpuView drawCIImage:ciimage]; // 初始化一个CIFilter _ciFilter1 = [CIFilter filterWithName:@"CISepiaTone"]; [_ciFilter1 setValue:ciimage forKey:kCIInputImageKey]; [_ciFilter1 setValue:@0.f forKey:kCIInputIntensityKey]; _ciFilter2 = [CIFilter filterWithName:@"CIHueAdjust"]; [_ciFilter2 setValue:[_ciFilter1 outputImage] forKeyPath:kCIInputImageKey]; [_ciFilter2 setValue:@0.f forKeyPath:kCIInputAngleKey]; // 初始化UISlider _slider1 = [[UISlider alloc] initWithFrame:CGRectMake(0, 400, 320, 20)]; [self.view addSubview:_slider1]; [_slider1 addTarget:self action:@selector(event1:) forControlEvents:UIControlEventValueChanged]; _slider1.minimumValue = 0; _slider1.maximumValue = 1; _slider1.value = 0.5f; _slider2 = [[UISlider alloc] initWithFrame:CGRectMake(0, 450, 320, 20)]; [self.view addSubview:_slider2]; [_slider2 addTarget:self action:@selector(event2:) forControlEvents:UIControlEventValueChanged]; _slider2.minimumValue = -3.14f; _slider2.maximumValue = +3.14f; _slider2.value = 0.f; } - (void)event1:(UISlider *)slider { [_ciFilter1 setValue:[NSNumber numberWithFloat:_slider1.value] forKey:kCIInputIntensityKey]; [_ciFilter2 setValue:[_ciFilter1 outputImage] forKeyPath:kCIInputImageKey]; [_ciFilter2 setValue:[NSNumber numberWithFloat:_slider2.value] forKeyPath:kCIInputAngleKey]; [_gpuView drawCIImage:[_ciFilter2 outputImage]]; } - (void)event2:(UISlider *)slider { [_ciFilter1 setValue:[NSNumber numberWithFloat:_slider1.value] forKey:kCIInputIntensityKey]; [_ciFilter2 setValue:[_ciFilter1 outputImage] forKeyPath:kCIInputImageKey]; [_ciFilter2 setValue:[NSNumber numberWithFloat:_slider2.value] forKeyPath:kCIInputAngleKey]; [_gpuView drawCIImage:[_ciFilter2 outputImage]]; } @end