簡述
本文記錄我記錄我學(xué)習(xí) 坐標(biāo)體系和矩陣轉(zhuǎn)換的過程,加深學(xué)習(xí)便于后續(xù)查詢,可能有些描述不夠準(zhǔn)確,或者內(nèi)容不夠充實(shí),還請多多指正,共同學(xué)習(xí).
顏色
一個沒有Alpha通道的顏色可以用一個3維向量來表示 例如 glm::vec3(1.0,1.0,1.0); 表示白色.
在現(xiàn)實(shí)世界中,一個物體的顏色是它反射的顏色導(dǎo)致的, 例如我們將純紅光 照射在純綠物體上, 因?yàn)榧t光都被吸收,所以顯示為黑色.
將吸收反射的過程用向量表示出來
glm::vec3 lightColor(0.0f, 1.0f, 0.0f); //綠色光源向量
glm::vec3 objColor(1.0f, 0.5f, 0.31f); //物體色
glm::vec3 result = lightColor * objColor; // 光源下顏色(0.0f, 0.5f, 0.0f);
馮氏光照模型
馮氏光照模型的主要結(jié)構(gòu)由3個分量組成 環(huán)境(Ambient) 漫反射(Diffuse) 鏡面(Specular)
環(huán)境光照
在現(xiàn)實(shí)環(huán)境下 即使在黑暗的情況下,世界上通常也會有一些光亮(如 月光), 而且即使物體不朝光源的,也會因?yàn)?其他物體的反射,使陰面有光,這種情況下 就要使用 全局照明算法 這種算法開銷大而且復(fù)雜,以后在研究 先實(shí)現(xiàn)簡單的 環(huán)境光照
所以給物體一個環(huán)境光照量,讓物體始終有一點(diǎn)顏色. 在著色器中表現(xiàn)如下
void main()
{
float ambientStrength = 0.1; //至少有%10的光找到物體所有面
vec3 ambient = ambientStrength * lightColor;
vec3 result = ambient * objectColor;
FragColor = vec4(result, 1.0);
}
漫反射光照
模擬光源對物體的方向性影響(Directional Impact)。它是馮氏光照模型中視覺上最顯著的分量。物體的某一部分越是正對著光源,它就會越亮. 也就是光線和物體表面法線的夾角越小,光線對物體的影響就越大.
這樣就可以利用夾角的cos值作為參考,來修改光線對物體的影響.
片段著色器重相關(guān)實(shí)現(xiàn)
uniform vec3 lightColor; //光源色
uniform vec3 lightPo; //光源位置
uniform vec3 objectColor; //物體色
uniform vec3 viewPo; //物體位置
in vec3 outNormal; //傳入當(dāng)前頂點(diǎn)平面的法向量
vec3 norm = normalize(outNormal); //確保法線為單位向量
vec3 lightDir = normalize(lightPo - FragPo); //頂點(diǎn)指向光源 單位向量
float diff = max(dot(norm,lightDir),0.0); //得到兩向量的cos值 小于0則則為0
vec3 diffuse = diff * lightColor; //得到漫反射收的光源向量
法向量變換
對于法向量,它是一個方向向量,不會因?yàn)槲矬w的移動而發(fā)生變化,所以在對法向量 進(jìn)行矩陣處理時,要消除矩陣中位移部分對其造成的影響. 因此位移使用3x3矩陣 或者 將 法向量的w分量設(shè)置為0.0;
另外,若矩陣對物體進(jìn)行里不等比縮放時候,會導(dǎo)致法向量不在垂直于物體表面.
這種情況 則需要使用法線矩陣 來移除對法向量錯誤縮放的影響. 法線矩陣由逆矩陣和轉(zhuǎn)置矩陣 組成.
glm::transpose(glm::inverse(model)); //法線矩陣的計算
mat3(transpose(inverse(model))) * aNormal; //著色器語言的使用 使用3x3矩陣 能夠與 vec3法向量計算
鏡面光照
模擬有光澤物體上面出現(xiàn)的亮點(diǎn)郎楼。鏡面光照的顏色相比于物體的顏色會更傾向于光的顏色。鏡面光照的計算依賴于 觀察的視角, 若視線與光源在物體的反射線的夾角越小 則鏡面光照效果越好.
計算他 我們需要 觀察者位置.鏡面強(qiáng)度(鏡面效果強(qiáng)弱)
float specularStrength = 0.5; //鏡面強(qiáng)度
vec3 viewDir = normalize(viewPo - FragPo); //頂點(diǎn)指向觀察點(diǎn)的單位向量
vec3 reflectDir = reflect(-lightDir,outNormal); //求得光線 在 頂點(diǎn)的反射線(傳入光源指向頂點(diǎn)的向量)
float spec = pow(max(dot(viewDir, reflectDir),0.0),256.0);
// 求得夾角cos值 取256次冪 注意 pow(float,float)函數(shù)參數(shù)類型
vec3 specular = specularStrength * spec * lightColor;
256 表示高光的反光度, 反光度越高,發(fā)射光的能力越強(qiáng),散射越少 高光點(diǎn)越小
最后綜合
vec3 res =(ambientStrength + diffuse + specular) * objectColor;
效果圖: 白色方塊為白色光源