GPUImage源碼解析(1)—— GLProgram

GLProgram

GLProgram的實現(xiàn)相對簡單哩掺,沒有與其他類產(chǎn)生依賴關(guān)系云芦,主要封裝了著色器與著色器程序的創(chuàng)建关炼、編譯程腹、鏈接、使用和銷毀儒拂。

GPUImage中負責(zé)創(chuàng)建GLProgram的只有GLImageContext寸潦,其他類型需要用到GLProgram的時候,會通過GLImageContext來獲取社痛。

關(guān)于著色器的介紹甸祭,可以參考LearnOpenGL-著色器

下面簡單介紹一下GPUImage的方法:

  • 初始化方法,根據(jù)需要傳入頂點著色器和片源著色器的路徑或存放在NSBundle的文件名進行初始化褥影。
- (id)initWithVertexShaderString:(NSString *)vShaderString 
            fragmentShaderString:(NSString *)fShaderString;
- (id)initWithVertexShaderString:(NSString *)vShaderString 
          fragmentShaderFilename:(NSString *)fShaderFilename;
- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename 
            fragmentShaderFilename:(NSString *)fShaderFilename;

初始化的過程包含了頂點著色器和片段著色器的創(chuàng)建池户、編譯,著色器程序的創(chuàng)建并綁定著色器凡怎。

// 其他的初始化方法都會調(diào)用這個初始化方法
- (id)initWithVertexShaderString:(NSString *)vShaderString 
            fragmentShaderString:(NSString *)fShaderString;
{
    if ((self = [super init])) 
    {
        _initialized = NO;
        
        attributes = [[NSMutableArray alloc] init]; // 局部變量列表
        uniforms = [[NSMutableArray alloc] init]; // 全局變量列表
        program = glCreateProgram(); // 創(chuàng)建Program
        
        // 編譯頂點著色器
        if (![self compileShader:&vertShader 
                            type:GL_VERTEX_SHADER 
                          string:vShaderString])
        {
            NSLog(@"Failed to compile vertex shader");
        }
        
        // 編譯片段著色器
        if (![self compileShader:&fragShader 
                            type:GL_FRAGMENT_SHADER 
                          string:fShaderString])
        {
            NSLog(@"Failed to compile fragment shader");
        }
        
        // 綁定著色器到著色器程序
        glAttachShader(program, vertShader);
        glAttachShader(program, fragShader);
    }
    
    return self;
}

著色器編譯過程校焦,主要包括著色器創(chuàng)建并綁定源代碼、編譯和輸出錯誤日志统倒。

- (BOOL)compileShader:(GLuint *)shader 
                 type:(GLenum)type 
               string:(NSString *)shaderString
{
//    CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();

    GLint status;
    const GLchar *source;
    
    // 獲取著色器代碼
    source = 
      (GLchar *)[shaderString UTF8String];
    if (!source)
    {
        NSLog(@"Failed to load vertex shader");
        return NO;
    }
    
    *shader = glCreateShader(type); // 創(chuàng)建指定類型的著色器
    glShaderSource(*shader, 1, &source, NULL); // 綁定著色器代碼到著色器
    glCompileShader(*shader); // 編譯著色器
    
    glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); // 獲取編譯狀態(tài)

    // 判斷著色器編譯是否成功寨典,失敗則輸出日志
    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;
}
  • 鏈接著色器程序
- (BOOL)link
{
//    CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();

    GLint status;
    
    // 鏈接著色器程序
    glLinkProgram(program);
    
    // 獲取鏈接狀態(tài)
    glGetProgramiv(program, GL_LINK_STATUS, &status);
    
    // 判斷鏈接是否成功,失敗則返回
    if (status == GL_FALSE)
        return NO;
    
    // 鏈接成功房匆,就可以刪掉相關(guān)的shader耸成,釋放資源
    if (vertShader)
    {
        glDeleteShader(vertShader);
        vertShader = 0;
    }
    if (fragShader)
    {
        glDeleteShader(fragShader);
        fragShader = 0;
    }
    
    // 設(shè)置初始化成功標(biāo)識
    self.initialized = YES;

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

    return YES;
}
  • 使用著色器程序
- (void)use
{
    glUseProgram(program);
}
  • 獲取相關(guān)屬性的索引报亩,用于為著色器傳值。
- (void)addAttribute:(NSString *)attributeName
{
     // 判斷當(dāng)前的屬性是否已存在
    if (![attributes containsObject:attributeName])
    {
          // 如果不存在先加入屬性數(shù)組井氢,然后綁定該屬性的索引為在屬性數(shù)組中的索引
        [attributes addObject:attributeName];
        glBindAttribLocation(program, 
                             (GLuint)[attributes indexOfObject:attributeName],
                             [attributeName UTF8String]);
    }
}

// 獲取屬性的索引
- (GLuint)attributeIndex:(NSString *)attributeName
{
    return (GLuint)[attributes indexOfObject:attributeName];
}

// 獲取uniform的索引
- (GLuint)uniformIndex:(NSString *)uniformName
{
    return glGetUniformLocation(program, [uniformName UTF8String]);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末弦追,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子花竞,更是在濱河造成了極大的恐慌劲件,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件约急,死亡現(xiàn)場離奇詭異零远,居然都是意外死亡,警方通過查閱死者的電腦和手機厌蔽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門牵辣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人奴饮,你說我怎么就攤上這事纬向。” “怎么了拐云?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵罢猪,是天一觀的道長。 經(jīng)常有香客問我叉瘩,道長膳帕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任薇缅,我火速辦了婚禮危彩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘泳桦。我一直安慰自己汤徽,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布灸撰。 她就那樣靜靜地躺著谒府,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浮毯。 梳的紋絲不亂的頭發(fā)上完疫,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天,我揣著相機與錄音债蓝,去河邊找鬼壳鹤。 笑死,一個胖子當(dāng)著我的面吹牛饰迹,可吹牛的內(nèi)容都是我干的芳誓。 我是一名探鬼主播余舶,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼锹淌!你這毒婦竟也來了匿值?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤葛圃,失蹤者是張志新(化名)和其女友劉穎千扔,沒想到半個月后憎妙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體库正,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年厘唾,在試婚紗的時候發(fā)現(xiàn)自己被綠了褥符。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡抚垃,死狀恐怖喷楣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鹤树,我是刑警寧澤铣焊,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站罕伯,受9級特大地震影響曲伊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜追他,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一坟募、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧邑狸,春花似錦懈糯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至硅堆,卻和暖如春屿储,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背硬萍。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工扩所, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人朴乖。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓祖屏,卻偏偏與公主長得像助赞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子袁勺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內(nèi)容