通過(guò)OpenGL理解前端渲染原理(1)
一、OpenGL
OpenGL,是一套繪制3D圖形的API,當(dāng)然它也可以用來(lái)繪制2D的物體。OpenGL有一大套可以用來(lái)操作模型和圖片的函數(shù),通常編寫(xiě)OpenGL庫(kù)的人是顯卡的制造者。我們買(mǎi)的顯卡都支持特定版本的OpenGL。
下圖是用OpenGL做的旋轉(zhuǎn)的立方體。
2.1 渲染管道
在OpenGL中,所有東西都在一個(gè)3D的空間里,而我們的屏幕和窗口都是2D的,所以O(shè)penGL需要將3D的坐標(biāo)轉(zhuǎn)換成2D的坐標(biāo),做這件事的是OpenGL中的渲染管道(graphics pipeline)。
渲染管道可以分成兩大部分:第一部分將3D坐標(biāo)轉(zhuǎn)換成2D坐標(biāo);第二部分把2D的坐標(biāo)轉(zhuǎn)換成實(shí)際的像素。
2.2 著色器
通常來(lái)說(shuō),渲染管道把一組3D坐標(biāo)轉(zhuǎn)換成屏幕上帶有顏色的2D像素需要經(jīng)過(guò)很多步。上一步的輸出作為下一步的輸入,所有步驟都是高度專(zhuān)一的,每步都有一個(gè)特定的函數(shù),且可以很容易地并發(fā)執(zhí)行。顯卡有數(shù)千個(gè)處理核心來(lái)快速處理渲染管道中的數(shù)據(jù),而這些是在每個(gè)步驟中通過(guò)運(yùn)行在GPU上的多個(gè)小程序來(lái)處理的,這些小的程序被稱(chēng)之為程序著色器(shader)。
其中的一些著色器是可以配置的,開(kāi)發(fā)者可以根據(jù)需求配置自己的著色器去替代已經(jīng)存在的那些,這就讓我們能夠更自由和細(xì)粒度地控制渲染的過(guò)程。同時(shí),因?yàn)樗鼈冞\(yùn)行在GPU上,又給我們保留了珍貴的GPU時(shí)間,在平時(shí)的開(kāi)發(fā)中,我們也要充分利用GPU渲染來(lái)提高軟件性能。
著色器通常使用GLSL來(lái)寫(xiě),全稱(chēng)是OpenGL Shading Language。
2.3 舉個(gè)例子
下圖展示了一個(gè)抽象的渲染管線中的步驟,其中藍(lán)色部分是我們可以注入自己的著色器。
通過(guò)上圖我們發(fā)現(xiàn),要把頂點(diǎn)數(shù)據(jù)轉(zhuǎn)換成全渲染的像素要經(jīng)過(guò)很多步,接下來(lái)我們對(duì)每一個(gè)步驟和代碼進(jìn)行簡(jiǎn)單的解釋。
我們?cè)阡秩竟芫€中傳入一組可以組成三角形的3D坐標(biāo)數(shù)據(jù),這組數(shù)據(jù)即頂點(diǎn)數(shù)據(jù)。頂點(diǎn)數(shù)據(jù)是頂點(diǎn)的集合,而一個(gè)頂點(diǎn)是一個(gè)3D坐標(biāo)的集合。
渲染管線的第一步是頂點(diǎn)著色器(Vertex Shader)。我們這里傳入的是一個(gè)簡(jiǎn)單的頂點(diǎn),頂點(diǎn)著色器可以讓我們做一些基礎(chǔ)的處理操作,比如頂點(diǎn)的屬性。
在初始裝配階段,也就是Shape Assembly階段,從頂點(diǎn)著色器中輸出的頂點(diǎn)會(huì)形成一個(gè)原始的形狀。本例中,輸出的頂點(diǎn)形成的是一個(gè)三角形。
從初始裝配階段到geometry shader階段,我們可以通過(guò)發(fā)散其他頂點(diǎn)來(lái)形成新的圖形,本例中形成了第二個(gè)三角形。
在Tessellation Shader階段,可以把上一階段給出的原型圖再分割成若干個(gè)小的原型圖。本例中,可以形成更多的三角形來(lái)創(chuàng)造一個(gè)更加平坦、順滑的環(huán)境。這么說(shuō)可能難以理解,我們結(jié)合下圖來(lái)進(jìn)一步闡述,這就是細(xì)分曲面著色器的作用。
細(xì)分曲面著色器的下一階段是光柵化階段(Rasterzation stage),在這一階段會(huì)對(duì)最終的原型和呈現(xiàn)在屏幕上的對(duì)應(yīng)像素做一個(gè)映射,形成fragment,供下一階段的fragment shader使用。
Fragment shader最主要的使命是計(jì)算出一個(gè)像素的最終顏色,在這個(gè)階段我們可以使用OpenGL中一些高級(jí)的特效。通常fragment shader會(huì)包含3D界面的多個(gè)數(shù)據(jù),包括燈光、陰影、顏色等等。
當(dāng)所有對(duì)應(yīng)的顏色都確定以后,最終的原型將會(huì)被傳入最后一個(gè)步驟,我們稱(chēng)之為Alpha test and blending階段。這個(gè)階段會(huì)判斷相應(yīng)的深度,比如一個(gè)物體可能在另一個(gè)物體的后面,那它可能采用其他的顏色;或者如果該物體被遮擋,可能會(huì)被裁掉。
如上文所述,我們可以看到整個(gè)渲染管線的步驟和邏輯是十分復(fù)雜的,這其中包含了很多個(gè)可以改變的步驟,但我們一般只操作Vertex Shader 和 fragment shader,其他的著色器我們會(huì)直接采用默認(rèn)的。在實(shí)際的OpenGL編程中,我們至少需要定義一個(gè)Vertex Shader和Fragment shader。(需要說(shuō)明的是,OpenGL 3.1之前的版本包含了固定管線,從3.1版本開(kāi)始,固定管線從核心中刪掉了,因此我們必須使用著色器去工作)。
本文為該系列文章的第一篇,先簡(jiǎn)單介紹OpenGL的一些原理,后續(xù)文章中會(huì)添加新的代碼分析,包括著色器(Shader)、紋理(Textture)、變形(transformation)、坐標(biāo)系統(tǒng)(Coordinate systems)、相機(jī)(Camera)等。
【本文是51CTO專(zhuān)欄機(jī)構(gòu)宜信技術(shù)學(xué)院的原創(chuàng)文章,微信公眾號(hào)“宜信技術(shù)學(xué)院( id: CE_TECH)”】