OpenGL 基本概念

推薦

OpenGL 經(jīng)典兩本書(shū)紅寶書(shū)和藍(lán)寶書(shū),其中藍(lán)寶書(shū)更適合初學(xué)者
《OpenGL超級(jí)寶典 第5版》
《OpenGL編程指南(英文第八版)》

前置概念解釋

1.OpenGL與OpenGL ES 的區(qū)別

OpenGL針對(duì)PC端,是Sun公司開(kāi)發(fā)的一套三維圖形應(yīng)用程序接口庫(kù),軟件開(kāi)發(fā)者借助OpenGL可以實(shí)現(xiàn)復(fù)雜的三維圖形變換。
OpenGL ES (OpenGL for Embedded Systems)是OpenGL三維圖形API的子集,針對(duì)手機(jī),PAD和游戲主機(jī)等嵌入式設(shè)備而設(shè)計(jì)。

2.DirectX windows 多媒體處理框架

3.metal 2014年推出, 蘋果內(nèi)核逐漸使用的三維圖形框架

4.圖形API目的是解決什么問(wèn)題?

1)音視頻開(kāi)發(fā)中,對(duì)于視頻解碼后的數(shù)據(jù)渲(ijkplayer,kxmovie等等)
2)地圖數(shù)據(jù)渲染
3)核心動(dòng)畫繪制
4)加濾鏡效果
5)游戲人物場(chǎng)景的渲染
6)離屏渲染
解決問(wèn)題的本質(zhì)是操作GPU芯片。

前言

在開(kāi)始這段旅程之前我們先了解一下OpenGL到底是什么。一般它被認(rèn)為是一個(gè)API (應(yīng)用程序編程接口),包含了一系列可以操作圖形、圖像的函數(shù)。然而,OpenGL本身并不是一個(gè)API,它僅僅是一個(gè)由Khronos組織制定并維護(hù)的規(guī)范(Specification)。
實(shí)際的OpenGL庫(kù)的開(kāi)發(fā)者通常是顯卡的生產(chǎn)商。你購(gòu)買的顯卡所支持的OpenGL版本都為這個(gè)系列的顯卡專門開(kāi)發(fā)的。當(dāng)你使用Apple系統(tǒng)的時(shí)候,OpenGL庫(kù)是由Apple自身維護(hù)的。在Linux下,有顯卡生產(chǎn)商提供的OpenGL庫(kù),也有一些愛(ài)好者改編的版本。這也意味著任何時(shí)候OpenGL庫(kù)表現(xiàn)的行為與規(guī)范規(guī)定的不一致時(shí),基本都是庫(kù)的開(kāi)發(fā)者留下的bug。

概念解析

一、狀態(tài)機(jī)

OpenGL自身是一個(gè)巨大的狀態(tài)機(jī)(State Machine):一系列的變量描述OpenGL此刻應(yīng)當(dāng)如何運(yùn)行。OpenGL的狀態(tài)通常被稱為OpenGL上下文(Context)。我們通常使用如下途徑去更改OpenGL狀態(tài):設(shè)置選項(xiàng),操作緩沖。最后,我們使用當(dāng)前OpenGL上下文來(lái)渲染。

假設(shè)當(dāng)我們想告訴OpenGL去畫線段而不是三角形的時(shí)候,我們通過(guò)改變一些上下文變量來(lái)改變OpenGL狀態(tài),從而告訴OpenGL如何去繪圖。一旦我們改變了OpenGL的狀態(tài)為繪制線段,下一個(gè)繪制命令就會(huì)畫出線段而不是三角形。

當(dāng)使用OpenGL的時(shí)候,我們會(huì)遇到一些狀態(tài)設(shè)置函數(shù)(State-changing Function),這類函數(shù)將會(huì)改變上下文。以及狀態(tài)使用函數(shù)(State-using Function),這類函數(shù)會(huì)根據(jù)當(dāng)前OpenGL的狀態(tài)執(zhí)行一些操作。只要你記住OpenGL本質(zhì)上是個(gè)大狀態(tài)機(jī),就能更容易理解它的大部分特性。

二、上下文

在應(yīng)?程序調(diào)?任何OpenGL的指令之前,首先需要?jiǎng)?chuàng)建?個(gè)OpenGL的上下文。這個(gè)上下?是?個(gè)?常龐?的狀態(tài)機(jī),保存了了OpenGL中的各種狀態(tài),這也是OpenGL指令執(zhí)?的基礎(chǔ)。

