GPUImage源码分析与使用(一)

2020-02-12  本文已影响0人  紫水依

GPUImage简介

CoreImage与GPUImage的对比

GPUImage的优势

CoreImage的优势

GPUImage的特性

GPUImage框架

Source(来源)

GPUImageOutput,常用的为前4个,最终处理的都是纹理

  1. GPUImageVideoCamera(正在录制的视频)
  2. GPUImageStillCamera(拍摄的照片)
  3. GPUImagePicture(静态图片)
  4. GPUImageMovie(一段视频)
  5. GPUImageMovieComposition
  6. GPUImageTextureInput(纹理)
  7. GPUImageRawDataOutput(二进制数据)
  8. GPUImageUIElement(UIView/UILayer)
  9. GPUImageColorConversion

Pipeline(管道)

  1. GPUImageFilterPipeline

Filters(过滤器/滤镜)

  1. Base基类

内置滤镜

  1. Color processing(色彩处理)

  2. Image processing(图像处理)

  3. Blends(混合)

  4. Effects(效果)

Outputs(输出)

4种输出结果

  1. GPUImageView
  2. GPUImageMovieWriter
  3. GPUImageTextureOutput
  4. GPUImageRawDataOutput

SupportFrameworks

  1. CoreMedia.framework
  2. CoreVideo.framework
  3. OpenGL ES.framework(1.0和2.0使用,3.0使用Metal)
  4. QuartzCore.framework
  5. AV Foundation.framework(捕捉视频)

GPUImage类的介绍

  1. GLProgram,shader管理,编译链接
  2. GPUImageContext,OpenGL Context管理
  3. GPUImageFramebuffer和GPUImageFramebufferCache,buffer管理
  4. Source,数据源
  5. Pipeline,处理管道
  6. Filters,滤镜组合
  7. Outputs,输出组件

图片处理示例

  1. 饱和度滤镜

GPUImage基类的具体介绍

GPUImage.h

GPUImage所有需要使用到的类的声明基本上都在这里了。

GLProgram

shader管理

GLProgram.h

  1. 变量声明,全局变量声明
{
    NSMutableArray  *attributes; //属性
    NSMutableArray  *uniforms; //通道
    GLuint          program,
    vertShader,  //顶点着色器
    fragShader;  //片元着色器
}
  1. 属性声明,记录编译信息等
@property(readwrite, nonatomic) BOOL initialized;
//编译信息记录
@property(readwrite, copy, nonatomic) NSString *vertexShaderLog;
@property(readwrite, copy, nonatomic) NSString *fragmentShaderLog;
@property(readwrite, copy, nonatomic) NSString *programLog;
  1. 初始化,三种初始化方法,第一种是主要方法
/*
 传入顶点着色器代码和片元着色器代码
 可以传入字符串类型,也可以传入文件类型,比如以.vsh/.fsh/.glsl等为后缀等命名的文件
 GPUImage里自定义滤镜基本都是使用字符串类型
*/
- (id)initWithVertexShaderString:(NSString *)vShaderString 
            fragmentShaderString:(NSString *)fShaderString;
- (id)initWithVertexShaderString:(NSString *)vShaderString 
          fragmentShaderFilename:(NSString *)fShaderFilename;
- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename 
            fragmentShaderFilename:(NSString *)fShaderFilename;
  1. 添加attribute
- (void)addAttribute:(NSString *)attributeName;
  1. attribute和uniform的获取
//获得attribute
- (GLuint)attributeIndex:(NSString *)attributeName;
//获得uniform
- (GLuint)uniformIndex:(NSString *)uniformName;
  1. program操作
- (BOOL)link;
- (void)use;
- (void)validate;

GLProgram.m

  1. 初始化方法,后两种初始化方法都是在获取到本地文件路径后读取glsl字符串,然后调用第一种方法
//传入顶点着色器和片元着色器进行初始化
- (id)initWithVertexShaderString:(NSString *)vShaderString 
            fragmentShaderString:(NSString *)fShaderString;
{
    if ((self = [super init])) 
    {
        _initialized = NO;
        
        attributes = [[NSMutableArray alloc] init];
        uniforms = [[NSMutableArray alloc] init];
        program = glCreateProgram();
        
        //拿到着色器代码进行编译
        if (![self compileShader:&vertShader 
                            type:GL_VERTEX_SHADER 
                          string:vShaderString])
        {
            NSLog(@"Failed to compile vertex shader");
        }
        
        // Create and compile fragment shader
        if (![self compileShader:&fragShader 
                            type:GL_FRAGMENT_SHADER 
                          string:fShaderString])
        {
            NSLog(@"Failed to compile fragment shader");
        }
        
        //着色器编译后附着到program
        glAttachShader(program, vertShader);
        glAttachShader(program, fragShader);
    }
    
    return self;
}
  1. 着色器编译方法
