音視頻之基礎+渲染流程

常用圖形API簡介:

OpenGL(Open Graphics Library)是一個跨編程語言、跨平臺的編程圖形程序接口,它將計算機的資源抽象稱一個個OpenGL的對象,對這些資源的操作抽象為一個個的OpenGL指令。
OpenGL ES(OpenGL for Embedded Systems)是OpenGL三維圖形API的子集,針對手機PDA和游戲機等嵌入式設備而設計,去除了許多不必要和性能低的API的接口。
DirectX 是由很多API組成的,DirectX并不是一個單純的圖形API,最重要的是DirectX是屬于Windows上一個多媒體處理API,并不支持Windows以外的平臺,所以不是跨平臺的框架,按照性質分類。可以分為四大部分:顯示部分、聲音部分、輸入部分和網絡部分。
Metal :Metal :Apple為游戲開發(fā)者退出了新的平臺技術Metal,該技術能夠為3D圖像提高10倍的渲染性。Metal是Apple為解決3D渲染而推出的框架

OpenGL / OpenGL ES /Metal在任何項目中解決問題的本質就是利用GPU芯片來高效渲染圖形圖像,圖形API是iOS開發(fā)唯一接近GPU的方式

  • OpenGL上下文【context】
    1.在應用程序調用任何OpenGL的指令之前,需要安排首先創(chuàng)建一個OpenGL的上下文。這個上下文是一個非常龐大的狀態(tài)機,保存了OpenGL中的各種狀態(tài),這也是OpenGL指令執(zhí)行的基礎。
    2.OpenGL的函數不管在哪個語言中,都是類似C語言一樣的面向過程的函數,本質是都是對OpenGL上下文這個龐大的狀態(tài)機中的某個狀態(tài)或者對象進行操作,當然你得首先把這個對象設置為當前對象。因此,通過對OpenGL指令的封裝,是可以將OpenGL的相關封裝成為一個面向對象的圖形API
    3.由于OpenGL上下文是個龐大的狀態(tài)機,切換上下文往往會產生比較大的開銷,但是不同的繪制模塊,可能需要使用完全獨立的狀態(tài)管理。因此,可以在應用程序中分別創(chuàng)建多個不同的上下文,在不同的線程中使用不同的上下文,上下文之間共享紋理、緩沖區(qū)等資源。這樣的方案,會比反復切換上下文或者大量修改渲染狀態(tài),更加合理高效。

  • OpenGL狀態(tài)機
    狀態(tài)機是理論上的一種機器。狀態(tài)機描述了一個對象在其生命周期內所經歷的各種狀態(tài),狀態(tài)間的轉變,發(fā)生轉變的動因,條件及轉變中所執(zhí)行的活動?;蛘哒f,狀態(tài)機是一種行為,說明對象在其生命周期中響應事件所經歷的狀態(tài)序列以及對那些狀態(tài)事件的響應
    有記憶功能,能記住其當前的狀態(tài)
    可以接收輸入,根據輸入的內容和自己原先狀態(tài),修改當前自己狀態(tài),并且可以有對應輸出
    當進入特殊狀態(tài)(停機狀態(tài))的時候,便不在接收輸入,停止工作
    類推到OpenGL中,可以理解為:
    OpenGL可以記錄自己的狀態(tài)(如當前所使用的顏色、是否開啟了混合功能等)
    OpenGL可以接收輸入(當調用OpenGL函數的時候,實際上可以看成OpenGL在接收我們的輸入),如我們調用glColor3f,則OpenGL接收到這個輸入后會修改自己“當前顏色”這個狀態(tài)
    OpenGL可以進入停止狀態(tài),不再接收輸入,在程序退出前,OpenGL總會先停止工作的
    渲染--> 將圖像、圖形數據轉換成3D空間圖像操作叫做渲染(Rendering)

  • 頂點數組【VertexArray】
    畫圖一般是先畫好圖像的骨架,然后再往骨架里面填充顏色,這對于OpenGL也一樣。頂點數據就是要畫的圖像的骨架,和現實中不同的是,OpenGL中的圖像都是由圖元組成。在OpenGL中,有3中類型的圖元:點、線、三角形這些頂點數據最終存儲在哪里呢?開發(fā)者可以選擇設定函數指針,在調用繪制方法的時候,直接由內存?zhèn)魅腠旤c數據,也就是說這部分數據之前是存儲在內存中的,被稱為頂點數組。
    頂點指的是我們在繪制一個圖形時,它的頂點位置數據,而這個數據可以直接存儲在數組中或者將其緩存到GPU內存中

  • 和頂點緩沖區(qū)【VertexBuffer】
    而性能更高的做法是,提前分配一塊顯存,將頂點數據預先傳入到顯存當中。這部分的顯存,就被稱為頂點緩沖區(qū)

  • 管線
    在OpenGL下渲染圖形,就會有經歷一個一個節(jié)點。而這樣的操作可以理解管線。類似于流水線,任務之間有先后順序,管線是一個抽象的概念,之所以稱之為管線是因為顯卡在處理數據的時候是按照一個固定的順序來的,而且嚴格按照這個順序

  • 固定管線/存儲著色器
    在早起的OpenGL版本,它封裝了很多種著色器程序塊內置一段包含了光照、坐標轉換、裁剪等等諸多功能的固定shader程序來完成,來幫助開發(fā)者完成圖形的渲染,開發(fā)者只需傳入相應的參數,就能快速完成圖形的渲染。類似于iOS開發(fā)者會封裝很多API,而我們只需要調用。就可以說實現功能,不需要關注底層的實現原理。
    但是OpenGL的使用場景非常豐富,固定管線或存儲著色器無法完成每一個業(yè)務,這時將相關部分開放成可編程

  • 著色器程序Shader
    就全面的將固定渲染管線架構變?yōu)榱丝删幊啼秩竟芫€。因此,OpenGL在實際調用繪制函數之前,還需要制定一個由shader編譯成的著色器程序。常見的著色器主要有頂點著色器(VertexShader)片段著色器(FragmentShader)/像素著色器(PixelShader)、幾何著色器(GeometryShader)、曲面細分著色器(TessellatiionShader)。片段著色器和像素著色器只是在OpenGL和DX中的不同叫法而已。OpenGL3.0 依然只支持頂點著色器和片段著色器這兩個最基礎的著色器。
    OpenGL在處理shader時,和其他編譯器一樣。通過編譯、鏈接等步驟,生成了著色器程序(glProgram),著色器程序同時包含了頂點著色器和片段著色器的運算邏輯。在OpenGL進行繪制的時候,首先由頂點著色器對傳入的頂點數據進行運算,再通過圖元裝配,將頂點轉換為圖元,然后進行光柵化,將圖元這種矢量圖形、轉換為柵格化數據。最后將柵格化數據傳入片段著色器中進行運算。片段著色器會對柵格化數據中的每一個像素進行運算,并決定像素的顏色。

  • 頂點著色器VertexShader
    一般用來處理圖形每個頂點變換【旋轉、平移、投影】
    頂點著色器是OpenGL中用于計算頂點屬性的程序。頂點著色器是逐個頂點運算的程序,也就是說每個頂點數據都會執(zhí)行一次頂點著色器,當然這是并行的,并且頂點著色器運算時無法訪問其他頂點數據
    一般來說典型的需要計算的頂點屬性包括頂點左邊變換、逐個頂點關照運算等。頂點坐標由自身坐標系轉換到歸一化坐標器的運算,就是在這里發(fā)生的。

  • 片元著色器程序FragmentShader
    用來處理圖形中每個像素點顏色計算和填充
    片元著色器是OpenGL中用于計算片段(像素)顏色的程序。片段著色器是這個像素運算,也就是說每個像素都會執(zhí)行一次片段著色器,并行執(zhí)行。

  • GGSL(OpenGL Shading Language)
    OpenGL著色語言(OpenGL Shading Language)是用來在OpenGL中著色編程的語言,也即是開發(fā)寫的短小自定義程序,他們是在圖形卡的GPU(Graphic Progcessor Unit圖形處理單元)上執(zhí)行的,代替了固定的渲染管線的一部分,使得渲染管線中不同層次具有可編程性。比如:試圖轉換、投影轉換等。GLSL(GL Shading Language)的著色器代碼分成兩個部分:Vertex Shader(頂點著色器)Fragment(片段著色器)

  • 光柵化Rasterization
    把頂點數據轉換為片元的過程,具有將圖轉化為一個個柵格組成的圖像的作用,特點是每個元素對應幀緩沖區(qū)的一個像素。光柵化就是把頂點數據轉換為片元的過程,片元中的每一個元素對應于幀緩沖區(qū)的一個像素。
    光柵化其實是一種將幾何圖元變?yōu)槎S圖像的過程。該過程包含了兩個部分的工作。一:決定窗口坐標中的哪些整形柵格區(qū)域被基本圖元占用;二:分配一個顏色值和一個深度值到各個區(qū)域。光柵化過程產生的是片元
    把物體的數學描述以及物體相關的顏色信息轉換為屏幕上用于對應位置的像素及用于填充像素的顏色。這個過程被稱為光柵化,這是一個將模擬信號轉化為離散信號的過程。

  • 紋理
    紋理可以理解為圖片。大家在渲染圖形時需要在其編碼填充圖片,為了使得場景更加逼真。而這里使用的圖片,就是常說的紋理。但是在OpenGL,我們習慣叫紋理,而不是圖片

  • 混合(Blending)
    在測試階段之后,如果像像素依然沒有被剔除,那么像素的顏色將和幀緩沖區(qū)中的顏色附著上的顏色進行混合,混合的算法可以通過OpenGL的函數進行指定。但是OpenGL提供的混合算法是有限的,如果需要更加復雜的混合算法,一般可以通過像素著色器進行實現,當然性能會比原生的混合算法差一些。

  • 變換矩陣
    圖形發(fā)生平移、縮放、旋轉就需要使用變換矩陣實現

  • 投影矩陣
    用于將3D坐標轉換為二維屏幕坐標,實際線條也將在二維坐標下繪制

  • 渲染上屏、交換緩沖區(qū)
    渲染緩沖區(qū)一般映射的是系統(tǒng)的資源:比如窗口,將圖像直接渲染到窗口對應的緩沖區(qū),則可以將圖像顯示到屏幕上,但是值得注意的是,如果每個窗口只有一個緩沖區(qū),那么在繪制的過程中屏幕進行了刷新,窗口可能顯示不完成圖像?
    怎么辦???
    常規(guī)的OpenGL程序至少會有兩個緩沖區(qū),顯示在屏幕上的成為屏幕緩沖區(qū),沒有顯示的成為離屏緩沖區(qū)。在一個緩沖區(qū)渲染完成后,通過將屏幕緩沖區(qū)和離屏緩沖區(qū)交換,實現圖像在屏幕上顯示,由于顯示器的刷新是逐行進行的,因此為了防止交換緩沖區(qū)的時候,屏幕上下區(qū)域的圖像分屬于兩個不同的幀,因此交換一般會等待顯示器刷新完成的信號,在顯示器刷新的間隔中進行交換,這個信號就垂直同步信號,使用雙緩沖區(qū)和垂直同步技術后,由于總要等待緩沖區(qū)交換后再進行下一幀的渲染,是的幀率無法完全達到硬件允許的最高水平,為了解決這個問題,引入三緩沖區(qū)技術,在等待垂直同步時,來回交替渲染兩個離屏的緩沖區(qū),而垂直同步發(fā)生時,屏幕緩沖區(qū)和最近渲染完成的離屏緩沖區(qū)進行交換,實現充分利用硬件性能的目的

  • 渲染流程

    1. GPU獲取圖片的左邊
    2. 將坐標交給頂點著色器(頂點計算)
    3. 將圖片光柵化(獲取圖片對應屏幕上的像素點)
    4. 片元著色器計算(計算每個像素點的最終顯示的顏色值)
    5. 從幀緩沖區(qū)渲染到屏幕上
      渲染管線
      9082112B468F3CDF5FDB5529C9233925.png
  • 下面代碼就展示一個加載圖片的優(yōu)化:

//  Created by 隨風流年 
//  Copyright ? 2019 隨風流年. All rights reserved.
//

#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>

@interface ViewController ()
@property (nonatomic, weak) UIImageView *imageView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self image];

}
- (void)image{
    UIImageView *imageView = [[UIImageView alloc]init];
    imageView.frame = CGRectMake(100, 100, 100, 100);
    [self.view addSubview:imageView];
    self.imageView = imageView;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        //獲取CGImage
        CGImageRef cgImage = [UIImage imageNamed:@"img"].CGImage;
        
        // alphaInfo
        CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(cgImage) & kCGBitmapAlphaInfoMask;
        BOOL hasAlpha = NO;
        if (alphaInfo == kCGImageAlphaPremultipliedLast ||
            alphaInfo == kCGImageAlphaPremultipliedFirst ||
            alphaInfo == kCGImageAlphaLast ||
            alphaInfo == kCGImageAlphaFirst) {
            hasAlpha = YES;
        }
        //bitmapInfo
        CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;
        bitmapInfo |= hasAlpha ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst;
        //size
        size_t width = CGImageGetWidth(cgImage);
        size_t height = CGImageGetHeight(cgImage);
        
        //context
        CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, CGColorSpaceCreateDeviceRGB(), bitmapInfo);
        //draw
        CGContextDrawImage(context, CGRectMake(0, 0, width, height), cgImage);
        //get CGImage
        cgImage = CGBitmapContextCreateImage(context);
        //into UIImage
        UIImage *newImage = [UIImage imageWithCGImage:cgImage];
        //release
        CGContextRelease(context);
        CGImageRelease(cgImage);
        
        //back to main thread
        dispatch_async(dispatch_get_main_queue(), ^{
            self.imageView.image = newImage;
        });
        
    });
}
  • 它接受一個原始的位圖參數cgImage,最終返回一個新的解壓縮后的位圖newImage 中間經過一下三個步驟:
  • 使用CGBitmapContextCreate函數創(chuàng)建一個位圖上下文
  • 使用CGContextDrawImage函數將原始位圖繪制到上下文中
  • 使用CGBitmapContextCreateImage創(chuàng)建一張新的解壓縮后的位圖
    事實上,SDWebImage中對圖片的解壓縮過程與上述完全一致,只是傳遞給CGBitmapContextCreate函數的部分參數存在細微差別
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,622評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 99,716評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,746評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,991評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,706評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,036評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,029評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,203評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 49,725評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,451評論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,677評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,161評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,857評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,266評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,606評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,407評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,643評論 2 380

推薦閱讀更多精彩內容