OpenGL的函數(shù)不管在哪個(gè)語(yǔ)?中,都是類似C語(yǔ)?一樣的面向過(guò)程的函數(shù)。本質(zhì)上都是對(duì)OpenGL上下?這個(gè)龐?的狀態(tài)機(jī)中的某個(gè)狀態(tài)或者對(duì)象進(jìn)行操作。通過(guò)對(duì) OpenGL指令的封裝,可以將OpenGL的相關(guān)調(diào)?封裝成為?個(gè)?向?qū)ο蟮膱D形API。

由于OpenGL上下?是?個(gè)巨大的狀態(tài)機(jī),切換上下文往往會(huì)產(chǎn)生較?的開(kāi)銷,但是不同的繪制模塊,可能需要使?完全獨(dú)立的狀態(tài)管理。因此,可以在應(yīng)?程序中分別創(chuàng)建多個(gè)不同的上下文,在不同線程中使?不同的上下文,上下?之間共享紋理、緩沖區(qū)等資源。這樣的方案,會(huì)?反復(fù)切換上下?,或者?量修改渲染狀態(tài),更加合理高效。

重點(diǎn):

OpenGL指令執(zhí)?的基礎(chǔ),是?個(gè)?常龐?的狀態(tài)機(jī)。
OpenGL上下文切換開(kāi)銷大,雖然可能使用多個(gè)上下文,但上下文之間會(huì)共享紋理、緩沖區(qū)等資源。

三、渲染

將圖形/圖像數(shù)據(jù)轉(zhuǎn)換成3D空間圖像操作叫做渲染(Rendering)。

四、頂點(diǎn)數(shù)組 (VertexArray)

這頂點(diǎn)指的是我們?cè)诶L制一個(gè)圖形時(shí),它的頂點(diǎn)位置數(shù)據(jù),而這個(gè)數(shù)據(jù)可以直接存儲(chǔ)在數(shù)組中或者將其緩存到GPU內(nèi)存中

頂點(diǎn)數(shù)組指定每個(gè)頂點(diǎn)的屬性,是保存應(yīng)用程序地址空間的緩沖區(qū)。他們作為頂點(diǎn)緩沖對(duì)象的基礎(chǔ),提供指定頂點(diǎn)屬性數(shù)據(jù)的一個(gè)高效、靈活的手段

頂點(diǎn)數(shù)據(jù)就是圖像的輪廓。OpenGL中的圖像都是由圖元組成。在OpenGL ES中,有3種類型的圖元:點(diǎn)、線、三?形。
在調(diào)?繪制?法的時(shí)候,直接由內(nèi)存?zhèn)魅腠旤c(diǎn)數(shù)據(jù),也就是說(shuō)這部分?jǐn)?shù)據(jù)之前是存儲(chǔ)在內(nèi)存當(dāng)中的,被稱為頂點(diǎn)數(shù)組(VertexArray)。

五、頂點(diǎn)緩存區(qū)(VertexBuffer)

緩沖區(qū)保存在GPU內(nèi)存中, 可以在CPU不介入的情況下,完成數(shù)據(jù)操作。
性能更高的做法是,提前分配?塊顯存,將頂點(diǎn)數(shù)據(jù)預(yù)先傳?到顯存當(dāng)中。這部分的顯存,就被稱為頂點(diǎn)緩沖區(qū)(VertexBuffer)。

頂點(diǎn)數(shù)組指定的頂點(diǎn)數(shù)據(jù)保存在客戶內(nèi)存(CPU)中。在進(jìn)行g(shù)lDrawArrays或者glDrawElements等繪圖調(diào)用時(shí),這些數(shù)據(jù)必須同客戶內(nèi)存復(fù)制到圖形內(nèi)存。

沒(méi)必要每次繪圖時(shí)都復(fù)制頂點(diǎn)數(shù)據(jù),而是在圖形內(nèi)存中緩存這些數(shù)據(jù),這樣可以顯著改善渲染性能,也可以降低內(nèi)存帶寬和電力消耗需求。這就是頂點(diǎn)緩沖區(qū)對(duì)象發(fā)揮作用的地方

六、位圖(OpenGL 也稱為紋理)