- (BOOL)compileShader:(GLuint *)shader 
                 type:(GLenum)type 
               string:(NSString *)shaderString
{
//    CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();

    GLint status;
    const GLchar *source;
    
    //拿到source
    source = 
      (GLchar *)[shaderString UTF8String];
    if (!source)
    {
        NSLog(@"Failed to load vertex shader");
        return NO;
    }
    
    //创建着色器
    *shader = glCreateShader(type);
    glShaderSource(*shader, 1, &source, NULL);
    glCompileShader(*shader);
    
    //获取shader信息
    glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);

    if (status != GL_TRUE)
    {
        GLint logLength;
        glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
        if (logLength > 0)
        {
            GLchar *log = (GLchar *)malloc(logLength);
            glGetShaderInfoLog(*shader, logLength, &logLength, log);
            if (shader == &vertShader)
            {
                self.vertexShaderLog = [NSString stringWithFormat:@"%s", log];
            }
            else
            {
                self.fragmentShaderLog = [NSString stringWithFormat:@"%s", log];
            }

            free(log);
        }
    }   
    
//    CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
//    NSLog(@"Compiled in %f ms", linkTime * 1000.0);

    return status == GL_TRUE;
}
  1. 添加属性addAttribute,使用函数glBindAttribLocation
- (void)addAttribute:(NSString *)attributeName
{
    if (![attributes containsObject:attributeName])
    {
        [attributes addObject:attributeName];
        //glBindAttribLocation函数添加addattribute
        glBindAttribLocation(program, 
                             (GLuint)[attributes indexOfObject:attributeName],
                             [attributeName UTF8String]);
    }
}
  1. 获取attribute和uniform
- (GLuint)attributeIndex:(NSString *)attributeName
{
    return (GLuint)[attributes indexOfObject:attributeName];
}
- (GLuint)uniformIndex:(NSString *)uniformName
{
    return glGetUniformLocation(program, [uniformName UTF8String]);
}
  1. 链接program
- (BOOL)link
{
//    CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();

    GLint status;
    
    //链接Program
    glLinkProgram(program);
    
    //获取link状态
    glGetProgramiv(program, GL_LINK_STATUS, &status);
    if (status == GL_FALSE)
        return NO;
    
    //link成功之后删除着色器,从program中去着色器信息
    if (vertShader)
    {
        glDeleteShader(vertShader);
        vertShader = 0;
    }
    if (fragShader)
    {
        glDeleteShader(fragShader);
        fragShader = 0;
    }
    
    self.initialized = YES;

//    CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
//    NSLog(@"Linked in %f ms", linkTime * 1000.0);

    return YES;
}
  1. 使用和销毁program
- (void)use
{
    glUseProgram(program);
}

- (void)validate;
{
    GLint logLength;
    
    glValidateProgram(program);
    glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
    if (logLength > 0)
    {
        GLchar *log = (GLchar *)malloc(logLength);
        glGetProgramInfoLog(program, logLength, &logLength, log);
        self.programLog = [NSString stringWithFormat:@"%s", log];
        free(log);
    }   
}
  1. dealloc,删除着色器和program
- (void)dealloc
{
    if (vertShader)
        glDeleteShader(vertShader);
        
    if (fragShader)
        glDeleteShader(fragShader);
    
    if (program)
        glDeleteProgram(program);
       
}

GPUImageContext

GPUImage会有很多context,需要GPUImageContext进行context管理

GLProgramGPUImageContext 不需要使用GPUImage的开发者更改和直接使用,这是GPUImage框架本身使用的

GPUImageFramebuffer/GPUImageFramebufferCache

Framebuffer的管理

//开辟Framebuffer
// Initialization and teardown
- (id)initWithSize:(CGSize)framebufferSize;
- (id)initWithSize:(CGSize)framebufferSize textureOptions:(GPUTextureOptions)fboTextureOptions onlyTexture:(BOOL)onlyGenerateTexture;
- (id)initWithSize:(CGSize)framebufferSize overriddenTexture:(GLuint)inputTexture;
上一篇 下一篇

猜你喜欢

热点阅读