要做出變換效果,其實(shí)就是玩數(shù)據(jù),而數(shù)據(jù)的來(lái)源及數(shù)據(jù)的一些變量都依賴glsl,所以需要先系統(tǒng)的學(xué)習(xí)下。其實(shí)glsl一開(kāi)始是配合opengl專屬的。
為了看明白glsl,首先要學(xué)習(xí)語(yǔ)法,網(wǎng)上很多。然后就是理解這些變量的作用及使用的階段。我先進(jìn)行了第一輪基礎(chǔ)學(xué)習(xí)
1.為什么要光柵化?
圖形管線的輸入是圖元頂點(diǎn),輸出的則是像素(pixel),這個(gè)步驟其中還有個(gè)中間產(chǎn)物叫做片段(fragment),一個(gè)片段相應(yīng)一個(gè)像素,但片段比像素多了用于計(jì)算的屬性,比如:深度值和法向量。通過(guò)片段能夠計(jì)算出終于將要生成像素的顏色值,我們把輸入頂點(diǎn)計(jì)算片段的過(guò)程叫作光柵化。為什么要光柵化?由于要生成用以計(jì)算終于顏色的片段。
2.光柵化發(fā)生在哪一步?

光柵化函數(shù)也須要輸入和輸出,從上圖來(lái)看函數(shù)的輸入就是組成圖元的頂點(diǎn)結(jié)構(gòu),輸出的就是片段結(jié)構(gòu)
既然光柵化是在頂點(diǎn)處理程序以后發(fā)生的步驟,那么輸入的頂點(diǎn)結(jié)構(gòu)是經(jīng)過(guò)頂點(diǎn)處理以后的,也就是進(jìn)行過(guò)mvp變換,乘以透視矩陣之后的頂點(diǎn),注意:這步還沒(méi)有做透視除法,光柵化插值發(fā)生在裁剪空間,絕不是標(biāo)準(zhǔn)化空間,所以頂點(diǎn)位置是四維齊次坐標(biāo)不是三維坐標(biāo)!
3.著色器(Shader)作用?
畫(huà)畫(huà)的時(shí)候我們經(jīng)常有這么一個(gè)過(guò)程:先打線稿,再上色。著色器就是用來(lái)做這個(gè)工作的。
通常著色器分兩種:
1頂點(diǎn)著色器(vertex shader)這個(gè)是告訴電腦如何打線稿的——如何處理頂點(diǎn)、法線等的數(shù)據(jù)的小程序。
2片面著色器(fragment shader)這個(gè)是告訴電腦如何上色的——如何處理光、陰影、遮擋、環(huán)境等等對(duì)物體表面的影響,最終生成一副圖像的小程序。
采用了這兩種著色器小程序 的 數(shù)據(jù)傳輸處理計(jì)算的渲染過(guò)程,稱之為 可編程管線。
4. 法向量有什么用?
法向量主要影響光照
-
光照類型包括:環(huán)境光(Ambient light),方向光(Directional light),點(diǎn)光(Point light),聚光(Spot light)。
2)根據(jù)把光線在物體表面發(fā)射的方式分為兩類:漫反射(Diffuse reflection),鏡面反射(Specular reflection)。
法向量:
我們用法線向量來(lái)表示平面朝向,在具體實(shí)現(xiàn)中,每個(gè)點(diǎn)都會(huì)有一個(gè)法線向量。所謂法線向量就是垂直于平面的一個(gè)三維向量。
法向量.png
圖中展示了兩種法線向量的表示方法,左邊是每個(gè)多邊形的每個(gè)點(diǎn)有一個(gè)法線向量,右邊是每個(gè)點(diǎn)有一個(gè)法線向量,共享點(diǎn)的法線向量是這個(gè)點(diǎn)在所有平面上的法線向量之和。法線向量應(yīng)該總是被規(guī)范化成單位向量。本文的例子中使用的是左邊的方式。
需要注意的是,法線向量只代表方向,不代表位置信息,所以法向向量盡量用歸一化的數(shù)據(jù)。如下圖
法向量2.png
先分析頂點(diǎn)著色器程序:
shader代碼分析.png
第二行代碼 光照強(qiáng)度 = 法向量 * 反向歸化后的光源向量 。從數(shù)學(xué)公式來(lái)說(shuō),光照強(qiáng)度就是法向量與反向歸化后的光源向量的點(diǎn)積。
得到光照強(qiáng)度之后,第三行代碼 vec4(_lightColor * lightStrength + _lightDiffuse, 1),光照強(qiáng)度*環(huán)境光色值,這時(shí)其實(shí)已經(jīng)具備光照效果,加上漫反射_lightDiffuse是防止沒(méi)有光照強(qiáng)度的地方會(huì)完全變黑,那如實(shí)際情況不相符。漫反射還有很多內(nèi)容可以擴(kuò)充,譬如根據(jù)紋理的材質(zhì)進(jìn)行漫反射的光強(qiáng)度計(jì)算,添加自己的色值等等。
5. 深度值有什么用?
簡(jiǎn)單理解就是通過(guò)深度測(cè)試然后在后面的圖像被遮擋,這樣看起來(lái)的3D圖形就是真實(shí)的。有了距離那么還可以處理隱形。
1)一般情況下,計(jì)算機(jī)在渲染圖像的過(guò)程中會(huì)同時(shí)產(chǎn)生一張深度圖,這是一張只有一個(gè)通道的圖像,代表了物體距離攝像機(jī)的距離。越亮的地方代表離攝像機(jī)的距離越近,越暗的地方代表離攝像機(jī)的距離越遠(yuǎn)。有了這張圖,在渲染物體時(shí),先把即將輸出的像素的深度值(深度圖中這個(gè)像素的顏色)與當(dāng)前深度緩沖區(qū)(當(dāng)前深度圖)中的像素顏色進(jìn)行比較,如果這里已經(jīng)有一個(gè)比要渲染的像素還要離攝像機(jī)近的像素存在,就拋棄掉將要渲染的像素;反之就覆蓋掉原來(lái)的。這就是被稱為“深度測(cè)試”(depth test)的操作。
2)有了這張深度圖,我們其實(shí)不僅能處理遮擋,還能夠渲染陰影,陰影就是從光源的位置看來(lái),各個(gè)物體之間的遮擋關(guān)系;被遮擋的地方涂上陰影,沒(méi)被遮擋的地方該咋樣咋樣。也就是說(shuō),我們需要讓攝像機(jī)的位置朝向等與光源一致,然后渲染一張圖像,取出它的深度圖(事實(shí)上,我們只需要深度數(shù)據(jù),所以我們可以只渲染深度來(lái)節(jié)約開(kāi)銷)。然后把攝像機(jī)移回原來(lái)的位置,再進(jìn)行渲染。在渲染時(shí),對(duì)渲染的每個(gè)像素,找到它在光源處那張深度圖中的位置,并計(jì)算出它離光源的距離;然后把光源深度圖中的數(shù)據(jù)和它離光源的距離數(shù)據(jù)比較,就可以判斷出它是不是應(yīng)該被涂上陰影了。
6. obj模型文件
在3d圖形處理中,一個(gè)模型(model)通常由一個(gè)或者多個(gè)Mesh(網(wǎng)格)組成,一個(gè)Mesh是可繪制的獨(dú)立實(shí)體。例如復(fù)雜的人物模型,可以分別劃分為頭部,四肢,服飾,武器等各個(gè)部分來(lái)建模,這些Mesh組合在一起最終形成人物模型。
Mesh由頂點(diǎn)、邊、面Faces組成的,它包含繪制所需的數(shù)據(jù),例如頂點(diǎn)位置、紋理坐標(biāo)、法向量,材質(zhì)屬性等內(nèi)容,它是OpenGL用來(lái)繪制的最小實(shí)體。Mesh的概念示意如下圖所示

對(duì)這個(gè)文本格式做一個(gè)簡(jiǎn)要說(shuō)明:
以#開(kāi)始的行為注釋行 usemtl和mtllib表示的材質(zhì)相關(guān)數(shù)據(jù),解析材質(zhì)數(shù)據(jù)稍微繁瑣,本節(jié)我們只是為了說(shuō)明加載模型的原理,不做討論。 o 引入一個(gè)新的object v 表示頂點(diǎn)位置 vt 表示頂點(diǎn)紋理坐標(biāo) vn 表示頂點(diǎn)法向量 f 表示一個(gè)面,面使用1/2/8這樣格式,表示頂點(diǎn)位置/紋理坐標(biāo)/法向量的索引,這里索引的是前面用v,vt,vn定義的數(shù)據(jù) 注意這里Obj的索引是從1開(kāi)始的,而不是0
參考文檔
https://www.cnblogs.com/kex1n/p/3941680.html
https://www.cnblogs.com/betairy-linkzeldagg/p/5445613.html
https://blog.csdn.net/shareus/article/details/80007236
https://www.2cto.com/kf/201607/525593.html