位圖圖像(bitmap),亦稱為點(diǎn)陣圖像柵格圖像,是由稱作像素(圖片元素)的單個(gè)點(diǎn)組成的。這些點(diǎn)可以進(jìn)行不同的排列和染色以構(gòu)成圖樣。當(dāng)放大位圖時(shí),可以看見(jiàn)賴以構(gòu)成整個(gè)圖像的無(wú)數(shù)單個(gè)方塊。擴(kuò)大位圖尺寸的效果是增大單個(gè)像素,從而使線條和形狀顯得參差不齊。然而,如果從稍遠(yuǎn)的位置觀看它,位圖圖像的顏色和形狀又顯得是連續(xù)的。用數(shù)碼相機(jī)拍攝的照片、掃描儀掃描的圖片以及計(jì)算機(jī)截屏圖等都屬于位圖。位圖的特點(diǎn)是可以表現(xiàn)色彩的變化和顏色的細(xì)微過(guò)渡,產(chǎn)生逼真的效果,缺點(diǎn)是在保存時(shí)需要記錄每一個(gè)像素的位置和顏色值,占用較大的存儲(chǔ)空間。

七、管線

在OpenGL下渲染圖形,就會(huì)經(jīng)歷?個(gè)?個(gè)的節(jié)點(diǎn)。而這樣的操作可以理理解管線。就像一個(gè)流?線,任務(wù)按照先后順序依次執(zhí)行。管線是?個(gè)抽象的概念,之所以稱之為管線是因?yàn)轱@卡在處理數(shù)據(jù)的時(shí)候是按照一個(gè)固定的順序來(lái)的,而且嚴(yán)格按照這個(gè)順序。

八、固定管線 和 可編程管線

在早期的OpenGL版本,封裝了多種著色器程序塊,內(nèi)置了一段包含了光照、坐標(biāo)變換、裁剪等諸多功能的固定shader程序來(lái)完成。來(lái)幫助開(kāi)發(fā)者來(lái)完成圖形的渲染。開(kāi)發(fā)者只需要傳入相應(yīng)的參數(shù),就能快速完成圖形的渲染。類似于iOS開(kāi)發(fā)會(huì)封裝很多API,而我們只需要調(diào)?,就可以實(shí)現(xiàn)功能,不需要關(guān)注底層實(shí)現(xiàn)原理。
但是由于OpenGL的使?場(chǎng)景?常豐富,固定管線或存儲(chǔ)著?器?法完成每一 個(gè)業(yè)務(wù),這時(shí)將相關(guān)部分開(kāi)放成可編程。

九、著色器(Shader)

著色器(Shader)是運(yùn)行在GPU上的小程序。這些小程序?yàn)閳D形渲染管線的某個(gè)特定部分而運(yùn)行。從基本意義上來(lái)說(shuō),著色器只是一種把輸入轉(zhuǎn)化為輸出的程序。著色器也是一種非常獨(dú)立的程序,因?yàn)樗鼈冎g不能相互通信;它們之間唯一的溝通只有通過(guò)輸入和輸出。

OpenGL在實(shí)際調(diào)?繪制函數(shù)之前,還需要指定?個(gè)由shader編譯成的著色器程序。常見(jiàn)的著?器主要有頂點(diǎn)著?器(VertexShader),?段著?器(FragmentShader)/像素著?器(PixelShader),幾何著?(GeometryShader),曲?細(xì)分著?器(TessellationShader)。片段著?器和像素著?器只是在OpenGL和DX中的不同叫法而已??上У氖?,直到OpenGL ES 3.0,OpenGL ES依然只?持頂點(diǎn)著?器和片段著?器這兩個(gè)最基礎(chǔ)的著?器。

OpenGL在處理理shader時(shí),和其他編譯器一樣。通過(guò)編譯、鏈接等步驟,?成了著?器程序(glProgram),著?器程序同時(shí)包含了頂點(diǎn)著?器和?段著?器的運(yùn)算邏輯。在OpenGL進(jìn)行繪制的時(shí)候,?先由頂點(diǎn)著?器對(duì)傳?的頂點(diǎn)數(shù)據(jù)進(jìn)?運(yùn)算。再通過(guò)圖元裝配,將頂點(diǎn)轉(zhuǎn)換為圖元。然后進(jìn)?光柵化,將圖元這種?量圖形,轉(zhuǎn)換為柵格化數(shù)據(jù)。最后,將柵格化數(shù)據(jù)傳入?段著?器中進(jìn)?運(yùn)算。?段著?器會(huì)對(duì)柵格化數(shù)據(jù)中的每一個(gè)像素進(jìn)行運(yùn)算,并決定像素的顏?。

十、頂點(diǎn)著色器(VertexShader)

