四、GPUImage自定義濾鏡

一、背景

GPUImage的官方地址:https://github.com/BradLarson/GPUImage
官方給出的自定義濾鏡的方法是讓開發(fā)者自己寫fragmentShader實(shí)現(xiàn)特效,但是粒子效果需要更多的頂點(diǎn),這顯然需要另一種方式來實(shí)現(xiàn),完全自己定義的vertexShaderfragmentShader

二、GPUImage自定義filter

在自定義filter的時候需要弄清楚GPUImage的規(guī)則,以及在編寫著色器語言時的一些限制。
1、創(chuàng)建一個WYFilter繼承自GPUImageFilter
2、頂點(diǎn)著色器要有position、inputTextureCoordinate這兩個輸入變量,片元著色器要有textureCoordinateinputImageTexture 這兩個變量。[注:GPUImage內(nèi)部的頂點(diǎn)坐標(biāo)和紋理坐標(biāo)還有紋理就是以這個名稱進(jìn)行傳值的]
3、重寫initializeAttributes增加自己的attribute屬性

- (void)initializeAttributes {
    [super initializeAttributes];
    
    [filterProgram addAttribute:@"flag"];
}

4、重寫initWithVertexShaderString:fragmentShaderString:,在該方法中調(diào)用runSynchronouslyOnVideoProcessingQueue獲取內(nèi)建變量的位置索引

- (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fragmentShaderFromString:(NSString *)fragmentShaderString {
    if (!(self = [super initWithVertexShaderFromString:vertexShaderString fragmentShaderFromString:fragmentShaderString])) {
        return nil;
    }
    
    runSynchronouslyOnVideoProcessingQueue(^{
        _flagSlot = [filterProgram attributeIndex:@"flag"];
    });
    
    return self;
}

5、重寫renderToTextureWithVertices:textureCoordinates:,在這個方法中畫自己想要畫的東西

- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates {
    
    [super renderToTextureWithVertices:vertices textureCoordinates:textureCoordinates];
    
    static GLfloat vertices2[] = {
        -0.25, 0.25,   1.0,  // 左上
        -0.25, -0.25,  1.0,  // 左下
        0.25, 0.25,    1.0,  // 右上
        0.25, -0.25,   1.0,  // 右下
    };
    
    const GLbyte *pointer2 = (const GLbyte*)vertices2;

    glVertexAttribPointer(filterPositionAttribute, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, pointer2);
    glVertexAttribPointer(_flagSlot, 1, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, pointer2 + sizeof(GLfloat) * 2);
    glEnableVertexAttribArray(_flagSlot);
    glDrawArrays(GL_POINTS, 0, 4);
    
    glDisableVertexAttribArray(_flagSlot);
}

注意點(diǎn):
1、當(dāng)我們使用了glEnable的函數(shù)之后記得在調(diào)用glDrawArrays之后調(diào)用glDisable
例:

glVertexAttribPointer(_flagSlot, 1, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 3, pointer2 + sizeof(GLfloat) * 2);
glEnableVertexAttribArray(_flagSlot);
glDrawArrays(GL_POINTS, 0, 4);
    
glDisableVertexAttribArray(_flagSlot);

2、GPUImage的坐標(biāo)系的y軸跟Opengl坐標(biāo)系的y軸是相反的
3、GPUImage中紋理加載方式,盡量使用GLKTextureLoader加載,否則可能在部分系統(tǒng)的手機(jī)上出現(xiàn)圖片紋理模糊的情況,需要#import <GLKit/GLKit.h>

- (int)loadTexture {
   
    CGImageRef imgRef = [UIImage imageNamed:@"white.png"].CGImage;
    GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithCGImage:imgRef options:nil error:nil];
    _wyTexture = textureInfo.name;

    glActiveTexture(GL_TEXTURE3);
    glBindTexture(GL_TEXTURE_2D, _wyTexture);
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    
    return textureInfo.width * 0.5;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容