zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    关于分布式系统中雷同集群技术及原理,你知道多少?
    如何在PHP中进行会话处理?
    PHP的isset()、is_null、empty()使用总结
    Mycatweb的介绍与搭建
    企业如何部署开源邮箱系统?
    企业如何选择合适的邮箱系统?
    Ansible原理与安装部署
    gRPC的简介与实例详解
    高效的性能测试工具-wrk
    轻松玩转windows之wamp开发环境部署
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3760742.html
Copyright © 2011-2022 走看看