頂點(diǎn)著色器對(duì)頂點(diǎn)實(shí)現(xiàn)了一種通用的可編程方法,它一般用來(lái)處理圖形每個(gè)頂點(diǎn)變換(旋轉(zhuǎn)/平移/投影等)
頂點(diǎn)著色器是OpenGL中用于計(jì)算頂點(diǎn)屬性的程序。每個(gè)頂點(diǎn)都會(huì)執(zhí)行依次頂點(diǎn)著色器,執(zhí)行順序是按照存儲(chǔ)在頂點(diǎn)數(shù)組的順序依次處理(一般是逆時(shí)針)。

十一、片元著色器(FragmentShader)/ 像素著?器(PixelShader)

片元著色器主要是對(duì)光柵化處理后生成的片元逐個(gè)進(jìn)行處理(并行)。接收頂點(diǎn)著色器輸出的值,需要傳入的數(shù)據(jù),以及它經(jīng)過(guò)變換矩陣后輸出值存儲(chǔ)位置。

十二、GLSL

GLSL著色語(yǔ)?是?來(lái)在OpenGL中著?編程的語(yǔ)?,是在圖形卡的GPU上執(zhí)?的。代替了固定的渲染管線的?部分,使渲染管線中不同層次具有可編程性。?如:視圖轉(zhuǎn)換、投影轉(zhuǎn)換等。GLSL(GL Shading Language)的著?器代碼分成2個(gè)部分: Vertex Shader(頂點(diǎn)著?器)和Fragment(?斷著?器)。

十三、光柵話(Rasterization)

光柵化(Rasterization)是把頂點(diǎn)數(shù)據(jù)轉(zhuǎn)換為片元的過(guò)程,具有將圖轉(zhuǎn)化為一個(gè)個(gè)柵格組成的圖象的作用,特點(diǎn)是每個(gè)元素對(duì)應(yīng)幀緩沖區(qū)中的一像素。

光柵化其實(shí)是一種將幾何圖元變?yōu)槎S圖像的過(guò)程。該過(guò)程包含了兩部分的工作。
第一部分工作:決定窗口坐標(biāo)中的哪些整型柵格區(qū)域被基本圖元占用
第二部分工作:分配一個(gè)顏色值和一個(gè)深度值到各個(gè)區(qū)域。光柵化過(guò)程產(chǎn)生的是片元

把物體的數(shù)學(xué)描述以及與物體相關(guān)的顏色信息轉(zhuǎn)換為屏幕上用于對(duì)應(yīng)位置的像素及用于填充像素的顏色,這個(gè)過(guò)程稱為光柵化,這是一個(gè)將模擬信號(hào)轉(zhuǎn)化為離散信號(hào)的過(guò)程

簡(jiǎn)而言之,光柵化階段繪制對(duì)應(yīng)的圖元(點(diǎn)、線、三角形),將圖元轉(zhuǎn)化為一組二維數(shù)組的過(guò)程,然后傳遞給片元著色器處理。這些二維數(shù)組代表屏幕上繪制的像素

十三、紋理

紋理可以理解為圖?。 在渲染圖形時(shí)需要在頂點(diǎn)圍成的區(qū)域中填充圖?,使得場(chǎng)景更加逼真。?這?使?的圖?,就是常說(shuō)的紋理。只是在OpenGL,我們更加習(xí)慣叫紋理,?不是圖?。

十四、混合(Blending)

Blend 混合是將源色和目標(biāo)色以某種方式混合生成特效的技術(shù)。混合常用來(lái)繪制透明或半透明的物體。

在混合中起關(guān)鍵作用的α值實(shí)際上是將源色和目標(biāo)色按給定比率進(jìn)行混合,以達(dá)到不同程度的透明。α值為0則完全透明,α值為1則完全不透明?;旌喜僮髦荒茉赗GBA模式下進(jìn)行,顏色索引模式下無(wú)法指定α值。物體的繪制順序會(huì)影響到OpenGL的混合處理。

十五、矩陣

變換矩陣(Transformation)

例如圖形想發(fā)?平移、縮放、旋轉(zhuǎn)等變換,就需要使用變換矩陣。

投影矩陣(Projection)

?于將3D坐標(biāo)轉(zhuǎn)換為?維屏幕坐標(biāo),實(shí)際線條也將在二維坐標(biāo)下進(jìn)行繪制。

十六、坐標(biāo)系

2D笛卡爾坐標(biāo)系
截屏2020-07-02下午10.09.22.png
3D笛卡爾坐標(biāo)系
截屏2020-07-02下午10.10.27.png

關(guān)于坐標(biāo)系后續(xù)會(huì)有一些單獨(dú)的介紹

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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