OpenGLES渲染


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

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM